«

»

Oct 25

Grundlagen einer gut strukturierten Programmierung

Nachdem die letzten Blog-Einträge schon sehr praktisch orientiert waren und für diverse Probleme Lösungen und Tools vorgestellt wurden, will ich heute einen “Schritt zurück” gehen und ein paar Grundlagen zum Thema Programmierung, insbesondere MQL-Programmierung erläutern.

Mit dem aktuellen Update von MetaQuotes auf MT4 Build 6xx, ist die gesamte MetaTrader-Entwicklungsumgebung deutlich aufgewertet wurden. Viele attraktive Features, wie sie schon lange in MQL5 vorhanden waren sind nun auch in MQL4 verfügbar, so dass es kaum noch Unterschiede in den Entwicklungsumgebungen gibt. Auf die Details der Unterschiede möchte ich an dieser Stelle aber nicht eingehen.

Vieles von dem, was wir im täglichen Arbeiten im Team, aber auch in Einzelprojekten verwenden, ist keine Neuerfindung von uns. Die Programmierung und natürlich auch guter Programmierstil ist schon lange vor MetaTrader erfunden worden. Trotzdem sehen wir fast täglich wirklich grauenvollen Source-Code. Man braucht nur in den zahlreichen Forex und MetaTrader Foren ein wenig stöbern … jedem der ein wenig Ahnung von halbwegs gutem Programmierstil hat, wird schaurig was man so alles zu sehen bekommt. Erst vor ein paar Tagen hat mir ein langjähriger, guter Kunde einen EA zur Überarbeitung zugesendet. Die Startfunktion hatte unfassbare 2000 Zeilen!

Damit wären wir auch schon beim ersten und wichtigsten Punkt den Sie bei der Programmierung Ihrer Expert-Advisor beachten sollten.

1. Funktionsumfang

Eine Funktion erfüllt genau EINE Funktion und Nicht 5 oder 10 oder 20!
Ganz egal ob es die Startfunktion ist, oder irgend eine andere Unterfunktion. Eine Funktion ist kein Universal-Vehikel.
In der Fachliteratur ist in der Regel die Rede von maximal 50 Zeilen pro Funktion! Das Trennen von Funktionen in sinnvolle Unterfunktionen ist die absolute Basis für jede Programmierung. Wenn Sie 500 oder 1000 oder gar noch mehr Zeilen in einer Funktion unterbringen, dann ist es nur eine Frage der Zeit, bis das Gebilde bei einer kleinen Änderung zusammenbricht wie das sprichwörtliche Kartenhaus.
So lange Sie alleine vor sich hin programmieren und Sie den Faden nicht verlieren, mag es für Sie alleine auch noch halbwegs überschaubar sein, aber wehe dem Sie schauen mal ein paar Wochen nicht in Ihren Source-Code, oder Sie geben das Projekt einem anderen Programmierer … früher oder später kann mit diesem Quellcode niemand mehr etwas anfangen.

Die Start-Funktion im Speziellen sollte außerdem eine reine “Koordinations”-Funktion sein. Sie verteilt lediglich den Datenfluss und die Aufgaben, übernimmt aber selber keine Berechnungen.
Schauen Sie doch beispielsweise mal beim Tool zur Latency-Messung, dort sieht die OnInit() Funktion (ich habe in diesem Tool keine Startfunktion verwendet, weil der Ablauf nur einmal ausgeführt werden soll) wie folgt aus

void OnInit()
{
   f_comment("\n*** Code4Trading.com made by ForexInnovation @ metatrader-experts.de ... have fun***");

   f_openAllTrades();

   f_modifyAllTrades();

   f_closeAllTrades();
}

… es wird ein wenig kommentiert, genau eine Zeile, weshalb ich mir eine separate Funktion gespart habe und danach werden die Aufgaben verteilt. Es werden also der Reihe nach die einzelnen Pakete aufgerufen und abgearbeitet. In der OnInit()-Funktion findet aber keinerlei Ausführung von irgendwelchen Berechnungen oder ähnlichem statt.

