Tipps für nachhaltige PHP Entwicklung – Teil1

Jeder Entwickler kennt Sie, jeder Entwickler produziert Sie: Fehler. Aus ihnen kann man lernen und an ihnen wachsen. Vor allem im PHP Umfeld gibt es auch heute noch viel Software der Struktur fehlt, wodurch Fehler begünstigt werden. PHP macht es einfach eine unsaubere Lösung in kurzer Zeit umzusetzen. Der Einstieg in PHP ist unter anderem deshalb so leicht, weil kurzfristige Erfolge ohne viel Hintergrundwissen möglich sind. Da dies aber mittelfristig zu Problemen führt, ist hier der Entwickler umso mehr gefragt. Ein durchdachtes Design hat viele Vorteile:

  • vermeidet Redundanz
  • Fehler werden vermieden
  • Fehlersuche ist einfacher
  • Software ist leichter erweiterbar

Außerdem macht Programmieren mit Stil einfach viel mehr Spaß und ist wirtschaftlich betrachtet sinnvoller. Hier sind einige Tipps und Anregungen für PHP Entwickler, die als Denkanstoss dienen sollen. Passende Bücher die in keiner Bibliothek fehlen sollten sind am Ende des Artikels zu finden. In den nächsten Tagen kommen weitere Anregungen zu dem Thema.

.

Inhalt

0. Design / Logik trennen

Eigentlich ein alter Hut, aber auch heute noch nicht überall angekommen: Programmcode und grafisches Layout muss man trennen! Es entstehen Fehler, selbst triviale Anpassungen sind nicht mehr einfach möglich und man nimmt sich selbst den kompletten Spaß bevor er überhaupt angefangen hat. Es gibt dazu die verschiedensten Ansätze. Bspw. Template-Engines wie Smarty. Mindestens genau so effizient finde ich persönlich allerdings z.B. die Lösung beim Zend Framework. Hier wird auf Basis des MVC (Model-View-Controller) Pattern noch weiter getrennt. Der hier relevante Aspekt ist vor allem dass dort trotz der Option auf Smarty auch ganz ohne Template Engines die Logik elegant vom Design getrennt werden kann.

1. DRY – Dont Repeat Yourself

Unheimlich wichtig bei der Programmierung generell ist es benötigte Funktionalität genau nur einmal zu implementieren. Es gilt also, Redundanz ist zu vermeiden. Das ist sogar nicht nur auf einzelne Anwendungen zu beziehen, sondern kann auch als Denkanstoss für den Aufbau einer eigenen Bibliothek dienen. Redundanz innerhalb von Software macht die Wartung, die Fehlersuche und die Erweiterung der Software umständlich und führt früher oder später zu Problemen. Grundsätzlich sollte man generalisieren/abstrahieren und darauf achten dass Funktionen auch an anderer Stelle genutzt werden können. So müssen Anpassungen nur an einer Stelle gemacht werden und können ggf. sogar auf weitere Systeme oder Anwendungen übertragen werden. Man sollte also auch den Quellcode nicht aus dem Blick verlieren und wenn benötigt einfach Funktionen/Methoden/Klassen ungesehen anlegen, sondern vorab prüfen ob es die Funktionalität schon gibt oder ob man auf etwas vorhandenem Aufbauen kann.

2. Objektorientierung

Objekte bieten unheimlich tolle Möglichkeit und vereinfachen die Entwicklung. So wird Funktionalität gekapselt, der globale Namensraum bleibt sauber und man muss nicht die Funktionsweise der Methode im einzelnen kennen. An diese werden einfach Parameter übergeben, die gewünschten Aktionen intern durchgeführt und anschließend ggf. Werte zurückgegeben. Die Entwicklung im Team wird hier deutlich einfacher. Man einigt sich im Vorfeld auf geeignete Schnittstellen und muss zunächst auch nur diese kennen. So können mehrere Entwickler an verschiedenen Teilen eines Projekts arbeiten. Während der eigenen Entwicklung können z.B. Klassen von anderen Entwicklern einfach gegen Dummy Klassen ausgetauscht. Am Ende werden dann die einzelnen Teile zu einem größeren ganzen zusammen gesetzt. Dadurch ergibt sich ebenfalls dass bei sauberer Programmierung einzelne Klassen unkompliziert ausgetauscht werden können. Das ganze hört sich spektakulär an, die benötigte Syntax ist aber mit etwas Übung nicht schwer. Klassen und die daraus resultierenden Objekte sind an die reale Welt angelehnt, was auch das Lesen und Verstehen von Quellcode vereinfacht. Die wirkliche Kunst ist es, Objekte und Klassen in Anwendungen zu gestalten um sie dann geschickt miteinander in Verbindung zu bringen. Aber auch hier ist man niemals alleine. Zum einen hilft Erfahrung, Planung der Struktur (z.B. mit UML) aber auch Design Patterns.

