Discussion de l'article "Implémentation d'un modèle de table dans MQL5 : Application du concept MVC"

 

Un nouvel article Implémentation d'un modèle de table dans MQL5 : Application du concept MVC a été publié :

Dans cet article, nous examinons le processus de développement d'un modèle de table dans MQL5 en utilisant le modèle architectural MVC (Modèle - Vue - Contrôleur) pour séparer la logique des données, la présentation et le contrôle, ce qui permet d'obtenir un code structuré, flexible et évolutif. Nous envisageons la mise en œuvre de classes pour la construction d'un modèle de table, y compris l'utilisation de listes chaînées pour le stockage des données.

En programmation, l'architecture des applications joue un rôle clé pour garantir la fiabilité, l'évolutivité et la facilité d'assistance. L'une des approches permettant d'atteindre ces objectifs consiste à tirer parti d'un modèle d'architecture appelé MVC (Modèle-Vue-Contrôleur).

Le concept MVC permet de diviser une application en 3 composants interdépendants : le modèle (gestion des données et de la logique), la vue (affichage des données) et le contrôleur (traitement des actions de l'utilisateur). Cette séparation simplifie le développement, le test et la maintenance du code, le rendant plus structuré et plus flexible.

Dans cet article, nous examinons comment appliquer les principes MVC pour mettre en œuvre un modèle de tableau dans le langage MQL5. Les tableaux sont un outil important pour le stockage, le traitement et l'affichage des données, et une bonne organisation peut faciliter grandement le travail avec les informations. Nous allons créer des classes pour travailler avec des tableaux : cellules de tableau, lignes et modèle de tableau. Pour stocker les cellules dans les lignes et les lignes dans le modèle de tableau, nous utiliserons les classes de listes liées (linked list) de la bibliothèque standard MQL5 qui permettent un stockage et une utilisation efficaces des données.


Auteur : Artyom Trishkin

 

Bonjour, Artem.

Voici une question :

Votre code lit le type d'objet.

      //--- Lire le type d'objet
      this.m_element_type=(ENUM_OBJECT_TYPE)::FileReadInteger(file_handle,INT_VALUE);

Mais il n'est pas vérifié comme dans SB

bool CList::Load(const int file_handle)
  {
   uint     i,num;
   CObject *node;
   bool     result=true;
//--- vérifier
   if(file_handle==INVALID_HANDLE)
      return(false);
//--- lecture et vérification du marqueur de début - 0xFFFFFFFFFFFFFFFFFFF
   if(FileReadLong(file_handle)!=-1)
      return(false);
//--- lecture et vérification du type
   if(FileReadInteger(file_handle,INT_VALUE)!=Type())
      return(false);
//--- taille de la liste de lecture
   num=FileReadInteger(file_handle,INT_VALUE);
//--- création séquentielle des éléments de la liste par l'appel de la méthode Load()
   Clear();
   for(i=0;i<num;i++)
     {
      node=CreateElement();
      if(node==NULL)
         return(false);
      Add(node);
      result&=node.Load(file_handle);
     }
//--- réussi
   return(result);
  }

Comme nous pouvons le voir, la méthode Type() renvoie simplement une valeur

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

Quelle est la nécessité d'une telle vérification dans SB ? Est-il vraiment suffisant de lire le type et de créer un élément du type correspondant ?

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

Si le type n'est pas lu, que faire ?

Voici le code :

//--- Recréer séquentiellement les éléments de la liste en appelant la méthode Load() des objets nœuds.
   this.Clear();
   for(uint i=0; i<num; i++)
     {
      //--- Lire et vérifier le marqueur de début des données de l'objet - 0xFFFFFFFFFFFFFFFFFFF
      if(::FileReadLong(file_handle)!=MARKER_START_DATA)
         return false;
      //--- Lire le type d'objet
      this.m_element_type=(ENUM_OBJECT_TYPE)::FileReadInteger(file_handle,INT_VALUE);
      node=this.CreateElement();
      if(node==NULL)
         return false;
      this.Add(node);
      //--- Le pointeur de fichier est maintenant décalé de 12 octets par rapport au début du marqueur d'objet (8 - marqueur, 4 - type).
      //--- Plaçons un pointeur au début des données de l'objet et chargeons les propriétés de l'objet à partir du fichier à l'aide de la méthode Load() de l'élément node.
      if(!::FileSeek(file_handle,-12,SEEK_CUR))
         return false;
      result &=node.Load(file_handle);
     }
//--- Résultat
   return result;
  }
