OOP vs. prozedurale Programmierung - Seite 23

 
Maxim Kuznetsov:

Sieht so aus, als hätten Sie das Geplauder verpasst :-) die Moderatoren sind gegen flammende Themen vorgegangen ... aber hier geht es um OOP vs.

Übrigens, 99% von @Peter Konow's verwendet OOP, aber er ist sich dessen nicht bewusst :-) OOP ist nicht unbedingt "Klasse und Vorlage".

Und umgekehrt... das Vorhandensein von Objekten und Klassen in einem Programm ist kein Hinweis auf OOP

Das ist ein sehr interessanter Gedanke. Vielleicht ist es so, aber ich vermute es nicht. ))


Aber woher wissen Sie das?

 
Реter Konow:

Das ist ein sehr interessanter Gedanke. Vielleicht ist es so, aber ich vermute es nicht. ))


Und woher wissen Sie davon?

Zum Beispiel kann die OO durch Message Dispatching implementiert werden (und mit einigen "Pluspunkten", die nicht in der Klasse/Template MQL sind),

Ich habe nicht durch Ihren Code gesehen und wahrscheinlich nicht in der Lage sein, es zu lesen, aber da Sie GUI-Bibliothek verwenden, bin ich sicher, es hat mindestens eine Warteschlange und Ereignisse/Satz/Zustände Verarbeitung hat eine Menge von Wendungen. Und genau diese "Verdrehung" ist letztendlich nur Vererbung/Polymorphismus.

 
Dmitry Fedoseev:

Über den Igel:

"Der Igel steht auf der Lichtung, posiert und lässt seinen Bizeps spielen: - Ich bin stark, ich bin mutig, ich bin wendig, ich bin stark, ich bin mutig, ich bin wendig...

Ein Bär kommt vorbei - tritt ihn einmal, der Igel flieht hinter den Baum, steht auf und schüttelt sich ab:

- Ich bin stark, ich bin mutig, ich bin beweglich... ...aber ich bin leicht...


Wie mein Freund aus Kindertagen zu sagen pflegte: Der Igel ist ein stolzer Vogel, wenn man ihn nicht tritt, fliegt er nicht ))
 
Alexey Volchanskiy:

Georges, ich bin heute mit einem Mädchen spazieren gegangen, wir haben ein bisschen geplaudert, wir haben uns ein bisschen an schüchterne Männer erinnert. Ehrlich gesagt, mache ich mich nicht lustig, jeder hat eine andere Persönlichkeit und eine andere Erziehung.

Oh... Und Lekha ist für Tussis... Und das zu Recht. Viel interessanter als die GOP.

Nun, mein Problem ist nicht Schüchternheit. Das Einzige, womit ich mich rühmen kann, ist die "gut abgehangene Zunge". Mein Problem ist der Vaginozentrismus mit der Mittellosigkeit. Ich lege zu viel Wert auf Privatsphäre und Sex. Sie schrieben oben: "...ich habe gesehen, wie hart Männer arbeiten können, wenn schöne Frauen vor ihnen stehen." Nun, ich bin einer von diesen Typen. Aber die Mädels brauchen dich, solange du noch jung, stark und reich bist. Und wenn eine Frau die Möglichkeit hat, dich zu verarschen, dann wird sie dich früher oder später auch verarschen. Selbst ein junger, starker und reicher Mann. Ich bin ein mittelloser alter Invalide ohne Zuhause. Meine Chancen sind also gleich null... Ich bin nicht einmal überrascht, dass meine Frau mich verlassen hat. Nur scheint es Sie nicht zu interessieren, dass Sie geschieden sind. Ich hingegen finde es äußerst frustrierend, dass ich nicht die Voraussetzungen dafür schaffen konnte, dass meine Frau mich nicht verlassen kann.

 

Und über OOP...

Hätte ich das gleiche Gedächtnis wie Retag Konow, würde ich wahrscheinlich zustimmen, dass OOP unnötig ist, wozu all diese Schnittstellen, Klassen, Objekte, Vererbungssysteme und virtuelle Funktionen...

