Interessante Sicht auf die PLO - Seite 8

 
fxsaber:

Ich schreibe so, weil ich es mag. Allerdings wird es beim Debuggen richtig schlimm.


Auch in diesem Ausdruck.

ist es schwer herauszufinden, wer was zurückgegeben hat. In komplexeren Fällen (ich übe das ständig) ist es wirklich schwierig.

Wenn Sie 2-3... Nehmen wir an, dass 5 Ergebnisse der Ausführung von Funktionen durch logische Operationen (oder bedingte ternäre Operatoren) vereint sind - ich habe es auf Githab oder irgendwo anders gesehen, dieser Code kann gehandhabt werden

Aber wenn Sie ein Dutzend dieser "Leckereien" haben... imho ist es nicht praktisch

 
Maxim Kuznetsov:

Ich bin natürlich kein mql-Entwickler,

aber in C erzeugt switch eine recht effiziente binäre Suche und verursacht keine unnötigen Seitenauslagerungen oder Cache-Dumps. Ja, das ist oft besser als die indirekte Adressierung über Arrays und Strukturen.

die Entwickler schrieben irgendwo und hier ähnliche Informationen

fand nur dies:

Forum zum Thema Handel, automatisierte Handelssysteme und Strategietests

Dies ist der Artikel, den wir in MQL5 gefunden haben.

Slawa, 2011.04.14 09:59

Nein, das wird es leider nicht. Bei String-Typen nur, wenn ... sonst wenn ... sonst

Die Verwendung von Integer-Typen in switch beschleunigt den Code des Analysators um ein Vielfaches im Vergleich zu


 
Igor Makanu:

aber wenn es ein Dutzend oder so ist... Imho ist das nicht praktikabel.

Kleines Ungeheuer.

  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__
           );
  }

Logische Operationen ermöglichen es Ihnen, bei der Verwendung verschiedener Einstellungen über Makros kurz und bündig zu schreiben. Aber es ist natürlich ein Horror.

 
fxsaber:

Dielogischen Operationen ermöglichen ein übersichtliches Schreiben bei der Verwendung verschiedener Einstellungen über Makros. Aber es ist natürlich ein Horror.

Ihr Beispiel von "der Zweck heiligt die Mittel"

meine Frage bezog sich auf einen ganz anderen und unverständlichen Stil

 
fxsaber:

Das kleine Ungeheuer.

Einem geschenkten Gaul schaut man nicht ins Maul. Aber hier sind noch ein paar Beispiele für den Code anderer Leute, die mir ein paar unvergessliche Dutzend Minuten Debugging beschert haben. Vielleicht erkennt jemand seinen eigenen Code.

      Res = (!FillingMode || (Type >= ORDER_FILLING_RETURN) || ((FillingMode & (Type + 1)) != Type + 1)) ?
            (((ExeMode == SYMBOL_TRADE_EXECUTION_EXCHANGE) || (ExeMode == SYMBOL_TRADE_EXECUTION_INSTANT)) ?
             ORDER_FILLING_RETURN : ((FillingMode == SYMBOL_FILLING_IOC) ? ORDER_FILLING_IOC : ORDER_FILLING_FOK)) :
            (ENUM_ORDER_TYPE_FILLING)Type;
    return((arrow_color == INT_MAX) ? (MT4ORDERS::NewOrderCheck() ? 0 : -1) :
           ((((int)arrow_color != INT_MIN) || MT4ORDERS::NewOrderCheck()) &&
            MT4ORDERS::OrderSend(MT4ORDERS::LastTradeRequest, MT4ORDERS::LastTradeResult) ?
            (MT4ORDERS::IsHedging ? (long)MT4ORDERS::LastTradeResult.order : // PositionID == Result.order - особенность MT5-Hedge
             ((MT4ORDERS::LastTradeRequest.action == TRADE_ACTION_DEAL) ?
              (MT4ORDERS::IsTester ? (_B2(::PositionSelect(MT4ORDERS::LastTradeRequest.symbol)) ? PositionGetInteger(POSITION_TICKET) : 0) :
                                      // HistoryDealSelect в MT4ORDERS::OrderSend
                                      ::HistoryDealGetInteger(MT4ORDERS::LastTradeResult.deal, DEAL_POSITION_ID)) :
              (long)MT4ORDERS::LastTradeResult.order)) : -1));

