Schlechter Quellcode ist schwer zu lesen, schwerer zu überarbeiten und nur mit viel Aufwand an einen anderen Entwickler zu übergeben. Dies führt zu erheblichen unnötigen Kosten, wenn beispielsweise die Agentur gewechselt wird. Diesem Thema haben sich Dr. Nikolai Krambrock und Andreas von Studnitz auf der Meet Magento 2014 gewidmet. Inhalt ihres Vortrags waren: Was ist guter Quellcode? Wie sieht er aus? Wie entwickelt man ihn? Der erste Teil befasst sich zunächst mit allgemeiner Code-Qualität. Der darauf folgende Teil setzt sich mit Magento-spezifischen Themen auseinander, die Entwicklern helfen, besseren Quellcode zu schreiben.

Hier die dazugehörigen Folien:
140805_Code_Quality.pdf

Funktionen guter Codequalität

Shopbetreiber haben Interesse an externer Codequalität: Funktionalität, Gebrauchstauglichkeit, Sicherheit, Verfügbarkeit und Zuverlässigkeit. Daneben möchten sie ihren Online-Shop zu vertretbaren Kosten erweitern und ändern können. Die externe Codequalität wird in großen Teilen durch die interne Codequalität bestimmt. In einfachen Worten ist Quellcode dann von guter interner Qualität, wenn er durch Entwickler leicht zu lesen und leicht zu verändern ist. Es geht dabei nicht darum, dass Maschinen den Quellcode gut interpretieren können, sondern Menschen.

Allgemeine Codequalität

Regeln für guten Quellcode

Gute interne Codequalität durch einfachen Quellcode lässt sich erreichen, indem die Entwickler sich an einige einfache Regeln halten. Leider sind nur die Regeln einfach – deren Einhaltung aber keineswegs. Einfachen Quellcode zu schreiben ist wesentlich komplizierter als komplizierten Quellcode zu schreiben.

Folgende Regeln sind elementar:

  • Einfache Lösungen für Probleme sind das A und O guter interner Codequalität. Wer bloß 5 Elemente sortieren will, sollte besser einen einfachen Bubble-Sort schreiben als einen komplizierten Quick-Sort. Auch sollte keine Rekursion verwendet werden, wenn es auch mit einer For-Schleife geht.
  • Es ist sinnvoll Strukturierungselement wie Klassen und Methoden in mittlere Klassen anzulegen. Diese Strukturierungselemente ergeben nur Sinn, wenn sie auch zur Strukturierung genutzt werden, also nur dann, wenn sie mittelgroß sind. Für Klassen gilt daher 100-200 Lines of Code, für Methoden 3-20 Lines of Code.
  • Nach Beginn von Fallunterscheidungen (if) oder Schleifen (while) wird der Quellcode eingerückt. Wird mehr als drei Mal eingerückt, so gibt dies einen Hinweis darauf, dass der Quellcode zu komplex wird und er überarbeitet werden muss. Ab fünf Einrückungen ist der Quellcode definitiv überarbeitungsbedürftig.
  • Sprechende Variablenamen sind wichtig, da sie einen großen Teil der Dokumentation des Quellcodes einnehmen und als Art Geschichte fungieren. Sie lassen den Code für sich sprechen. Das funktioniert allerdings nur mit guten Variablennamen.
    • Beispiel eines sehr schlechten Variablennamens:
      "$c=Mage::getModel"
    • Beispiel eines schlechten, dennoch häufig genutzten Variablennamens:
      "$customer=getModel("...")"
    • Beispiel eines guten Variablennamens:
      "$customerToAdd=getModel("...")"
    • Das Gleiche gilt für sprechende Methoden und Klassennamen. So lässt beispielsweise
      "deepClone()"

      mehr Rückschlüsse auf den Vorgang zu als

      "copy()"
  • Dead Code ist Quellcode, der nicht ausgeführt wird. Dieser kann mit statischen Analysen gefunden werden und sollte dann gelöscht werden.
  • Doppelter Quellcode ist nach dem Buch „Refactoring“ von Martin Fowler das größte interne Qualitätsproblem in Quellcode. Dieser sollte in Funktionen, Vererbung oder gemeinsam genutzten Klassen ausgelagert werden.
  • Magic Numbers sind Zahlen oder Zeichenfolgen, die mitten im Quellcode auftauchen – z.B. in „x>7“. Die magischen Zahlen sollten in Konstanten, eine Konfiguration oder Sprachdateien ausgelagert werden.