Alexey sagte richtig - der Prozessor weiß nichts über irgendwelche Objekte... Es weiß nicht einmal etwas über Funktionen. Das beweist, dass jede Aufgabe nicht nur ohne OOP, sondern sogar ohne Funktionen gelöst werden kann, indem man sich einfach Rücksprungadressen merkt und die Kontrolle über IP-Register (oder was auch immer moderne CPUs heutzutage verwenden) weitergibt.

Ich habe den Standpunkt von Retug Konow nicht verstanden, bis er mir seinen Code zeigte. Jetzt ist alles klar, und ich kann ihm sogar zustimmen, wenn ich es schaffe, alles im Gedächtnis zu behalten, und lange Wenns mich nicht stören, vermute ich, dass es vernünftiger ist, es so zu schreiben, wie er es tut. Außerdem wird OOP in diesem Fall wirklich zu einem "fünften Rad am Wagen".

Aber mein persönliches Problem ist, dass mir die meisten Feinheiten der Arbeit entgehen. Ich vergesse zum Beispiel immer, wofür jeder Index im mehrdimensionalen Array G_CORE zuständig ist; bei jeder Bedingung in einem bestimmten Fragment werde ich jedes Mal ernsthaft darüber nachdenken, was sie definiert. Auch die Analyse der langen Laufzeiten wird für mich spannend sein.

Und manchmal schreibe ich selbst solchen Code, der schwer zu verstehen ist. Hier ist ein Fragment MEINES"falschen" Codes, in dem ich auf dieselbe Weise untergehe (ich habe es oben zitiert):

virtual bool IsTPCInUnloss() const { if(GetTPCStopLoss() <= 0 || GetTPCStopLoss() == EMPTY_VALUE) return(false); if(GetTPCType() == POSITION_TYPE_BUY) { if(GetTPCStopLoss() >= GetTPCOpenPrice()) return(true); } else { if(GetTPCStopLoss() <= GetTPCOpenPrice())return(true); }; return (false); };

Dies ist die Funktion der Handelskomponenten-Schnittstelle CTradePosComponentI, die feststellt, ob diese Komponente den Break-even erreicht hat.

"Das "Falsche" an diesem Code ist, dass hier die Lesbarkeit auf Kosten der Kompaktheit und Lesbarkeit geopfert wird. Da die Funktion in die Schnittstelle integriert ist, wollte ich, dass die gesamte Schnittstelle möglichst auf einem Bildschirm sichtbar ist. Nur damit ich mir nicht merken muss, welche Funktionen sie bietet, damit ich alle Funktionen auf einmal sehen kann. Wenn ich mich an alles erinnern würde, wäre es nicht nötig, die Funktion in eine Zeichenkette zu "strecken". Die Funktion dehnte sich also auf ein Dutzend Zeilen aus - gut... Es war mir jedoch wichtig, dass alle Funktionen nebeneinander in die Oberfläche passen und alle sichtbar sind. Ich wollte, dass ein Blick auf die Benutzeroberfläche mir sofort eine Vorstellung von den Funktionen vermittelt, die sie bietet. Aus diesem Grund musste ich die Funktionen in einer langen Zeile ausschreiben. Es ist jedoch völlig unrealistisch, das zu verstehen.

Beim Schreiben des Codes habe ich diese Funktion anfangs ganz anders geschrieben. In klarer Form und mit Kommentaren. Damit ich es verstehen kann.

Zum Beispiel so:

virtual bool IsTPCInUnloss() const 
{ 
    // Отсеем вариант, когда СЛ отсутствует
    if(GetTPCStopLoss() <= 0 || GetTPCStopLoss() == EMPTY_VALUE)
         return(false);

    //  Проверим тип торговой компоненты
    if(GetTPCType() == POSITION_TYPE_BUY)
        { 
        // Торговая компонента - лонг
        if(GetTPCStopLoss() >= GetTPCOpenPrice())
            return(true);
        }
    else
        { 
        // Торговая компонента - шорт
        if(GetTPCStopLoss() <= GetTPCOpenPrice())
             return(true); 
        }; 

    return (false); 
};