//+------------------------------------------------------------------+
//| Méthode de création d'un élément de liste|
//+------------------------------------------------------------------+
CObject *CListObj::CreateElement(void)
  {
//--- En fonction du type d'objet dans m_element_type, créer un nouvel objet
   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;
     }
  }

Nous lisons le type de l'objet dans une variable. Ensuite, nous essayons de créer cet objet dans CreateElement(), et il y a des cas. Que retournera cette méthode si le type de l'objet créé n'est pas lu dans le fichier ?

 
Artyom Trishkin #:

Si le type n'est pas lu, que se passe-t-il ensuite ?

Voici le code :

Nous lisons le type de l'objet dans une variable. Ensuite, nous essayons de créer cet objet dans CreateElement(), et il y a des cas. Que retournera cette méthode si le type de l'objet créé n'est pas lu dans le fichier ?

Artem, ce n'est pas de cela que je parle. Je parle du fait qu'il y a une vérification de type dans SB. Exactement la vérification.

//--- lecture et vérification du type
   if(FileReadInteger(file_handle,INT_VALUE)!= Type())
      return(false);

Le type lu dans le fichier correspond-il au type de la méthode Type()Read and typecheck. C'est ainsi que cela se traduit ?
Et vous lisez simplement le type sans le vérifier.

La question est donc la suivante : quelle est la signification profonde de cette vérification ?

 
Alexey Viktorov #:
Voici la question : quelle est la signification profonde de cette vérification ?

Lorsqu'une classe de SomeObject est chargée à partir d'un fichier en appelant la méthode Load() de ce même SomeObject, elle vérifie si elle s'est vraiment lue à partir du fichier (c'est ce que vous demandez). Si ce n'est pas le cas, cela signifie que quelque chose s'est mal passé et qu'il est inutile de poursuivre le chargement.

Ce que j'ai ici est une LISTE (CListObj) qui lit un type d'objet à partir d'un fichier. La liste ne sait pas ce qu'il y a (quel objet) dans le fichier. Mais elle doit connaître ce type d'objet pour le créer dans sa méthode CreateElement(). C'est pourquoi elle ne vérifie pas le type de l'objet chargé à partir du fichier. Après tout, il y aura une comparaison avec Type(), qui dans cette méthode renvoie le type d'une liste, pas d'un objet.

 
Artyom Trishkin #:

Lorsqu'une classe de SomeObject est chargée à partir d'un fichier en appelant la méthode Load() de ce même SomeObject, elle vérifie "est-ce que je me suis vraiment lu moi-même dans le fichier ? Si ce n'est pas le cas, cela signifie que quelque chose s'est mal passé et qu'il est inutile de poursuivre le chargement.

Ce que j'ai ici est une LISTE (CListObj) qui lit un type d'objet à partir d'un fichier. La liste ne sait pas ce qu'il y a (quel objet) dans le fichier. Mais elle doit connaître ce type d'objet pour le créer dans sa méthode CreateElement(). C'est pourquoi elle ne vérifie pas le type de l'objet chargé à partir du fichier. Après tout, il y aura une comparaison avec Type(), qui dans cette méthode renvoie le type d'une liste, pas d'un objet.

Merci, j'ai compris.

 

Je l'ai lu, puis relu.

c'est tout sauf un "modèle" en MVC. Certains ListStorage par exemple

 
Passons aux choses sérieuses. Gardez vos opinions pour vous.
 
Je m'interroge. Est-il possible d'obtenir un analogue des dataframes de python et de R de cette manière ? Il s'agit de tableaux dont les différentes colonnes peuvent contenir des données de différents types (à partir d'un ensemble limité de types, mais incluant les chaînes de caractères).
 
Aleksey Nikolayev #:
Je m'interroge. Est-il possible d'obtenir un analogue des dataframes de python et de R de cette manière ? Il s'agit de tableaux où les différentes colonnes peuvent contenir des données de différents types (à partir d'un ensemble limité de types, mais incluant les chaînes de caractères).

C'est possible. Si nous parlons de différentes colonnes d'un tableau, alors dans l'implémentation décrite, chaque cellule du tableau peut avoir un type de données différent.