Interessante Sicht auf die PLO - Seite 10

 
Vitaly Muzichenko:

Dieses Design gefällt mir überhaupt nicht, was die Lesbarkeit und die Unübersichtlichkeit angeht.

Ich stimme zu)))

Die einzige Rechtfertigung dafür ist die Fehlersuche)

 
Vitaly Muzichenko:

Dieses Design gefällt mir überhaupt nicht, was die Lesbarkeit und die Unübersichtlichkeit angeht.

das war ursprünglich meine Frage

die letzten beispiele sind die aussage von @fxsaber, dass sich die codes zur laufzeit zu 100% unterscheiden. ich habe den disassembler des debuggers vor ein paar seiten gepostet - die codes sind zu 90% identisch

Ich spreche nicht davon, dass einfache Konstrukte, die ohne Probleme gelesen werden, nicht zurückgegeben werden können.

 
Igor Makanu:

die Entwickler schrieben irgendwo und hier ähnliche Informationen

fand nur dies:

switch ist ein sicheres goto, das eine Sprungtabelle verwendet. Das heißt, die Adresse "case" wird anhandeines ganzzahligenSchlüssels in switch berechnet. Aus diesem Grund ist switch selbst im Vergleich zu if-else extrem effizient, ganz zu schweigen von fortgeschritteneren Sammlungen wie Wörterbüchern.

 
fxsaber:

Hat dies nicht den negativen Effekt, dass man jeden Qualitätscode in der Erwartung schreibt, dass "der Compiler ihn schon auf das Optimum bringen wird"?

Bei einem bestimmten Schreibstil können Sie sicher sein, dass der Compiler das Richtige tut. Bei einem anderen Stil muss man einfach darauf vertrauen, dass der Compiler schlauer ist.

In Anbetracht von plattformübergreifenden, unterschiedlichen Compilern usw. möchte ich wissen, was Sie im Code tun.

Nur der Compiler weiß genau, was er tun wird. Die heutigen Compiler haben eine erstaunliche Euristik. Sie stellen sich auf den durchschnittlichen Codierer ein und wissen bereits besser, was er oder sie braucht. Das Beste, was ein Compiler tun kann, ist, einfachen, überschaubaren Code mit kurzen Funktionen zu schreiben. Für den Compiler ist es einfacher und effizienter, den aus vielen Funktionsknoten bestehenden Quellcodegraphen zu analysieren, um das resultierende Programm zu erstellen. Dies kann sich nur positiv auf die Leistung auswirken, da die benötigten Funktionen an den richtigen Stellen eingefügt werden.

 
Vasiliy Sokolov:

switch ist ein sicheres goto, das eine Sprungtabelle verwendet. Das heißt, die "case"-Adresse wird ausdem Integer-Schlüssel in switch berechnet. Aus diesem Grund ist switch selbst im Vergleich zu if-else äußerst effizient, ganz zu schweigen von fortgeschritteneren Sammlungen wie Wörterbüchern.

cool! Das sind nützliche Informationen

Danke!

 

Viele Leute empfehlen, kleine Klassen zu schreiben. Derselbe Eckel sagt: "Erstellen Sie Klassen für einen einzigen, klar definierten Zweck".

Ich arbeite gerade an einem EA, und ich werde eine kleine Vereinfachung für ein Beispiel schreiben. Es gibt einen der Parameter "Reach max stoploss". Wenn man SL erhält, sollte es als Rückgabezähler auf Null funktionieren und die Arbeit des EA stoppen, und wenn man TP erhält, sollte es auf den Anfangswert zurückgesetzt werden, wobei der Wert auf dem Panel angezeigt wird.

Für diesen Zähler habe ich eine eigene Klasse erstellt. Es stellt sich heraus, dass sich der Wert an mehreren Stellen ändert, nämlich bei OnInit beim Setzen der Eingabeparameter und im Eingabefeld des Panels nach Auftragsabschluss (sl und tp ändern den Wert unterschiedlich). Außerdem wird die Hauptfunktion von OnTick() aus aufgerufen, um die maximale Anzahl von Stoplosses zum Stoppen des EA zu verfolgen.

Die Klasse scheint sehr einfach zu sein. Es stellt sich jedoch heraus, dass diese kleine Klasse andere Objekte im Panel (Eingabefeld, Schaltflächen) beeinflusst. Sie beeinträchtigt den Betrieb anderer Funktionen. Und wenn es ein Dutzend solcher kleiner Klassen gibt, ist es schon schwierig zu verfolgen, welche Funktionen das Objekt verändern oder welche Methoden einiger Objekte den Zustand anderer Objekte verändern können.

Ich möchte wissen, wie man die Interaktion von Objekten miteinander am besten organisiert, um die Verwirrung zu verringern. Gibt es irgendwelche guten Artikel oder Bücher mit Beispielen von Codes, Diagrammen zu diesem Thema und guten Erklärungen? Bitte teilen Sie mit, was jemandem geholfen hat, zu lernen, wie man gut konzipierte Architekturen schreibt.

 
Dies ist kein OOP-Problem, sondern ein Problem mit dem allgemeinen Ansatz zur Erstellung von EAs. Wir sollten die Anzahl der Stoplosses in der Geschichte zählen. Dafür ist im Allgemeinen der Kopf eines Mannes zuständig, eine Universallösung gibt es nicht.
 
Vitaly Muzichenko:

Dieses Design gefällt mir überhaupt nicht, was die Lesbarkeit und die Unübersichtlichkeit angeht.

Geschmack und Farbe.... alle Filzstifte sind unterschiedlich.

Es war ein Kontrast zu dem "kleinen Monster":

Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien

Interessante Meinung über OOP

fxsaber, 2021.01.31 01:09

Ein 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 ein übersichtliches Schreiben bei der Verwendung verschiedener Einstellungen über Makros. Aber es ist natürlich ein Horror.


 
Andrey Khatimlianskii:

Geschmack und Farbe.... alle Filzstifte sind unterschiedlich.

Das stimmt nicht. Sie unterscheiden sich nur in der Farbe, aber sie schmecken alle gleich...))))

 
Vitaly Muzichenko:

Dieses Design gefällt mir überhaupt nicht, was die Lesbarkeit und die Unübersichtlichkeit angeht.

Und warum?

Im Gegenteil, mit zwei "ifs" ist es viel einfacher als mit dem "or"-Operator.

Es ist einfacher, zuerst eine Bedingung zu prüfen und die Funktion zu verlassen, wenn sie wahr ist, und dann eine andere Bedingung zu prüfen und ebenfalls zu verlassen, wenn sie wahr ist, als zu versuchen, das Ergebnis einer komplexen Bedingung mit logischem "oder" (das leicht mit "und" verwechselt werden kann) zu erraten und beide Rückgabewege zu verfolgen.

Es ist ziemlich lustig, unten zu lesen, dass "die Rechtfertigung für solche ist Debugging", weil es bedeutet, dass solche Code ist viel verständlicher (sonst warum ist es in Debugging?).

"Apotheose" halte ich für einen Ausdruck von fxsaber, zu dem er selbst nicht sagen konnte, wie er funktioniert, sondern nur sagte, dass "der Code wiederholt getestet wurde und er funktioniert". Das sollte meiner Meinung nach nicht der Fall sein:

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

Dieser Code prüft, obder Befehl otfFilingTypeausgeführt werden kann, und gibt ihn zurück, wenn er auf strSymbol verfügbar ist, andernfalls ist er korrekt.


Ich habe absolut keine Ahnung, wie das funktioniert. Und verlassen Sie sich nur auf die Autorität von fxsaber.

Vielleicht kann das jemand erklären?