Ich weiß nicht, ob es einfach war, es so zu schreiben, aber es ist unwirklich, es zu debuggen, und erst recht, es zu lesen. Und ich sehe auch keine objektiven Gründe dafür, es so zu schreiben.

 
traveller00:

Und ich sehe auch keine objektiven Gründe dafür, es so zu schreiben.

Sie sind natürlich subjektiv. Ich mag keine unnötigen Variablen und Mehrfachrückgaben. Aus irgendeinem Grund glaube ich, dass EX5 ohne sie kürzer und schneller ausgeführt werden kann.

 
fxsaber:

Sie sind natürlich subjektiv. Ich mag keine zusätzlichen Variablen und Mehrfachrückgaben. Aus irgendeinem Grund glaube ich, dass EX5 ohne sie kürzer und schneller sein wird.

Diese Zuversicht, dass der Code kürzer und schneller sein wird, ist übrigens nicht gerechtfertigt.

hier ist es

bool a=A();
bool b=B();
//....много промежуточных результатов
bool x=X();
bool Res=a||b||x ;
return Res;

und dies

return A()||B()||X();

Ich bin sicher, dass die Geschwindigkeit (und vielleicht auch die Größe des Codes und des verwendeten Speichers) die gleiche sein wird.

Es ist nur so, dass die zweite Variante schneller zu schreiben ist und jeder sie schreibt, und dann, wenn es notwendig ist, etwas hinzuzufügen/zu verkomplizieren, belassen sie die zweite Variante, aber aufgebläht zu einer schwer lesbaren Variante.

Sie sollten in dieser Hinsicht regelmäßig ein Refactoring durchführen, und Sie werden keine Probleme haben.

 
Aleksey Mavrin:

Führen Sie in dieser Hinsicht regelmäßig Refactoring durch, und es wird keine Probleme geben.

Nur für diejenigen, die viel Freizeit haben oder objektiv so unter Zeitdruck stehen, dass es ohne sie gar nicht geht.

Bei einer hohen Rücklaufquote wird der Code zu 100 % anders sein.
 
fxsaber:

Nur für diejenigen, die viel Freizeit haben oder objektiv so unter Zeitdruck stehen, dass es ohne sie gar nicht geht.

ZS Wenn es viele Rückgaben gibt, wird der Code zu 100 % anders sein.

Ich verstehe das, stimme aber teilweise zu. Ich denke nur, dass jeder die Erfahrung gemacht hat, dass es relativ lange dauert, Fehler zu beheben, die schneller gefunden würden, wenn der Code "perfekt" zum Debuggen bereit wäre.

Es ist unklar, was mehr Zeit in Anspruch nimmt - das längere Schreiben von "brauchbarem" Code oder das Debuggen und Finden von Fehlern, es ist wohl immer etwas anderes.

 
fxsaber:

Wenn es viele Rückläufer gibt, wird der Code zu 100 % anders sein.

C++ VS2019 unter Debugger

Quellcode:

bool a(int v) { return(v > 0); }
bool b(int v) { return(v < 0); }
bool c(int v) { return(v == 0);}

bool tst1(int v1, int v2, int v3)
{
        if (a(v1)) return(true);
        if (b(v2)) return(true);
        if (c(v3)) return(true);
        return(false);
}

bool tst2(int v1, int v2, int v3)
{
        return(a(v1) && b(v2) && c(v3));
}

int main()
{
        int x = 1, y=2, z=3;
        bool result1 = tst1(x, y, z);
        bool result2 = tst2(x, y, z);
}

Asm-Debugger

bool tst1(int v1, int v2, int v3)
{
        if (a(v1)) return(true);
000 E1918  mov         eax,dword ptr [v1]  
000 E191B  push        eax  
000 E191C  call        a (0 E137Ah)  
000 E1921  add         esp,4  
000 E1924  movzx       ecx,al  
000 E1927  test        ecx,ecx  
000 E1929  je          tst1+3 Fh (0 E192Fh)  
000 E192B  mov         al,1  
000 E192D  jmp         tst1+6 Fh (0 E195Fh)  
        if (b(v2)) return(true);
000 E192F  mov         eax,dword ptr [v2]  
000 E1932  push        eax  
000 E1933  call        b (0 E13ACh)  
000 E1938  add         esp,4  
000 E193B  movzx       ecx,al  
000 E193E  test        ecx,ecx  
000 E1940  je          tst1+56 h (0 E1946h)  
000 E1942  mov         al,1  
000 E1944  jmp         tst1+6 Fh (0 E195Fh)  
        if (c(v3)) return(true);
000 E1946  mov         eax,dword ptr [v3]  
000 E1949  push        eax  
000 E194A  call        c (0 E11B8h)  
000 E194F  add         esp,4  
000 E1952  movzx       ecx,al  
000 E1955  test        ecx,ecx  
000 E1957  je          tst1+6 Dh (0 E195Dh)  
000 E1959  mov         al,1  
000 E195B  jmp         tst1+6 Fh (0 E195Fh)  
        return(false);
000 E195D  xor         al,al  
}


bool tst2(int v1, int v2, int v3)
{
        return(a(v1) && b(v2) && c(v3));
000 E19C8  mov         eax,dword ptr [v1]  
000 E19CB  push        eax  
000 E19CC  call        a (0 E137Ah)  
000 E19D1  add         esp,4  
000 E19D4  movzx       ecx,al  
000 E19D7  test        ecx,ecx  
000 E19D9  je          tst2+6 Dh (0 E1A0Dh)  
000 E19DB  mov         edx,dword ptr [v2]  
000 E19DE  push        edx  
000 E19DF  call        b (0 E13ACh)  
000 E19E4  add         esp,4  
000 E19E7  movzx       eax,al  
000 E19EA  test        eax,eax  
000 E19EC  je          tst2+6 Dh (0 E1A0Dh)  
000 E19EE  mov         ecx,dword ptr [v3]  
000 E19F1  push        ecx  
000 E19F2  call        c (0 E11B8h)  
000 E19F7  add         esp,4  
000 E19FA  movzx       edx,al  
000 E19FD  test        edx,edx  
000 E19FF  je          tst2+6 Dh (0 E1A0Dh)  
000 E1A01  mov         dword ptr [ebp-0 C4h],1  
000 E1A0B  jmp         tst2+77 h (0 E1A17h)  
000 E1A0D  mov         dword ptr [ebp-0 C4h],0  
000 E1A17  mov         al,byte ptr [ebp-0 C4h]  
}



reduziert durch Befehle einen Aufruf nur in 2 Spalten nicht zu zählen:

ts1:                                                    tst2:
000 E1918  mov         eax,dword ptr [v1]                000 E19C8  mov         eax,dword ptr [v1]
000 E191B  push        eax                               000 E19CB  push        eax  
000 E191C  call        a (0 E137Ah)                       000 E19CC  call        a (0 E137Ah)  
000 E1921  add         esp,4                             000 E19D1  add         esp,4  
000 E1924  movzx       ecx,al                            000 E19D4  movzx       ecx,al  
000 E1927  test        ecx,ecx                           000 E19D7  test        ecx,ecx  
000 E1929  je          tst1+3 Fh (0 E192Fh)                000 E19D9  je          tst2+6 Dh (0 E1A0Dh)  
000 E192B  mov         al,1                              000 E19DB  mov         edx,dword ptr [v2]  
000 E192D  jmp         tst1+6 Fh (0 E195Fh)                000 E19DE  push        edx 


wie Sie hier sehen können, und die Befehle wiederholen sich fast, ist es klar, dass Sie im ersten Test mehr Rückgaben hinzufügen müssen

Mit 99%iger Sicherheit denke ich, dass diese Codes auf der Prozessorebene bis zu einem Takt mit der gleichen Geschwindigkeit laufen werden - im Prozessor funktionieren Optimierung, Parallelisierung und wer weiß, was sonst noch auf der Ebene der Mikrobefehle