Implémentations alternatives de fonctions/approches standard - page 8

 
fxsaber:

Un exemple de mon style ?

Par exemple ceci :

return((int)((Value > 0) ? Value / Points[digits] + HALF_PLUS : Value / Points[digits] - HALF_PLUS) * Points[digits]);

Imaginez que vous ayez 100 fonctions et que chacune d'entre elles renvoie un tel enregistrement. Vous recherchez une erreur parmi ces entrées. Combien de temps vous faut-il pour effectuer une recherche ?

 
Реter Konow:

Par exemple ceci :

Imaginez que vous ayez 100 fonctions et que chacune d'entre elles renvoie cet enregistrement. Vous recherchez une erreur parmi ces entrées. Combien de temps vous faut-il pour effectuer une recherche ?

Je ne chercherais pas plus de deux minutes, d'autant plus qu'une fiche de ce style permet d'afficher plus de quelques dizaines de fonctions en "un seul écran", ce qui facilite le travail avec le code

 
Реter Konow:

Par exemple ceci :

Imaginez que vous ayez 100 fonctions et que chacune d'entre elles renvoie cet enregistrement. Vous recherchez une erreur parmi ces entrées. Combien de temps vous faudra-t-il pour le trouver ?

Croyez-moi, quand j'écris des textes comme ça, ce n'est pas par souci de style ou par principe de brièveté, mais parce que c'est vraiment beaucoup plus facile pour moi.

Vous avez cité le moyen le plus simple. Honnêtement, je ne comprends pas ce qui pourrait être un tant soit peu déroutant.

Je dois avouer que je ne sais pas lire le code C++ car je ne le connais pas du tout. Mais les gens écrivent dedans. Donc c'est juste une question d'ignorance.

 
fxsaber:

Croyez-moi, lorsque j'écris de cette façon, ce n'est pas par souci de style ou par principe de concision, mais parce que c'est vraiment plus facile pour moi.

Vous avez cité les termes les plus simples. Honnêtement, je ne comprends pas ce qui pourrait être un tant soit peu déroutant.

Je dois avouer que je ne sais pas lire le code C++ car je ne le connais pas du tout. Mais les gens écrivent dedans. Donc c'est juste une question d'ignorance.

Peut-être avons-nous une idée différente de la simplicité du code.

Je comprends que vous êtes un grand professionnel de la programmation. Mais il ne faut pas oublier la productivité dutravail lorsque l'on recherche une productivité maximale. Cela commence par la lisibilité du code. Je ne vois pas très bien pourquoi l'envie de comprimer le code au détriment de sa lisibilité est justifiée, mais elle est tout à fait inacceptable dans les grands projets (indépendants).


Pour être franc, je déteste le C++ parce qu'il est trop illisible. Pour l'empilement d'entités dont l'existence pourrait être facilement évitée. Et ça ne peut que s'améliorer. Spacieux.

SZU. Je pense que dans le développement, le code doit être compressé non pas au détriment de la lisibilité mais au détriment de meilleures solutions, tout en le laissant aussi lisible que possible. La vitesse de compréhension du code a un impact énorme sur votre propre productivité.

ZSY. Le fil est génial. Merci.

Productivity - США - MetaTrader 5
Productivity - США - MetaTrader 5
  • www.metatrader5.com
Индекс производительности труда показывает изменение объема выпущенной продукции, приходящегося на одного работника. Этот показатель полезен для предсказания инфляции и прироста объема производства. Если стоимость труда увеличивается соответственно увеличению производительности, и, кроме того, маловероятно увеличение производственных издержек...
 
Renat Fatkhullin:
Pensez à ce que vous obtiendrez en dehors d'un nombre entier.

La vérification de LONG_MAX - devrait donc avoir lieu avant la conversion du double en long. Il est clair que la fonction d'arrondi n'est pas conçue pour les valeurs qui ne tiennent pas dans un entier. Et cela ne change rien au problème.

Si la fonction renvoie un double que nous convertissons ensuite en long, nous sommes confrontés au même danger de débordement.

