Discussão do artigo "Implementação do modelo de tabela em MQL5: Aplicação do conto MVC"

 

Novo artigo Implementação do modelo de tabela em MQL5: Aplicação do conto MVC foi publicado:

Neste artigo, analisaremos o desenvolvimento do modelo de tabela na linguagem MQL5, usando o conceito arquitetônico MVC (Model-View-Controller), que separa a lógica dos dados, a apresentação e o controle, o que ajuda a criar um código estruturado, flexível e escalável. Examinaremos a implementação das classes para construir o modelo de tabela, incluindo o uso de listas ligadas para armazenar dados.

Na programação, a arquitetura de uma aplicação desempenha um papel importante para garantir confiabilidade, escalabilidade e facilidade de manutenção. Uma das abordagens que ajuda a alcançar esses objetivos é o uso do padrão arquitetônico MVC (Model-View-Controller).

A concepção MVC permite dividir a aplicação em três componentes inter-relacionados: o modelo (gerenciamento de dados e lógica), a visualização (exibição dos dados) e o controlador (tratamento das ações do usuário). Essa divisão simplifica o desenvolvimento, o teste e a manutenção do código, tornando-o mais estruturado e flexível.

Neste artigo, veremos como aplicar os princípios do MVC para implementar o modelo de tabela na linguagem MQL5. As tabelas são uma ferramenta importante para armazenar, processar e exibir dados, e sua organização correta pode simplificar significativamente o trabalho com as informações. Criaremos classes para trabalhar com tabelas: células da tabela, linhas e o modelo de tabela. Para armazenar as células nas linhas e as linhas no modelo de tabela, usaremos listas ligadas da Biblioteca Padrão do MQL5, que permitem guardar e utilizar dados de forma eficiente.


Autor: Artyom Trishkin

 

Olá, Artem.

Aqui está uma pergunta:

Seu código lê o tipo de objeto.

      //--- Ler tipo de objeto
      this.m_element_type=(ENUM_OBJECT_TYPE)::FileReadInteger(file_handle,INT_VALUE);

Mas ele não é verificado como no SB

bool CList::Load(const int file_handle)
  {
   uint     i,num;
   CObject *node;
   bool     result=true;
//--- verificação
   if(file_handle==INVALID_HANDLE)
      return(false);
//--- lendo e verificando o marcador de início - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFF
   if(FileReadLong(file_handle)!=-1)
      return(false);
//--- leitura e verificação do tipo
   if(FileReadInteger(file_handle,INT_VALUE)!=Type())
      return(false);
//--- ler o tamanho da lista
   num=FileReadInteger(file_handle,INT_VALUE);
//--- criação sequencial de itens de lista usando a chamada do método Load()
   Clear();
   for(i=0;i<num;i++)
     {
      node=CreateElement();
      if(node==NULL)
         return(false);
      Add(node);
      result&=node.Load(file_handle);
     }
//--- bem-sucedido
   return(result);
  }

Como podemos ver, o método Type() simplesmente retorna um valor

   virtual int       Type(void) const { return(0x7779); }

Qual é a necessidade dessa verificação no SB? É realmente suficiente ler o tipo e criar um elemento do tipo correspondente?

 
Alexey Viktorov #:
this.m_element_type=(ENUM_OBJECT_TYPE)::FileReadInteger(file_handle,INT_VALUE);

Bem, se o tipo não for lido, o que acontecerá em seguida?

Aqui está o código:

//--- Recrie sequencialmente os itens da lista chamando o método Load() dos objetos de nó
   this.Clear();
   for(uint i=0; i<num; i++)
     {
      //--- Ler e verificar o marcador de início dos dados do objeto - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFF
      if(::FileReadLong(file_handle)!=MARKER_START_DATA)
         return false;
      //--- Ler tipo de objeto
      this.m_element_type=(ENUM_OBJECT_TYPE)::FileReadInteger(file_handle,INT_VALUE);
      node=this.CreateElement();
      if(node==NULL)
         return false;
      this.Add(node);
      //--- Agora o ponteiro do arquivo é deslocado em relação ao início do marcador de objeto em 12 bytes (8 - marcador, 4 - tipo).
      //--- Vamos colocar um ponteiro no início dos dados do objeto e carregar as propriedades do objeto do arquivo usando o método Load() do elemento do nó.
      if(!::FileSeek(file_handle,-12,SEEK_CUR))
         return false;
      result &=node.Load(file_handle);
     }
