Un point de vue intéressant sur l'OLP - page 10

 
Vitaly Muzichenko:

Je n'aime pas du tout ce design en termes de lisibilité et d'encombrement.

Je suis d'accord)))

La seule justification pour ceci est le débogage)

 
Vitaly Muzichenko:

Je n'aime pas du tout ce design en termes de lisibilité et d'encombrement.

c'était ma question à l'origine

les derniers exemples correspondent à l'affirmation de @fxsaber selon laquelle il y aura 100% de codes différents au moment de l'exécution. j'ai posté le désassembleur du débogueur il y a quelques pages - les codes sont identiques à 90%.

Je ne parle pas de l'impossibilité de renvoyer des constructions simples qui se lisent sans problème.

 
Igor Makanu:

les développeurs ont écrit quelque part et ici des informations similaires

J'ai seulement trouvé ceci :

switch est un goto sûr qui utilise une table de saut. En d'autres termes, l'adresse "case" est calculée à l'aide d'une clé entière dans le commutateur. C'est pourquoi le switch est extrêmement efficace, même par rapport au if-else, sans parler des collections plus avancées comme les dictionnaires.

 
fxsaber:

Cela n'a-t-il pas pour effet négatif d'écrire un code de qualité quelconque en espérant que "le compilateur le brossera à l'optimum" ?

Avec un style d'écriture, vous êtes sûr que le compilateur fera ce qu'il faut. Avec un autre style, vous devez simplement faire confiance au compilateur pour qu'il soit plus intelligent.

Compte tenu de la multi-plateforme, des différents compilateurs, etc., je choisis d'être conscient de ce que vous faites dans le code.

Seul le compilateur sait exactement ce qu'il va faire. Les compilateurs d'aujourd'hui ont une euristique stupéfiante. Ils s'adaptent au codeur moyen et savent déjà mieux ce dont il a besoin. La meilleure chose qu'un compilateur puisse faire est d'écrire un code simple et direct avec des fonctions courtes. Il est plus facile et plus efficace pour le compilateur d'analyser le graphe du code source composé de nombreux nœuds de fonction pour construire le programme résultant. Cela ne peut qu'avoir un impact positif sur les performances, car les fonctions nécessaires sont intégrées aux bons endroits.

 
Vasiliy Sokolov:

switch est un goto sûr qui utilise une table de saut. En d'autres termes, l'adresse "case" est calculée à partir dela clé entière dans switch. De ce fait, switch est extrêmement efficace, même par rapport à if-else, sans parler de collections plus avancées comme les dictionnaires.

cool ! c'est une information utile

Merci !

 

De nombreuses personnes recommandent d'écrire des classes de petite taille. Le même Eckel dit : "créer des classes pour un objectif unique et clairement défini".

Je travaille sur un EA en ce moment, et je vais écrire une petite simplification pour un exemple. Il y a un des paramètres "Reach max stoploss". Lorsqu'on obtient le SL, il doit fonctionner comme un compteur de retour à zéro et arrêter le travail de l'EA, et lorsqu'on obtient le TP, il doit se réinitialiser à la valeur initiale, avec la valeur affichée sur le panneau.

J'ai créé une classe séparée pour ce compteur. Il s'avère qu'elle change à partir de plusieurs points, à partir de OnInit lors du réglage des paramètres d'entrée et à partir du champ de saisie du panneau après la fermeture de l'ordre (sl et tp changent de valeur différemment). De plus, la fonction principale est appelée à partir de OnTick() pour garder la trace du nombre maximum de stoploss pour arrêter l'EA.

La classe semble être très simple. Mais il s'avère que cette petite classe affecte d'autres objets situés dans le panneau (boîte de saisie, boutons). Il affecte le fonctionnement d'autres fonctions. Et lorsqu'il existe une douzaine de ces petites classes, il est déjà difficile de repérer quelles fonctions modifient l'objet ou quelles méthodes de certains objets peuvent modifier l'état d'autres objets.

Je veux savoir comment organiser au mieux l'interaction des objets entre eux pour réduire la confusion, existe-t-il de bons articles ou livres avec des exemples de codes, des diagrammes sur ce sujet et de bonnes explications ? Veuillez partager ce qui a aidé quelqu'un à apprendre à écrire des architectures bien conçues.

 
Il ne s'agit pas d'un problème de POE, mais d'un problème lié à l'approche générale de la création des EA. Nous devrions compter le nombre de stoploss par histoire. En général, c'est à cela que sert la tête d'un homme, il n'y a pas de solution universelle.
 
Vitaly Muzichenko:

Je n'aime pas du tout ce design en termes de lisibilité et d'encombrement.

Goût et couleur.... tous les feutres sont différents.

C'était un contraste avec le "petit monstre" :

Forum sur le trading, les systèmes de trading automatisés et les tests de stratégies de trading