Personnellement, juste avant l'arrondi - j'ai toujours un assert-check pour les valeurs limites, plus la logique du programme - je cherche toujours à m'assurer que la conversion ne peut jamais obtenir plus que la valeur maximale pour un entier.

 
Vitaly Muzichenko:

Je ne chercherais pas plus de deux minutes, d'autant plus que l'écriture dans ce style permet d'afficher plus de quelques dizaines de fonctions sur "un seul écran", ce qui facilite le travail avec le code.

J'ai des doutes à ce sujet.

Voici le code actuel de ma fonction, qui renvoie le type d'exécution (le code a été suggéré par fxsaber, et je lui en suis très reconnaissant) :

// Для МТ4 - возвращает otfFilingType. // Для МТ5 - возвращает тип исполнения ордера, равный otfFilingType, если он доступен на символе strSymbol, иначе - корректный вариант. ENUM_ORDER_TYPE_FILLING CSymbolInfo::GetTypeFilling(string strSymbol,ENUM_ORDER_TYPE_FILLING otfFilingType = ORDER_FILLING_FOK) {    #ifndef __MQL5__       return(otfFilingType);    #else // __MQL5__          // Функцию предложил fxsaber. Серьезной проверки не было - полагаемся на его авторитет.          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);      #endif // __MQL5__ };

La fonction fonctionne très bien. Je l'ai vérifié plusieurs fois et aucune erreur ne s'est produite. Mais je ne comprends toujours pas comment le résultat est formé dans cet affreux retour, malgré ma propre expérience plutôt bonne. De plus, fxsaber a répondu à la question que lui-même ne s'en souvient pas.

Vitaly, dites-moi comment ce code fonctionne, si ce n'est pas trop difficile pour vous et que vous le "comprenez en quelques minutes" dans ce style !

J'ouvrirais les parenthèses dans l'opérateur de retour, remplacerais toutes les "questions" par des "si" et renverrais les valeurs trouvées par le biais de "ou" logique. Il produit exactement le même code qu'un if similaire, mais sa lisibilité est bien pire.

 
Georgiy Merts:

J'ai des doutes à ce sujet.

Voici le code réel de ma fonction, qui renvoie le type d'exécution (le code a été suggéré par fxsaber, pour lequel je lui suis très reconnaissant) :

La fonction fonctionne très bien. Je l'ai vérifié plusieurs fois et il n'y avait aucune erreur. Mais je ne comprends toujours pas comment le résultat est formé dans cet affreux retour, malgré mon expérience, je pense, suffisamment bonne. D'ailleurs, fxsaber lui-même a répondu à la question qu'il ne s'en souvient même pas.

Vitaly, dites-moi comment ce code fonctionne, si ce n'est pas trop difficile pour vous et que vous le "comprenez en quelques minutes" dans ce style !

Je "ouvrirais les parenthèses" dans l'opérateur de retour, remplacerais toutes les "questions" par des "si" et renverrais les valeurs trouvées via un "ou" logique. Personnellement, l'opérateur "question" m'ennuie beaucoup. Il produit exactement le même code qu'un if similaire, mais sa lisibilité est bien pire.

Je ne vais pas interpréter le code, mais j'ai déjà posté un morceau de mon modèle, et il y a une approche similaire. Je n'aime pas étirer les "si" en deux rouleaux de l'écran.

 
Реter Konow:

n'oubliez pas laproductivité du travail. Cela commence par la lisibilité du code.

Un exemple de mon code, que je ne comprends pas du tout pour l'instant. Et il y a beaucoup de facteurs que vous devez bien comprendre.

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

Séquence d'exécution de Init() et DeInit()

fxsaber, 2017.04.14 23:35

  bool Check( void ) const
  {
    static bool FirstRun = true;
    static bool FirstRunInit = true;

    if (FirstRun && (!::GlobalVariableCheck(this.GlobalName)))
    {
      FirstRun = (::GlobalVariableSet(this.GlobalName, 0) == 0);

      if (!FirstRun)
      {
        ::EventKillTimer();

        ::OnInit();
        FirstRunInit = false;
      }
    }
    else if (FirstRun)
      ::EventSetMillisecondTimer(1);
    else
      FirstRunInit = true;

    return(FirstRun || !FirstRunInit);
  }

