Parler de l'OLP dans le salon - page 5

 
Alexey Volchanskiy:

J'ai lu les différents intérêts de chacun... Je suis actuellement en train de redessiner une classe pour l'exposition et le contrôle de la grille virtuelle, j'en ai besoin.

Et cela fait deux jours que je me bats avec le constructeur de copie et l'opérateur d'affectation. C'est une classe compliquée avec des membres de données sous forme de pointeurs...

 
Dennis Kirichenko:

Je me débats depuis 2 jours avec le constructeur de copie et l'opérateur d'affectation. Il y a une classe complexe avec des membres de données sous forme de pointeurs...

Je semble écrire des choses très primitives...

 
Dennis Kirichenko:

Vous pouvez utiliser un pointeur vers une fonction.

Cela fonctionnera-t-il de cette manière avec une fonction virtuelle ?

J'ai toujours détesté les pointeurs de fonction en interne, et je ne me souviens pas pourquoi, lorsque je travaillais en "C pur" - les pointeurs de fonction étaient utilisés. Mais lorsque je suis passé au C++, j'ai dû les abandonner pour une raison quelconque. Et je ne les ai pas utilisés depuis cette époque. Un pointeur - il doit être dirigé vers un objet.

Mais je ne vais pas dire que j'ai "absolument raison". Je reconnais que j'ai beaucoup d'expérience de la vieille école en moi.

 
fxsaber:

Je semble écrire des choses très primitives...

Ne soyez pas modeste.

Je ne pense pas que quiconque puisse égaler votre utilisation virtuose des définitions.

 
George Merts:


...Chez moi, cette fonction ressemble à ceci :

int CFactoryBalanceResultSeries::Compare(const CObject *poNode,const int iMode) const
{
   CFactoryBalanceResultSeries* pfdsAnother = CONVERT_OBJECT_WITH_CHECK(poNode,CFactoryBalanceResultSeries,MOT_FACTORYBALANCERES_SERIES);
   
   switch(iMode)
      {
      case FSM_BY_PART_OF_MAX_DD_A:    return(_CompareByPartOfMaxDDWith(pfdsAnother,true));
      case FSM_BY_PART_OF_MAX_DD_D:    return(_CompareByPartOfMaxDDWith(pfdsAnother,false));

      case FSM_BY_PART_OF_MAX_SLQUEUE_A: return(_CompareByPartOfMaxSLQueueWith(pfdsAnother,true));
      case FSM_BY_PART_OF_MAX_SLQUEUE_D: return(_CompareByPartOfMaxSLQueueWith(pfdsAnother,false));

      case FSM_BY_LAST_PRCDATA_A:      return(_CompareByLastPrcdataWith(pfdsAnother,true));
      case FSM_BY_LAST_PRCDATA_D:      return(_CompareByLastPrcdataWith(pfdsAnother,false));
      case FSM_BY_LAST_MNYDATA_A:      return(_CompareByLastMnydataWith(pfdsAnother,true));
      case FSM_BY_LAST_MNYDATA_D:      return(_CompareByLastMnydataWith(pfdsAnother,false));
      case FSM_BY_LAST_MNYLOTDATA_A:   return(_CompareByLastMnylotdataWith(pfdsAnother,true));
      case FSM_BY_LAST_MNYLOTDATA_D:   return(_CompareByLastMnylotdataWith(pfdsAnother,false));
      
      case FSM_BY_PRCYEARRECOVERY_A:   return(_CompareByYearPrcrecoveryWith(pfdsAnother,true));
      case FSM_BY_PRCYEARRECOVERY_D:   return(_CompareByYearPrcrecoveryWith(pfdsAnother,false));
      case FSM_BY_MNYYEARRECOVERY_A:   return(_CompareByMnyYearRecoveryWith(pfdsAnother,true));
      case FSM_BY_MNYYEARRECOVERY_D:   return(_CompareByMnyYearRecoveryWith(pfdsAnother,false));
      case FSM_BY_MNYLOTYEARRECOVERY_A:return(_CompareByMnylotYearRecoveryWith(pfdsAnother,true));
      case FSM_BY_MNYLOTYEARRECOVERY_D:return(_CompareByMnylotYearRecoveryWith(pfdsAnother,false));
      
      case FSM_BY_PRCVAR_A:            return(_CompareByPrcVarWith(pfdsAnother,true));
      case FSM_BY_PRCVAR_D:            return(_CompareByPrcVarWith(pfdsAnother,false));
      case FSM_BY_MNYVAR_A:            return(_CompareByMnyVarWith(pfdsAnother,true));
      case FSM_BY_MNYVAR_D:            return(_CompareByMnyVarWith(pfdsAnother,false));
      case FSM_BY_MNYLOTVAR_A:         return(_CompareByMnylotVarWith(pfdsAnother,true));
      case FSM_BY_MNYLOTVAR_D:         return(_CompareByMnylotVarWith(pfdsAnother,false));
      
      case FSM_BY_PRC_GRAILRATIO_A:    return(_CompareByPrcGrailratioWith(pfdsAnother,true));
      case FSM_BY_PRC_GRAILRATIO_D:    return(_CompareByPrcGrailratioWith(pfdsAnother,false));

      case FSM_BY_MAGIC_A:             return(_CompareByMagicWith(pfdsAnother,true));
      case FSM_BY_MAIGC_D:             return(_CompareByMagicWith(pfdsAnother,false));
      default:
         break;
      };
         
   return(NULL);
};