Werkzeuge guter Codequalität

Das elementarste Werkzeug der Softwareentwicklung ist das Versionsmanagement. Es bietet erheblichen Nutzen bei nahezu keinem Aufwand und keinen Kosten. Das Versionsmanagement speichert alle vergangenen Versionen einer Software und alle Veränderungen. Verloren gegangene Vorgänge können wieder hergestellt werden; taucht ein Bug auf, so können alle Änderungen bis zu diesem Bug hin untersucht werden.
Ein weiteres wichtiges Werkzeug ist das automatisierte Testen. Hier gibt es zwei Varianten: Black-Box-Tests und White-Box-Tests. Black-Box-Tests testen die Funktionalität eines Quellcodes. Ein Beispiel dafür ist Selenium. White-Box-Tests wiederum werden vermehrt im PHP Umfeld mit PHP Unit eingesetzte. Diese Art des Testens ist hauptsächlich bei großen Projekten oder bei Modulen, die über zahlreiche Funktionen hinweg funktionieren müssen, hilfreich.

Codequalität mit Magento

Kapselung von Modulen in Magento

Bei der Entwicklung von Magento-Modulen sollte darauf geachtet werden, dass diese möglichst wenige Abhängigkeiten von anderen Modulen haben:

  • Module sollten eigenständig lauffähig sein und wenig Abhängigkeit zu von anderen Modulen – besonders nicht zu externen Modulen – aufweisen. Genauso wenig sollten sie von Template abhängig sein. Template sind projektbezogen und immer unterschiedlich, weshalb sie wiederholte Anpassungen erfordern, sobald sie modulabhängig sind. Offensichtlich, dass das mit Aufwand verbunden ist, den man mit möglichst wenig Abhängigkeit verhindern kann.
  • Es sollte die Möglichkeit bestehen, einzelne Module abschalten zu können. So lässt sich prüfen, in welchem Modul sich ein Fehler befindet, ohne dabei das Template zu zerstören. Das Abschalten einzelner Module erreicht man durch Layout-Updates. Dazu arbeitet man im Theme base/default, nicht in projektspezifischen Themes. Auf diese Weise werden Module weder überschrieben noch angepasst. Manche Projekte lassen jedoch nur ein Arbeiten im projektspezifischen Theme zu. Um trotzdem Module abschalten zu können, wird ein Modul entwickelt, das den Namen des Projekts trägt und die Template-spezifische Zusatzfunktionen abdeckt.

Updatefähigkeit in Magento erhalten

Um die Updatefähigkeit in Magento zu erhalten, dürfen keine Core-Hacks oder Änderungen an externen Dateien und Magento-Dateien ausgeführt werden. Passiert es doch, so werden alle Änderungen überschrieben. Letztendlich müssen so durchgeführte Änderungen dann von Hand nachgezogen werden – das Ergebnis ist häufig fehlerhaft. Stattdessen sollten Rewiters oder Observer eingesetzt werden. Gleiches gilt für Sprachdateien, die von Magento mitgeliefert werden. Bei ihnen empfiehlt es sich eigene Übersetzungsdateien anzufertigen. Hier kommen Code Pools als Hilfestellung ins Spiel. Sie verbessern – wenn sie korrekt verwendet werden – das Überschreiben, falls funktionale Anpassungen durchgeführt werden müssen:

  • local für projektspezifische Module
  • community für veröffentlichte/geteilte Module
  • core für Core
  • lib für externe Bibliotheken