Comme vous pouvez le constater, le code/style est très simple. Mais je ne pourrai détecter une erreur dans ce code ou son absence que lorsque je pourrai réécrire le même code. Cela va vraiment prendre beaucoup de temps, car je dois bien comprendre le problème.

C'est pourquoi le principe est que les choses complexes sont nettoyées (des tests de stress sont écrits) au stade de la création et utilisées sous une forme simple en branchant mqh. Comme vous pouvez le constater, la complexité n'est pas toujours déterminée par le style ou la brièveté.


Il existe également un exemple de construction purement linguistique - TypeToBytes. La complexité de la compréhension y est d'un tout autre niveau. Et c'est là que je dépérirais sans les macros. C'est grâce aux macros que l'on accède assez rapidement au code source. Car les macros sont souvent utilisées non pas pour la brièveté, mais pour la compréhension.


Et il y a aussi le cas où vous devez tenir compte d'un grand nombre de pièges peu compliqués mais oubliables. C'est le cas avec MT4Orders. C'est pourquoi certaines lignes y sont accompagnées de commentaires adressés uniquement à soi-même. Cela aide à comprendre votre code.


Mais notez que ce sont toutes des mqh, qu'il n'est pas nécessaire d'aborder. Et le code de TC est écrit avec mqh, ce qui est très simple. Vous ne regardez pas dans le code source des fonctions régulières de iHigh. Et ils sont en effet monstrueux. Vous les utilisez simplement. Vous devriez faire de même avec les bibliothèques. L'utilisation du même Generic-bibble ne nécessite pas que vous le compreniez parfaitement.


Regardez le QB pour les EA MT4 et leurs ports MT5. Les ports MT5 sont difficiles à comprendre. Non seulement il est loin d'être concis (le code est plusieurs fois plus gros que l'original), mais il comporte également des pièges MT5 qui ne sont pas pris en compte dans les fichiers mqh.

 
Vitaly Muzichenko:

Je ne vais pas interpréter le code, mais j'ai déjà posté un morceau de mon modèle, et il y a une approche similaire. Je n'aime pas étirer les "si" en deux parchemins de moniteur.

Dans ce cas, il est judicieux d'utiliser des fonctions.

Et le fait que vous n'ayez pas interprété le code indique que vous ne pouvez pas non plus comprendre immédiatement comment il fonctionne. Vous devez analyser en profondeur les parenthèses, ces mêmes "questions" et "ou" logiques. Mais cet "empilement" est acceptable dans des cas très limités, lorsqu'il permet d'utiliser un code plus efficace dans le "goulot d'étranglement" du programme. Dans ce cas, l'obtention du type d'exécution ne peut pas être un goulot d'étranglement et un tel code est indésirable ici. Je l'utilise uniquement sur la base de l'autorité de fxsaber et des autotests répétés. Mais, c'est une exception. En règle générale, je n'utilise pas de code que je n'ai pas compris moi-même dans le détail.

 
Georgiy Merts:

La fonction fonctionne vraiment bien. Je l'ai vérifié plusieurs fois, aucune erreur ne s'est produite. Mais je ne comprends toujours pas comment le résultat est formé dans cet horrible retour, malgré mon expérience, à mon avis, suffisamment bonne. D'ailleurs, fxsaber lui-même a répondu à la question qu'il ne s'en souvient pas lui-même.

Il ne s'agit pas de rapatriés. Si vous décrivez la même logique sous la forme de if-else, je ne la comprendrai pas mieux. C'est exactement le cas lorsque l'on prend le problème du "remplissage non soutenu" et qu'on l'étudie très profondément. Il faut écrire beaucoup de code de stress associé, ouvrir beaucoup de comptes sur différents serveurs torus et courir à travers tous les symboles. Trouver des modèles parmi différentes combinaisons de drapeaux. Et enfin, pour ramener tous les tableaux au même dénominateur. C'est là que le "je ne me souviens pas" entre en jeu.

Le problème n'existe plus et il est oublié. C'est génial quand on n'a pas besoin de revenir à un code déjà écrit. Il fonctionne - c'est l'essentiel.

Raison: