Discussione sull’articolo "Implementazione di un modello di tabella in MQL5: Applicazione del concetto MVC"

 

Il nuovo articolo Implementazione di un modello di tabella in MQL5: Applicazione del concetto MVC è stato pubblicato:

In questo articolo, esaminiamo il processo di sviluppo di un modello di tabella in MQL5 utilizzando il modello architettonico MVC (Model-View-Controller) per separare la logica dei dati, la presentazione e il controllo, consentendo un codice strutturato, flessibile e scalabile. Consideriamo l'implementazione di classi per la costruzione di un modello di tabella, compreso l'uso di liste collegate per la memorizzazione dei dati.

Nella programmazione, l'architettura delle applicazioni svolge un ruolo fondamentale nel garantire affidabilità, scalabilità e facilità di supporto. Uno degli approcci che aiuta a raggiungere tali obiettivi è quello di sfruttare il modello di architettura chiamato MVC (Model-View-Controller).

Il concetto MVC consente di dividere un'applicazione in tre componenti interconnessi: model (gestione dei dati e della logica), view (visualizzazione dei dati) e controller (elaborazione delle azioni dell'utente). Questa separazione semplifica lo sviluppo, il test e la manutenzione del codice, rendendolo più strutturato e flessibile.

In questo articolo, consideriamo come applicare i principi MVC per implementare un modello di tabella nel linguaggio MQL5. Le tabelle sono uno strumento importante per l'archiviazione, l'elaborazione e la visualizzazione dei dati e la loro corretta organizzazione può facilitare il lavoro con le informazioni. Creeremo classi per lavorare con le tabelle: celle, righe e un modello di tabella. Per memorizzare le celle all'interno delle righe e le righe all'interno del modello di tabella, utilizzeremo le classi degli elenchi collegati della Libreria Standard MQL5, che consentono di memorizzare e utilizzare i dati in modo efficiente.


Autore: Artyom Trishkin

 

Ciao, Artem.

Ecco una domanda:

Il tuo codice legge il tipo di oggetto.

      //--- Leggere il tipo di oggetto
      this.m_element_type=(ENUM_OBJECT_TYPE)::FileReadInteger(file_handle,INT_VALUE);

Ma non viene controllato come in SB

bool CList::Load(const int file_handle)
  {
   uint     i,num;
   CObject *node;
   bool     result=true;
//--- controllo
   if(file_handle==INVALID_HANDLE)
      return(false);
//--- lettura e controllo del marcatore di inizio - 0xFFFFFFFFFFFFFFFFFFF
   if(FileReadLong(file_handle)!=-1)
      return(false);
//--- lettura e controllo del tipo
   if(FileReadInteger(file_handle,INT_VALUE)!=Type())
      return(false);
//--- leggere la dimensione dell'elenco
   num=FileReadInteger(file_handle,INT_VALUE);
//--- creazione sequenziale degli elementi dell'elenco tramite la chiamata al metodo Load()
   Clear();
   for(i=0;i<num;i++)
     {
      node=CreateElement();
      if(node==NULL)
         return(false);
      Add(node);
      result&=node.Load(file_handle);
     }
//--- successo
   return(result);
  }

Come possiamo vedere, il metodo Type() restituisce semplicemente un valore.

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

Qual è la necessità di un tale controllo in SB? È davvero sufficiente leggere il tipo e creare un elemento del tipo corrispondente?

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

Se il tipo non viene letto, cosa fare?

Ecco il codice:

//--- Ricreare sequenzialmente gli elementi dell'elenco richiamando il metodo Load() degli oggetti nodo
   this.Clear();
   for(uint i=0; i<num; i++)
     {
      //--- Leggere e controllare il marcatore di inizio dei dati dell'oggetto - 0xFFFFFFFFFFFFFFFFFFFFF
      if(::FileReadLong(file_handle)!=MARKER_START_DATA)
         return false;
      //--- Leggere il tipo di oggetto
      this.m_element_type=(ENUM_OBJECT_TYPE)::FileReadInteger(file_handle,INT_VALUE);
      node=this.CreateElement();
      if(node==NULL)
         return false;
      this.Add(node);
      //--- Ora il puntatore al file è spostato rispetto all'inizio del marcatore dell'oggetto di 12 byte (8 - marcatore, 4 - tipo).
      //--- Mettiamo un puntatore all'inizio dei dati dell'oggetto e carichiamo le proprietà dell'oggetto dal file, usando il metodo Load() dell'elemento nodo.
      if(!::FileSeek(file_handle,-12,SEEK_CUR))
         return false;
      result &=node.Load(file_handle);
     }