Opinion intéressante sur la POO

fxsaber, 2021.01.31 01:09

Un petit monstre.

  static bool VirtualOrderSelect( const TICKET_TYPE Index, const int Select, const int Pool = MODE_TRADES )
  {
    return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.OrderSelect(Index, Select, Pool) :
           #ifdef  VIRTUAL_SNAPSHOT_REFRESHTIME
             VIRTUAL::SnapshotPtr ?
             #ifdef __MQL5__ // Выбор по тикету в MT5 - разнообразный набор вариантов.
               (Select == SELECT_BY_TICKET) ? ::OrderSelect(Index, Select, Pool) && VIRTUAL::SnapshotPtr.CopyOrder()
                                            :
             #endif // #ifdef __MQL5__
                                              ((((Index == INT_MIN) || (Index == INT_MAX)) && (Pool == MODE_TRADES) &&
                                               ::OrderSelect(Index, Select, Pool) &&
                                             #ifdef  VIRTUAL_SNAPSHOT_WITHOUT_HISTORY
                                               VIRTUAL::SnapshotPtr.CopyOrder(true))
                                             #else // #ifdef VIRTUAL_SNAPSHOT_WITHOUT_HISTORY
                                               VIRTUAL::SnapshotPtr.CopyOrder())
                                             #endif // #ifdef VIRTUAL_SNAPSHOT_WITHOUT_HISTORY #else
                                               || VIRTUAL::SnapshotPtr.OrderSelect(Index, Select, Pool))
                                  :
           #endif // #ifdef VIRTUAL_SNAPSHOT_REFRESHTIME
           #ifdef __MQL5__
             #ifdef __MT4ORDERS__
               ::OrderSelect(Index, Select, Pool)
             #else // __MT4ORDERS__
               false
             #endif // __MT4ORDERS__
           #else // __MQL5__
             ::OrderSelect(Index, Select, Pool)
           #endif // __MQL5__
           );
  }

Lesopérations logiques permettent une écriture concise lors de l'utilisation de différents paramètres via des macros. Mais c'est une horreur, bien sûr.


 
Andrey Khatimlianskii:

Goût et couleur.... tous les feutres sont différents.

C'est faux. Elles ne varient que par leur couleur, mais elles ont toutes le même goût...))))

 
Vitaly Muzichenko:

Je n'aime pas du tout ce design en termes de lisibilité et d'encombrement.

Pourquoi ?

Au contraire, avec deux "si", c'est beaucoup plus facile qu'avec l'opérateur "ou".

Il est plus facile de vérifier une condition en premier lieu, et de quitter la fonction si elle est vraie, puis d'en vérifier une autre, et de la quitter également, si elle est vraie, que d'essayer de déterminer le résultat d'une condition complexe, en utilisant le "ou" logique (qui peut facilement être confondu avec le "et"), et de garder la trace des deux options de retour.

C'est assez drôle de lire plus bas que "la justification d'un tel code est le débogage", car cela signifie qu'un tel code est beaucoup plus compréhensible (sinon pourquoi est-il en débogage ?).

"Apothéose" Je considère une expression de fxsaber, à propos de laquelle il n'a pas pu lui-même dire comment elle fonctionne, déclarant simplement que "le code a été testé à plusieurs reprises, et il fonctionne". À mon avis, cela ne devrait pas être le cas :

ENUM_ORDER_TYPE_FILLING CSymbolInfo::GetTypeFilling(string strSymbol,ENUM_ORDER_TYPE_FILLING otfFilingType)
{
   const ENUM_SYMBOL_TRADE_EXECUTION steExeMode = (ENUM_SYMBOL_TRADE_EXECUTION)::SymbolInfoInteger(strSymbol, SYMBOL_TRADE_EXEMODE);
   const int iFillingMode = (int)::SymbolInfoInteger(strSymbol, SYMBOL_FILLING_MODE);

   return((iFillingMode == 0 || (otfFilingType >= ORDER_FILLING_RETURN) || ((iFillingMode & (otfFilingType + 1)) != otfFilingType + 1)) ?
         (((steExeMode == SYMBOL_TRADE_EXECUTION_EXCHANGE) || (steExeMode == SYMBOL_TRADE_EXECUTION_INSTANT)) ?
           ORDER_FILLING_RETURN : ((iFillingMode == SYMBOL_FILLING_IOC) ? ORDER_FILLING_IOC : ORDER_FILLING_FOK)) :
          otfFilingType);
};

Ce code vérifie siun ordre otfFilingType peut êtreexécuté, et le renvoie s'il est disponible sur strSymbol, sinon il est correct.


Je n'ai absolument aucune idée de comment cela fonctionne. Et ne vous fiez qu'à l'autorité de Fxsaber.

Peut-être que quelqu'un peut expliquer ?