Und erst nachdem dies alles getestet und debuggt wurde, wurde der Code von Kommentaren befreit und "auf Linie gebracht".

Dies ist jedoch eine Ausnahme. Ich tue dies sehr selten, in besonderen Fällen, wenn die "Sichtbarkeit" wichtig ist. In allen anderen Fällen schreibe ich den Code sowohl "breit" als auch mit Einrückung und mit Kommentaren an jeder Stelle, an der es die geringste Schwierigkeit mit der Frage "was ist hier" geben könnte.

Sonst vergesse ich sehr schnell, wo, was und wofür es ist.

 
Maxim Kuznetsov:

Zum Beispiel ist OO durch Message Dispatch durchaus machbar (und mit einigen "Pluspunkten", die nicht in der Klasse/Template MQL enthalten sind),

Ich habe nicht durch Ihren Code gesehen und kann es nicht lesen, aber da Sie GUI-Bibliothek haben, bin ich sicher, es hat seine eigene (mindestens eine) Warteschlange und durch die Verarbeitung von Ereignissen/Sätzen/Zuständen gibt es viele Dinge vermasselt. Und genau diese "Verdrehung" ist letztendlich nur Vererbung/Polymorphismus.

Nun, da ich "A" gesagt habe, muss ich auch "B" sagen). Ich werde meine Technologie genauer beschreiben.

Indem ich die Funktionen, die an einer bestimmten Art von Aufgaben arbeiten, in großen Blöcken zusammenfasse, reduziere ich die Anzahl der Verbindungen, die zwischen den Funktionen hergestellt werden müssen. Das hat seine Vor- und Nachteile.

Zunächst zu den Profis:

In der OOP erfordert ein Mechanismus, der in eine große Anzahl von Funktionen unterteilt ist, die Erstellung vieler Objekte, um eine Verbindung zwischen den Klassen und den Strukturen herzustellen. Gleichzeitig ist jeder Funktionsprototyp von einer großen Anzahl von formalen Parametern umgeben, über die die Funktion mit dem umgebenden Code kommuniziert. Die interne Struktur des Codes wird komplexer, gerade weil die Verbindungen zwischen den Teilen des Mechanismus während der Entwicklung dieses Mechanismus zunehmen.

In meiner Technologie wird die Kommunikation zwischen Funktionen und Blöcken vollständig durch die Verwendung globaler Variablen vereinfacht, die durchgängig eingeprägt sind. Funktionen brauchen keine Parameter zu übergeben, da sie diese sofort auf der globalen Ebene sehen.

Globale Variablenwerte werden durch den Objektfokusblock gesetzt, der den Cursor "verfolgt". Es verwendet die aktuellen Koordinaten des Cursors, um festzustellen, auf welches Objekt die Maus gerichtet ist, und greift auf den Kernel (G_CORE) zu, in dem alle Eigenschaften aller Elemente, Objekte und Fenster gespeichert sind. Vom Kernel übernimmt der Block die aktuellen Werte aller Haupteigenschaften des Objekts unter dem Cursor und legt sie in den globalen Variablen ab. Bewegt sich der Cursor über die Objekte, werden die globalen Variablen in diesem Block neu definiert und entsprechen immer dem Objekt, das im Fokus steht.

Als nächstes erfasst die Funktion OnChartEvent() Diagrammereignisse, die den Zustand des Elements unter dem Cursor ändern sollen. Bei diesen Ereignissen sieht der Statuskontrollblock (der in OnChartEvent() selbst integriert ist) sofort, welches Fenster, Element und Objekt im Fokus ist und welche Eigenschaften es hat. Sie brauchen diesem Block nichts zu übergeben, denn alles, was Sie brauchen, ist bereits im Fokus, in globalen Variablen. Seine Aufgabe ist es, die Werte der Objekteigenschaften im G_CORE-Kernel zu ändern und das Element neu zu zeichnen. Er ändert die Werte und ruft den Draw-Block auf.