//--- Risultato
   return result;
  }
//+------------------------------------------------------------------+
//| Metodo per creare un elemento dell'elenco|
//+------------------------------------------------------------------+
CObject *CListObj::CreateElement(void)
  {
//--- A seconda del tipo di oggetto in m_element_type, creare un nuovo oggetto
   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;
     }
  }

Leggere il tipo dell'oggetto in una variabile. Poi si cerca di creare l'oggetto con CreateElement() e si verificano dei casi. Cosa restituirà questo metodo se il tipo dell'oggetto creato non viene letto dal file?

 
Artyom Trishkin #:

Se il tipo non viene letto, che fare?

Ecco il codice:

Leggiamo il tipo dell'oggetto in una variabile. Poi proviamo a creare l'oggetto con CreateElement() e si verificano dei casi. Cosa restituirà questo metodo se il tipo dell'oggetto creato non viene letto dal file?

Artem, non è di questo che sto parlando. Sto parlando del fatto che c'è un controllo di tipo in SB. Esattamente il controllo.

//--- lettura e controllo del tipo
   if(FileReadInteger(file_handle,INT_VALUE)!= Type())
      return(false);

Il tipo letto dal file corrisponde al tipo del metodo Type()Read and typecheck. È così che si traduce?
E si legge semplicemente il tipo senza controllarlo.

Quindi la domanda è: qual è il significato profondo di questo controllo?

 
Alexey Viktorov #:
Ecco la domanda: qual è il significato profondo di questo controllo?

Quando una classe di SomeObject viene caricata da un file chiamando il metodo Load() di questo stesso SomeObject, si controlla "mi sono davvero letto dal file?" (è quello che si sta chiedendo). In caso contrario, significa che qualcosa è andato storto, quindi è inutile continuare a caricare.

Si tratta di una LISTA (CListObj) che legge un tipo di oggetto da un file. La lista non sa cosa c'è (quale oggetto) nel file. Ma deve conoscere questo tipo di oggetto per crearlo nel suo metodo CreateElement(). Ecco perché non controlla il tipo dell'oggetto caricato dal file. Dopo tutto, ci sarà un confronto con Type(), che in questo metodo restituisce il tipo di una lista, non di un oggetto.

 
Artyom Trishkin #:

Quando una classe di SomeObject viene caricata da un file chiamando il metodo Load() di questo stesso SomeObject, esso controlla "mi sono davvero letto dal file?" (è quello che ci si chiede). In caso contrario, significa che qualcosa è andato storto, quindi è inutile continuare a caricare.

Si tratta di una LISTA (CListObj) che legge un tipo di oggetto da un file. La lista non sa cosa c'è (quale oggetto) nel file. Ma deve conoscere questo tipo di oggetto per crearlo nel suo metodo CreateElement(). Ecco perché non controlla il tipo dell'oggetto caricato dal file. Dopo tutto, ci sarà un confronto con Type(), che in questo metodo restituisce il tipo di una lista, non di un oggetto.

Grazie, ho capito, ho capito.

 

L'ho letto e poi riletto.

è tutto tranne che un "modello" in MVC. Alcuni ListStorage per esempio

 
Passiamo agli affari. Tenete per voi le vostre opinioni.
 
Mi chiedo. È possibile ottenere un analogo dei dataframe di python e R in questo modo? Si tratta di tabelle in cui le diverse colonne possono contenere dati di tipo diverso (da un insieme limitato di tipi, ma che includono le stringhe).
 
Aleksey Nikolayev #:
Mi chiedo. È possibile ottenere un analogo dei dataframe di python e R in questo modo? Si tratta di tabelle in cui le diverse colonne possono contenere dati di tipo diverso (da un insieme limitato di tipi, ma che includono le stringhe).

È possibile. Se stiamo parlando di diverse colonne di una tabella, nell'implementazione descritta ogni cella della tabella può avere un tipo di dati diverso.