Weitere Vorsicht ist bei Kopien von Template-Dateien geboten. Änderungen an kopierten Dateien gefährden die Updatefähigkeit, wie folgendes Beispiel zeigt: Sie kopieren eine layout.xml-Datei, um darin eine Zeile zu ändern. Gleichzeitig frieren Sie dadurch die restlichen unveränderten Dateien ein, so dass diese beim nächsten Update erhalten bleiben. Als Resultat müssten Sie alle einzelnen Änderungen des Updates nachziehen. Dieser Aufwand kann vermieden werden. Die Lösung liegt im Minimieren der Kopien von Template-Dateien und dem Einsetzen einer local.xml-Datei oder einer modulspezifischen layout.xml-Datei.

Minimale Änderungen am Quellcode

Für eine fehlerarme Entwicklung gilt: „Nur kein Code ist ein guter Code.“ Demnach sollten möglichst wenige Zeilen Quellcode genutzt werden. Die schärfste Waffe gegen viel Quellcode lautet bestehende Magento-Funktionen nutzen und keine neuen Funktionen erstellen. Ein gutes Beispiel dafür sind Staffelpreise für individuelle Optionen. Diese Funktion bietet Magento im Standard nicht an. Eine mögliche Lösung für das Problem wäre das Generieren zusätzlicher costumer options für jede Staffel. Weniger gut wäre es, die Preislogik zu überschreiben.

Model View Controller in Magento

Magento setzt das Model-View-Controller-Konzept (MVC) eigenwillig um. Die wichtigste Trennung in Magento ist die Aufteilung zwischen Code und Template, die nur partiell kompatibel mit MVC sind, denn sowohl das Tempalte als auch die Blocks gehören zum View. Dennoch bleibt diese Trennung das wichtigste Element in Magento: Im Template darf kein zeilenweiser Quellcode enthalten sein und im Quellcode kein HTML. Diese Trennung sollte unbedingt eingehalten werden. Daneben ist es hilfreich, Daten in Models anzureichern, Logik in Controllern und Observen einzuhalten und Hilfsfunktionen für das Template in Blocks zu gestalten.

Änderungen über Setup-Skripte

Setup-Skripte sind ein wichtiger Mechanismus von Magento, um die Qualität eines Gesamtprojekts zu verbessern und um mehr Sicherheit im Betrieb zu erzielen. Sie haben den Vorteil, dass Änderungen nur einmalig ausgeführt werden, wenn man sie über Setup-Skripte durchführt. Damit umgeht man eine direkte Änderung an der Datenbank oder im Admin-Bereich. Änderungen von Datenbank-Tabellen und-Spalten, Attributen oder Konfigurationen lassen sich zwar auch im Backend vornehmen, sie bergen aber das Risiko fehlerhaft zu werden – insbesondere bei größeren Projekten mit mehreren Systemen und Entwicklern.

Fremdmodule von zuverlässigen Anbietern

In Projekten kommt man selten um externe Module herum. Um auch hier gute Codequalität beizubehalten, ist es sinnvoll, nur Module von bekannt zuverlässigen Quellen zu verwenden. Ist einem der Anbieter des Moduls nicht bekannt, besteht die Möglichkeit gründliche Code-Analysen vorzunehmen. Module von bekanntermaßen fragwürdigen Anbietern, oder Module mit eigenem Lizensierungsmodul oder verschlüsseltem Quellcode sollten nicht eingesetzt werden. Bei letzterem kann im Ernstfall nicht auf den Quellcode zugegriffen werden, um Fehler zu beheben.

Links

Weitere Hilfestellung bieten folgende Coding-Guidlines an:

Fazit

Gute Codequalität sollte im Interesse aller Parteien liegen. Sie fördert nicht nur die Verständlichkeit, sondern auch die Wartbarkeit des Quelltextes und senkt die Wahrscheinlichkeit von schwerwiegenden Fehlern. Wer die Ratschläge dieses Artikels beachtet, schreibt einfacheren Quellcode und kann so bessere Ergebnisse erzielen.