3. Design Patterns / Entwurfsmuster

Entwurfsmuster bieten vor allem im Zusammenhang mit objektorientierter Programmierung Antworten auf bestimmte Fragen zum Software Design. Dadurch entstehen standardisierte Lösungen. Dies ist zugegeben ein Thema an dem sich teilweise die Geister scheiden. Ich persönlich halte Design Patterns für überaus sinnvoll, vorausgesetzt die Lösung ist zielführend. Ein wichtiger Aspekt ist hier die Lesbarkeit von Quellcode, vor allem wenn Software im Team entwickelt wird. Sie können z.B. beim lesen und verstehen von fremden Quellcode unterstützend wirken, da man keine individuelle Lösung verstehen muss. Des Weiteren halte ich es für sinnvoll nicht immer wieder dass Rad neu zu erfinden. Wenn eine Lösung bereitsteht über die sich bereits viele kluge Köpfe Gedanken gemacht haben, warum erneut bei Null anfangen? Wirtschaftlich betrachtet spart man dadurch vielleicht teilweise auch einfach noch Zeit und somit Geld.

4. Lose Kopplung und explizite Abhängigkeiten

Entwickelt man Klassen mit “loser Kopplung”, haben diese minimale Abhängigkeit zu anderen Klassen. Je weniger Abhängigkeiten bestehen, desto besser kann man sie auch an anderer Stelle wieder verwenden. Zusätzlich sollten Abhängigkeiten nicht implizit existieren, sondern explizit ausgewiesen sein bzw. “injeziert” werden. Eine implizite Abhängigkeit entsteht z.B. wenn innerhalb einer Methode Objekte per “new” erzeugt werden. Die Klasse zu der jene Methode gehört, funktioniert ggf. nur wenn auch die Klasse welche mittels “new” erzeugt wird vorhanden ist. Bei einer expliziten Abhängigkeit wird der Klassenname oder eine Objektinstanz an die aufrufende Klasse oder die Methode übergeben. Dies kann entweder bei dem Instanzieren über den Kontruktor erfolgen oder aber über Methodenaufrufe (“setter”). Dieses Vorgehen nennt man “Dependency Injection” oder auch “Inversion of Control“. Diese Entwurfsmuster machen Klassen bzw. die resultierenden Objekte einfacher austauschbar. Dies kann z.B. bei zukünftigen Erweiterungen der Software eine Rolle spielen, oder aber auch zur Laufzeit interessant werden.

5. Unittesting

Sicher kennt auch dies jeder Entwickler: Man entwickelt, testet intensiv und es sieht alles gut aus. Im Hintergrund wurden dann doch Fehler übersehen da einfach nicht jede Funktion getestet werden konnte. Ein weiteres Szenario: Es funktionieren bestimmte Features wunderbar. Es werden Anpassungen an der Software notwendig und von 5 Features die vorher nie Probleme gemacht haben, hat später min. 1 Probleme. Die Lösung dafür sind fest definierte Tests. Hierbei werden z.B. Methoden/Klassen in unterschiedlichen “Situationen” auf Herz und Nieren geprüft. D.h. man ruft eine Methode “addieren()” auf und prüft ob das Ergebnis wie erwartet zurückgegeben wird. Zusätzliche Tests für die Methode “addieren()” würden dann noch sicherstellen dass ein Fehler signalisiert wird wenn ein Parameter fehlt usw. Allerdings steht und fällt das Konzept komplett mit den Tests. Um sicherzustellen dass es diese für jede Methode / Klasse gibt, kann man nach dem “Test-Driven-Development” Schema arbeiten. In dem Fall wird bevor überhaupt eine Methode oder Klasse geschrieben wird ein passender Test geschrieben. So überlegt man sich genau was die Methode können soll und welche Fehlersituationen auftreten könnten. Ist Software mit Unittests abgedeckt bedeutet dies sicherlich nicht 100% Sicherheit. Dennoch ermöglichen Unittests gleichbleibende Qualität, machen größere Anpassungen leichter und führen zu einem besseren Stil.

Zudem ist es wichtig, immer weiter zu lernen! Natürlich kann man die Syntax von PHP relativ einfach beherrschen. Dabei kommt es gar nicht darauf an alles auswendig zu können. Dafür gibt es Dokumentation. Viel wichtiger und schwieriger ist dass Software Design. Hier kann ich empfehlen über den PHP Tellerrand hinausschauen und andere Programmiersprachen zu lernen (wenn dies nicht schon der Fall ist). Das Wissen was man sich aneignet, kann zu einem sehr großen Teil auch auf die PHP Programmierung übertragen werden. Ganz unten auf der Seite sind zudem Buchempfehlungen, die sich alle mit verwandten Themen befassen. Viel Spaß beim lernen!