Dem Zeichenblock müssen nur drei Parameter übergeben werden - Fenster, Leinwand und Element. Das Element wird neu gezeichnet und erhält ein seinem aktuellen Zustand entsprechendes Aussehen. Alle Hilfsfunktionen des Malblocks verwenden ebenfalls globale Variablen im Fokus. Zum Beispiel verwendet die obige Funktion "Farbteil()" "WINDOW", "OBJECT", "CATEGORY_OBJECT" usw... Sie sind alle sehr praktisch.


Nun zu den Nachteilen:

Zweifellos vereinfachen große Blöcke und Fokus-Objekte die Beziehung zwischen den Code-Teilen, aber es ist wegen der Tatsache, dass die Blöcke groß sind, was zu Schwierigkeiten bei der Arbeit mit ihnen. Die russische Sprache und die totale Vereinfachung der Syntax helfen mir hier, da ich keine OOP verwende.

Mit der Zeit erreichen die Blöcke einen Punkt, an dem sie nicht mehr verändert werden müssen und nicht mehr wachsen. Nach und nach prägt man sich ihre Struktur vollständig ein und vereinfacht die Arbeit mit ihnen auf das Äußerste.

Natürlich ist das Schleifen von Blöcken an sich eine ziemlich langwierige und schmerzhafte Angelegenheit, aber genau darum geht es bei der Fehlersuche in jedem Mechanismus.

 
George Merts:

Und über OOP...

Hätte ich das gleiche Gedächtnis wie Retag Konow, würde ich vielleicht zustimmen, dass OOP unnötig ist, wozu all diese Schnittstellen, Klassen, Objekte, Vererbungssysteme und virtuelle Funktionen...

Alexey sagte richtig - der Prozessor weiß nichts über irgendwelche Objekte... Es weiß nicht einmal etwas über Funktionen. Das beweist, dass jede Aufgabe nicht nur ohne OOP, sondern sogar ohne Funktionen gelöst werden kann, indem man sich einfach Rücksprungadressen merkt und die Kontrolle über IP-Register (oder was auch immer moderne CPUs heutzutage verwenden) weitergibt.

Ich habe den Standpunkt von Retug Konow nicht verstanden, bis er mir seinen Code zeigte. Jetzt ist alles klar, und ich kann ihm sogar zustimmen, wenn ich es schaffe, alles im Gedächtnis zu behalten, und lange Wenns mich nicht stören, vermute ich, dass es vernünftiger ist, es so zu schreiben, wie er es tut. Außerdem wird OOP in diesem Fall wirklich zu einem "fünften Rad am Wagen".

Aber mein persönliches Problem ist, dass mir die meisten Feinheiten der Arbeit entgehen. Ich vergesse zum Beispiel immer, wofür jeder Index im mehrdimensionalen Array G_CORE zuständig ist; bei jeder Bedingung in einem bestimmten Fragment werde ich jedes Mal ernsthaft darüber nachdenken, was sie definiert. Auch die Analyse der langen Laufzeiten wird für mich spannend sein.

Und manchmal schreibe ich selbst solchen Code, der schwer zu verstehen ist. Hier ist ein Fragment MEINES"falschen" Codes, in dem ich auf dieselbe Weise untergehe (ich habe es oben zitiert):

Dies ist die Funktion der Handelskomponenten-Schnittstelle CTradePosComponentI, die feststellt, ob diese Komponente den Break-even erreicht hat.

"Das "Falsche" an diesem Code ist, dass hier die Lesbarkeit auf Kosten der Kompaktheit und Lesbarkeit geopfert wird. Da die Funktion in die Schnittstelle integriert ist, wollte ich, dass die gesamte Schnittstelle möglichst auf einem Bildschirm sichtbar ist. Nur damit ich mir nicht merken muss, welche Funktionen sie bietet, damit ich alle Funktionen auf einmal sehen kann. Wenn ich mich an alles erinnern würde, wäre es nicht nötig, die Funktion in eine Zeichenkette zu "strecken". Die Funktion dehnte sich also auf ein Dutzend Zeilen aus - gut... Es war mir jedoch wichtig, dass alle Funktionen nebeneinander in die Oberfläche passen und alle sichtbar sind. Ich wollte, dass ein Blick auf die Benutzeroberfläche mir sofort eine Vorstellung von den Funktionen vermittelt, die sie bietet. Aus diesem Grund musste ich die Funktionen in einer langen Zeile ausschreiben. Es ist jedoch völlig unrealistisch, das zu verstehen.