2. Lesbarkeit von Quellcode

Variablen, Funktionen, Klassen, Strukturen etc. sind mit prägnanten, selbsterklärenden Begriffen zu versehen!
Der Quellcode darf kein Mysterium sein, sondern der Leser muss die “Geschichte” in den Abläufen beim Lesen verstehen.

Damit jeder Funktionsaufruf einer selbst geschriebenen Funktion von Standard-MetaTrader Funktionen unterschieden werden kann, verwenden wir außerdem vor jeder Funktion ein “f_“. Man kann sich über die Notwendigkeit darüber streiten, für die reine Programmierung ist es nicht wichtig, aber das Thema Lesbarkeit und damit auch Wartbarkeit von Quellcode ist uns an dieser Stelle sehr wichtig. Jeder Leser unseres Quellcodes, weiß bei einem “f_” sofort, dass es sich hierbei um eine selbst geschriebene Funktion handelt.

In der Praxis sieht man sehr oft wilde Abkürzungen für Variablen, die dann auch noch global sind, also Variablen die irgendwie immer präsent sind, aber nie weiß ein Entwickler was genau damit eigentlich gemeint war.

Sehr viele praktische Beispiele wie es nicht geht und auch mit klaren Richtlinien wie es dafür ums so besser geht, finden Sie in einer absoluten Pflichtlektüre zu diesem Thema von Robert C. Martin: Clean Code – Refactoring, Patterns, Testen und Techniken für sauberen Code: Deutsche Ausgabe Ein wirklich hervorragendes Buch für jeden der Programmierung noch selber lebt und nicht nur in der Welt der Software-Architektur unterwegs ist. Sehr viele Beispiele aus allen Bereichen der Software-Entwicklung.

Oder alternativ bei Steve McConnell, wobei dieses Buch noch deutlich mehr in die Tiefe geht und auch das Thema Software-Architektur, Test-Driven-Design usw. ausführlich behandelt Code Complete – Deutsche Ausgabe der Second Edition

Auch an dieser Stelle ein Beispiel aus dem MQL-Quellcode des Latency-Tools