//--- Resultado
   return result;
  }
//+------------------------------------------------------------------+
//| Método para criar um item de lista|
//+------------------------------------------------------------------+
CObject *CListObj::CreateElement(void)
  {
//--- Dependendo do tipo de objeto em m_element_type, crie um novo objeto
   switch(this.m_element_type)
     {
      case OBJECT_TYPE_TABLE_CELL   :  return new CTableCell();
      case OBJECT_TYPE_TABLE_ROW    :  return new CTableRow();
      case OBJECT_TYPE_TABLE_MODEL  :  return new CTableModel();
      default                       :  return NULL;
     }
  }

Ler o tipo do objeto em uma variável. Em seguida, tentamos criar esse objeto em CreateElement(), e há casos. O que esse método retornará se o tipo do objeto que está sendo criado não for lido do arquivo?

 
Artyom Trishkin #:

Bem, se o tipo não for lido, o que acontecerá em seguida?

Aqui está o código:

Lemos o tipo do objeto em uma variável. Em seguida, tentamos criar esse objeto em CreateElement(), e há casos. O que esse método retornará se o tipo do objeto que está sendo criado não for lido do arquivo?

Artem, não é disso que estou falando. Estou falando do fato de que há uma verificação de tipo no SB. Exatamente a verificação.

//--- leitura e verificação do tipo
   if(FileReadInteger(file_handle,INT_VALUE)!= Type())
      return(false);

O tipo lido do arquivo corresponde ao tipo do método Type()Read e daverificação de tipo? É assim que ele é traduzido?
E você simplesmente lê o tipo sem verificá-lo.

Portanto, a pergunta é: Qual é o significado profundo dessa verificação?

 
Alexey Viktorov #:
Aqui está a pergunta: Qual é o significado profundo dessa verificação?

Quando uma classe de SomeObject é carregada de um arquivo chamando o método Load() desse mesmo SomeObject, ele verifica "eu realmente me li do arquivo?" (é isso que você está perguntando). Se não, isso significa que algo deu errado e, portanto, não faz sentido continuar carregando.

O que tenho aqui é uma LISTA (CListObj) lendo um tipo de objeto de um arquivo. A lista não sabe o que está lá (qual objeto) no arquivo. Mas ela precisa conhecer esse tipo de objeto para criá-lo em seu método CreateElement(). É por isso que ela não verifica o tipo do objeto carregado do arquivo. Afinal de contas, haverá uma comparação com Type(), que nesse método retorna o tipo de uma lista, não de um objeto.

 
Artyom Trishkin #:

Quando uma classe de SomeObject é carregada de um arquivo por meio da chamada do método Load() desse mesmo SomeObject, ele verifica "eu realmente me li do arquivo?" (é isso que você está perguntando). Se não, isso significa que algo deu errado e, portanto, não há motivo para continuar o carregamento.

O que tenho aqui é uma LISTA (CListObj) lendo um tipo de objeto de um arquivo. A lista não sabe o que está lá (qual objeto) no arquivo. Mas ela precisa conhecer esse tipo de objeto para criá-lo em seu método CreateElement(). É por isso que ela não verifica o tipo do objeto carregado do arquivo. Afinal de contas, haverá uma comparação com Type(), que nesse método retorna o tipo de uma lista, não de um objeto.

Obrigado, já resolvi, estou entendendo.

 

Eu li e depois reli novamente.

é algo diferente de um "modelo" em MVC. Algum ListStorage, por exemplo

 
Vamos direto ao ponto. Guarde suas opiniões para si mesmo.
 
Gostaria de saber. É possível obter algum análogo dos dataframes do Python e do R dessa forma? Essas são tabelas em que colunas diferentes podem conter dados de tipos diferentes (de um conjunto limitado de tipos, mas incluindo string).
 
Aleksey Nikolayev #:
Gostaria de saber. É possível obter algum análogo dos dataframes do Python e do R dessa forma? Essas tabelas são aquelas em que colunas diferentes podem conter dados de tipos diferentes (de um conjunto limitado de tipos, mas incluindo string).

É possível. Se estivermos falando de colunas diferentes de uma tabela, então, na implementação descrita, cada célula da tabela pode ter um tipo de dados diferente.