Beim Schreiben des Codes habe ich diese Funktion anfangs ganz anders geschrieben. In klarer Form und mit Kommentaren. Damit ich es verstehen kann.

Zum Beispiel so:

Und erst nachdem all dies getestet und debuggt worden war, wurde der Code von Kommentaren befreit und "auf die Linie gezogen".

Dies ist jedoch eine Ausnahme. Ich mache das sehr selten - vor allem dann, wenn "Sichtbarkeit" wichtig ist. In allen anderen Fällen schreibe ich den Code sowohl "breit" als auch eingerückt und mit Kommentaren an jeder Stelle, an der auch nur die geringste Frage auftauchen könnte: "Was ist hier?".

Sonst vergesse ich sehr schnell, wo, was und wofür es ist.

Unsere Aufgaben sind sehr unterschiedlich, daher kann ich nur schwer etwas zu Ihren Lösungen sagen. Ich bin mir nicht sicher, ob es nur an meinem Gedächtnis liegt, es muss etwas anderes sein. Wenn Sie Ihren eigenen Code verstehen, können Sie ihn sich zweifellos besser merken. Ich will damit nicht sagen, dass Ihr Code weniger sinnvoll ist. Ich weiß nur nicht, wie ich Ihre Probleme angehen würde. Vielleicht ist Ihr Ansatz der richtige. Ich urteile nicht. Ich persönlich finde diese Art von Code sehr schwer zu verstehen.

Das ist wohl eine Frage der Gewohnheit.)

 
Реter Konow:

Unsere Aufgaben sind sehr unterschiedlich, daher kann ich nur schwer etwas zu Ihren Lösungen sagen. Ich bin mir nicht sicher, ob es nur an meinem Gedächtnis liegt, es muss etwas anderes sein. Wenn Sie Ihren eigenen Code verstehen, können Sie ihn sich zweifellos leichter merken. Ich will damit nicht sagen, dass Ihr Code weniger sinnvoll ist. Ich weiß nur nicht, wie ich Ihre Probleme angehen würde. Vielleicht ist Ihr Ansatz der richtige. Ich urteile nicht. Ich persönlich finde diese Art von Code sehr schwer zu verstehen.

Wahrscheinlich ist es eine Frage der Gewohnheit.)


Es ist eine völlig sinnlose Diskussion: Es gibt kein Kriterium für die Einstufung von Code als "gut" oder "schlecht". Deshalb ist es nicht klar, was OOP ist.

Für mich ist ein solches Kriterium die FEASIBILITÄT des Codes, die sich darin äußert, dass der Autor oder ein Dritter den Code lesen und für Änderungen verwenden kann, wobei er nach einem längeren Zeitraum nach Fehlern sucht.....


Hier oben hat Fedoseyev den OOP-Schalter ersetzt. Dieses spezielle Beispiel, das vielleicht unglücklich ist, ist für mich ein Beweis für die Bösartigkeit von OOP: klarer Code mit einem Schalter mit 100 Positionen wird durch eine einzige Zeile ersetzt. Um diese Linie zu verstehen, muss man irgendwo ansetzen. Das ist für mich nicht zulässig.

Das zweite Beispiel obenvon George Merts

Wenn der klare Code nach der Fehlersuche durch NICHT klaren Code ersetzt wurde. Nach meinem Kriterium wurde Qualitätscode (leicht zu lesen) durch für mich inakzeptablen Code ersetzt.