void f_modifyAllTrades()
{
   for (int thisOpenTradeByIndex = 0; thisOpenTradeByIndex < OrdersTotal(); thisOpenTradeByIndex++)
   {
      if (!OrderSelect(thisOpenTradeByIndex, SELECT_BY_POS, MODE_TRADES)) continue;

      f_doTheNextTradeModification();
   }
// ...

… ganz offensichtlich werden in dieser Funktion alle Trades modifiziert void f_modifyAllTrades()

   void f_modifyAllTrades()

Dazu werden die aktuell offenen Trades der Reihe nach entsprechend ihrem Index selected

   for (int thisOpenTradeByIndex = 0; thisOpenTradeByIndex < OrdersTotal(); thisOpenTradeByIndex++)
   {
      if (!OrderSelect(thisOpenTradeByIndex, SELECT_BY_POS, MODE_TRADES)) continue;

… und wenn ein Trade erfolgreich selected wurde, dann wird er anschließend modifiziert, wobei dafür eine separate Funktion aufgerufen wird, denn jede Funktion soll ja nur schön eine Funktion erledigen, in dem Fall also erstmal die Funktion Trade-Auswählen und dann die Weiterverzweigung in Trade-Modifizierung…

   f_doTheNextTradeModification();

3. Kommentierungen im und am Quellcode

Kommentare sind in 99% der Fälle vollkommen überflüssig und gehören in keinen Quellcode!
In vielen Fällen sieht man dem Quellcode an, dass der Entwickler einfach nicht wusste, dass man Funktionen und Variablen sinnvoll benennen muss, um den Quellcode zu einer sich selbsterklärenden Geschichte zu machen. An jeder zweiten Zeile findet sich eine ellenlange Erläuterung was denn hier nun genau passiert und warum es so gemacht werden muss und nicht anders.
Das hat viele Nachteile (um es diplomatisch zu sagen…)
Im ersten Moment verringert dies den Lese- und Verständnisfluss natürlich dramatisch. Wenn man zu jeder nicht zu verstehenden Zeile erst noch eine komplexe Erklärung lesen muss, nur um dann 5min später schon wieder vergessen zu haben, was genau an dieser Stelle gemeint war, so bremst dass den Arbeitsfluss doch sehr.
Viel gefährlicher ist aber die Vergänglichkeit von Kommentaren. Ein Kommentar ist schnell mal geschrieben. Aber wie aktuell ist ein Kommentar in 2 Wochen oder 2 Monaten oder 2 Jahren? Wir haben viel MQL-Quellcode gesehen, in dem mehr Kommentar als Quellcode vorhanden war. Aber zueinander gepasst hat beides ganz offensichtlich schon lange nicht mehr. Und was macht man dann mit solchem Quellcode, in dem ein Kommentar eine Beschreibung abliefert, was denn genau passieren soll, der Quellcode aber offensichtlich schon lange anderen Regeln folgt? … Schrott. Mülltonne.

Kommentare führen früher oder später in die Irre, sie erzeugen ggf. sogar Fehler, weil sie einfach nicht mehr aktuell sind.

Letztendlich sind Kommentare einfach nur überflüssig, da man alle Informationen die ein Leser eines Quellcodes benötigt auch im Code durch gute Strukturen, Benennungen usw. vermitteln kann.

Versuchen Sie also jeglichen Kommentar zu vermeiden. Es wird Sie automatisch dahin führen, dass Sie Ihre Programmierung verbessern! 

Viele Kommentare sind ein Synonym für schlechte Programmierung. Drücken Sie sich durch sauberen, gut lesbaren Quellcode aus, nicht durch vergängliche, irreführenden, überflüssige Kommentare.

Bei Kommentaren gibt einige wenige Ausnahmen die zulässig sind. Diese Ausnahmen kann man ebenfalls im Detail anhand von einleuchtenden Beispielen bei Robert C.Martin: Clean Code – Refactoring, Patterns, Testen und Techniken für sauberen Code: Deutsche Ausgabe oder bei Steve McConell Code Complete – Deutsche Ausgabe der Second Edition nachlesen.

 

Diese drei Punkte sollen für den Anfang erstmal reichen. Wenn Sie sich an diese drei Grundregeln halten, wird sich die Qualität Ihrer Programmierung dramatisch verbessern (falls Sie es nicht sowieso schon tun).

Sie werden damit automatisch in der Lage sein, wesentlich größere Projekte problemlos zu managen. Einzelne Funktionen, oder Funktionsblöcke können Sie auf dieser Basis dann auch in includes zusammen fassen und jederzeit wieder verwenden … aber dazu später mehr.

Außerdem macht Programmierung aus Basis dieser einfachen, aber effektiven Regeln einfach mehr Spaß! Und das sollte man nicht vergessen, wenn man mal wieder vor 550 Zeilen if then Verschachtelung sitzt und keine Lust mehr hat irgendwas an diesem Projekt zu tun … das darf nicht passieren.

So, dass soll es für den Anfang zum Thema Grundlagen einer gut strukturierten Programmierung erstmal gewesen sein, demnächst gibt’s mehr dazu. Unter diesem Artikel finden Sie auch nochmal die Links zu den beiden  Büchern, welche wir für ausgesprochen hilfreich halten für jeden, der noch selber programmiert und sein Handwerk dabei beherrschen möchten. Clean Code ist dabei etwas kürzer gefasst und etwas praktischer orientiert, Code-Complete ist ein extrem umfassendes Nachschlagewerk, welches auch viele andere Themen der Programmierung und Architektur behandelt.

Danke fürs Lesen

Thomas @ ForexInnovation

 

Clean Code by Robert C.Martin

Code Complete by Steve McConnell

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*