George, on ne peut pas voir ici si _CompareByPrcVarWith() est une méthode de classe ou une fonction ordinaire, par exemple. En C++, il existe des pointeurs vers les méthodes des classes. Ils ont leurs propres spécificités là-bas. Pour être honnête, je n'ai pas essayé d'utiliser de tels pointeurs dans MQL5.

Mais je pense que vous avez encore une réserve pour améliorer la structure du code.

Après tout, qu'est-ce qu'une fonction ?

LaFONCTION(lat.functio, "exécution, performance ; devoir") est une relation entre des éléments dans laquelle un changement dans l'un entraîne un changement dans l'autre.

C'est une fonction qui fait quelque chose. Les mêmes actions doivent être combinées dans le corps d'une seule fonction.

Dans votre exemple, il est évident que les fonctions

_CompareByPartOfMaxDDWith(),

_CompareByPartOfMaxSLQueueWith(),

_CompareByLastPrcdataWith(),

_CompareByLastMnydataWith(), etc.

faire un COMPARAISON et donner le résultat de cette comparaison. Ils diffèrent par leurs noms. Je pense que ce n'est pas une bonne pratique. Ils doivent se distinguer par des paramètres.

Donc. Je pense que vous devriez soit fusionner toutes les fonctions en une seule, soit en faire des méthodes virtuelles, ou des méthodes modèles. Évidemment, les classes doivent respecter la hiérarchie "parents-fils".

D'une manière générale, il est très facile d'écrire un code complexe et très difficile d'écrire un code simple.

 
Dennis Kirichenko:

George, on ne voit pas ici si _CompareByPrcVarWith() est une méthode de classe ou une fonction ordinaire. En C++, il existe des pointeurs vers les méthodes des classes. Ils ont leurs propres spécificités là-bas. Honnêtement, je n'ai pas essayé d'utiliser de tels pointeurs dans MQL5.

Cette fonction (et toutes celles qui commencent par un trait de soulignement) est une fonction protégée de la classe.

Ils s'occupent de l'ARRANGEMENT et donnent le résultat de cette comparaison. Ils diffèrent par leurs noms. Je pense que ce n'est pas une bonne pratique. Il vaudrait mieux qu'ils soient différents en termes de paramètres.

Donc. Je pense que nous devrions soit fusionner toutes les fonctions en une seule, soit en faire des méthodes virtuelles, ou des méthodes modèles. Évidemment, les classes doivent respecter la hiérarchie "parents-fils".

Eh bien, ils sont tous fusionnés en un seul !

Il n'y a qu'une seule fonction - Compare() mais elle doit effectuer une comparaison avec une clé passée. En conséquence, nous choisissons l'une des fonctions spécifiques du protecteur. C'est pourquoi ils sont protégés (protected), afin que l'utilisateur ne puisse pas y accéder - ils ne sont appelés que depuis Compare() et cela est indiqué par le soulignement.

C'est également l'une des règles de conception du code - une fonction commençant par un trait de soulignement n'est pas destinée à être appelée par les utilisateurs, elle sert uniquement à certaines tâches en classe. Son accès est restreint.

 
Dennis Kirichenko:

Je me débats depuis 2 jours avec le constructeur de copie et l'opérateur d'affectation. Il y a une classe complexe avec des membres de données sous forme de pointeurs...


Denis, je voulais dire que chacun a des approches différentes. En fait, lorsque j'ai ouvert le fil de discussion hier, j'étais curieux de voir si les pleurnichards d'hier allaient apparaître, à la "a-a-a-a OOP est très compliqué, SB est une horrible boîte noire". Ils ne sont pas venus, ce qui est normal.

Mais des personnes sont apparues et chacune a une approche différente. C'est également intéressant en termes de projets partagés, dont Renat parle tant.

ZS : le partage dans les projets ne fonctionne toujours pas, je l'ai essayé récemment.

 
George Merts:

Celle-ci (et toutes celles qui commencent par un trait de soulignement) sont des fonctions de protection de la classe.

Eh bien, ils sont fusionnés en un seul !

Il n'y a qu'une seule fonction - Compare(), mais elle doit effectuer une comparaison avec une clé passée. En conséquence, l'une des fonctions particulières contestées est choisie. C'est pourquoi ils sont protégés (protected), afin que l'utilisateur ne puisse pas y accéder - ils ne sont appelés qu'à partir de Compare(), ce qui est indiqué par le soulignement.

C'est également l'une des règles de conception du code - une fonction commençant par un trait de soulignement n'est pas destinée à être appelée par les utilisateurs, elle sert uniquement à certaines tâches en classe. Son accès est restreint.


Comment sont-elles fusionnées si vous avez plusieurs méthodes _CompareXXX() ? Et il devrait y en avoir 1 si je comprends bien.

Par exemple, la méthode_CompareByPartOfMaxDDWith() est-elle appelée ailleurs que dans CFactoryBalanceResultSeries::Compare() ?

 
Dennis Kirichenko:

Comment fusionner si vous avez plusieurs méthodes _CompareXXX() ? Et il devrait y en avoir 1 si je comprends bien.

Par exemple, la méthode_CompareByPartOfMaxDDWith() est-elle appelée ailleurs que dans CFactoryBalanceResultSeries::Compare() ?

Si la méthode _CompareXXX() est une, elle n'est pas différente de la fonction virtuelle originale Compare().

Le fait est que les méthodes _CompareBy...() ne sont appelées qu'à partir de la méthode principale Compare(). Et le soulignement au début met en garde contre ce problème.

La méthode générale Compare() accepte les pointeurs vers deux objets et la clé qui spécifie la comparaison. Dans cette méthode générale, la clé est analysée, et ensuite on appelle la méthode spécifique, qui est conçue pour comparer une seule clé. De plus, chacune de ces méthodes calcule la valeur des clés de deux objets passés et selon que la clé est un int, un double, un bool ou une chaîne - la méthode (également protégée) de comparaison du type concret est appelée.

Toutes les méthodes _CompareBy...() - nous pourrions les écrire dans une seule fonction. Mais alors, à mon avis, la lisibilité du code se détériorerait.

 
George Merts:

S'il n'y a qu'une seule méthode _CompareXXX(), elle n'est pas différente de la fonction virtuelle Compare() originale.

Le fait est que les méthodes _CompareBy...() ne sont appelées qu'à partir de la méthode principale Compare(). Et le soulignement au début met en garde contre ce problème.

La méthode générale Compare() accepte des pointeurs vers deux objets et la clé qui spécifie la comparaison. Dans cette méthode générale, la clé est analysée, et ensuite on appelle la méthode spécifique, qui est conçue pour comparer une seule clé. Et chacune de ces méthodes calcule la valeur des clés de deux objets passés et selon que la clé est un int, un double, un bool ou une chaîne - elle est appelée la méthode (également protégée) de comparaison de type concret.

Toutes les méthodes _CompareBy...() pourraient être écrites dans une seule fonction. Mais alors la lisibilité du code se détériorerait à mon avis.


Je comprends ce que vous voulez dire. Je suppose que c'est une question de goût. Mais je ferais tout en une seule méthode. En particulier, si les méthodes protégées et privées ne sont pas appelées ailleurs que parCompare().