Ich habe also eine Frage an alle OOP-Befürworter: Wird das Programm sichtbarer, wenn OOP angewendet wird, und ist das von Fedoseev angeführte Beispiel für den Schalter ein Fehlschlag, oder charakterisiert Fedoseevs Beispiel OOP sehr genau und führt OOP fast immer zu einem Verlust an Sichtbarkeit?

 
СанСаныч Фоменко:

1. Eine völlig sinnlose Diskussion: Es gibt kein Kriterium für die Einstufung von Code als "gut" oder "schlecht". Aus diesem Grund ist es nicht klar, was OOP ist.

Für mich ist ein solches Kriterium die FEASIBILITÄT des Codes, die sich darin äußert, dass der Autor oder ein Dritter den Code lesen und verwenden kann, um ihn zu ändern, Fehler nach einem längeren Zeitraum zu finden.....


2. Hier oben hat Fedoseyev den OOP-Schalter ersetzt. Dieses spezielle Beispiel, das vielleicht unglücklich ist, ist für mich ein Beweis für die Bösartigkeit von OOP: klarer Code mit einem 100-Positionen-Schalter wird durch eine einzige Zeile ersetzt. Um diese Linie zu verstehen, muss man irgendwo hingehen. Das ist für mich nicht zulässig.

Das zweite Beispiel obenvon George Merts

Wenn der klare Code nach der Fehlersuche durch NICHT klaren Code ersetzt wurde. Nach meinen Kriterien wurde der Qualitätscode (leicht lesbar) durch einen für mich inakzeptablen Code ersetzt.


3. Ich habe also eine Frage an alle OOP-Befürworter: Wird das Programm sichtbarer, wenn OOP angewandt wird, und ist das von Fedoseyev gegebene Beispiel für den Schalter ein Fehlschlag, oder ist Fedoseyevs Beispiel im Gegenteil eine sehr genaue Beschreibung von OOP und führt OOP fast immer zu einem Verlust an Sichtbarkeit?


1. Es gibt ein Kriterium. Das wichtigste Kriterium ist die Geschwindigkeit.

Die Klarheit des Codes ist das falsche Kriterium. Der Code wird nicht geschrieben, um angeschaut zu werden, sondern um zu funktionieren.

2. Ich sehe, es stellt sich heraus, dass einige von uns nicht reif genug sind, unseren Code mit Funktionen zu strukturieren. Sie sind also im falschen Thema, Sie sollten das Thema "einseitiger Code vs. funktionsstrukturierter Code" ansprechen.

Außerdem ging es bei der Probe nicht um Strukturierung und Klarheit/Nicht-Offensichtlichkeit, sondern um die Beseitigung von Ballast-Code-Fragmenten.

3... warum machst du nicht... Technische Grafik studieren? Oder die Darstellende Geometrie. Dort ist alles sehr visuell.

 
Dmitry Fedoseev:

Die Sichtbarkeit des Codes ist das falsche Kriterium. Code wird nicht geschrieben, um angeschaut zu werden, sondern um zu funktionieren.

Nun, da bin ich anderer Meinung.

Die Sichtbarkeit des Codes ist sehr wichtig, denn ein klarer Code ist viel einfacher zu pflegen und zu ändern.

Das stimmt - ich habe eine nackte Funktion geschrieben und sie dann tatsächlich "verschleiert", sie unsichtbar und unverständlich gemacht. Dies war eine erzwungene Entscheidung. In diesem Fall war es für mich wichtiger, die gesamte Klasse transparent zu machen. Ich habe die Klarheit einer recht trivialen Funktion geopfert. Natürlich hätten wir den Hauptteil dieser Funktion auch in die Datei .mq5 packen können, aber ich bin der Meinung, dass Schnittstellen nicht in zwei Dateien aufgeteilt werden sollten und vollständig in der Kopfdatei .mqh beschrieben werden sollten.

Geschwindigkeit ist auch etwas, das man im Auge behalten sollte, aber ich denke nicht, dass wir nach "Geschwindigkeit um jeden Preis" streben sollten. Es muss ein angemessenes Maß an Auskömmlichkeit gegeben sein.

Grund der Beschwerde: