php

OOP im Sinne von OOP

Anlässlich des PHP-Summit in München habe ich sehr viel Input zum Thema OOP bekommen und dies hat mir wieder einige Aspekte in das Gedächtnis gerufen, mit denen ich mich zuletzt bei meinem Erstkontakt mit OOP beschäftigt hatte. Um all die Eindrücke aus München hier wiedergeben zu können, müsste ich 1-2 Wochen Urlaub nehmen. Dennoch möchte ich nicht darauf verzichten, einen kleinen Auszug davon anzubieten. Wer seine ersten Erfahrungen mit Objektorientierter Programierung macht, wird etwas Zeit und Erfahrung brauchen, um tatsächlich Code produzieren zu können, der die Vorzüge von OOP implementiert.

OOP – Unvorteilhafte Abstraktion wird weiter vererbt

OOP verspricht lesbaren, wartbaren und wiederverwendbaren Code. Das soll durch eine bestmögliche Abstraktion von Aufgaben und Abläufen in seine Bestandteile erreicht werden. Bei richtiger Anwendung erspart man sich die mehrfache Implementierung einzelner Anweisungen. Sinnvolle Namen für Klassen und Funktionen offenbaren intuitiv und umgehend ihre Rolle und eine sorgfältige Kapselung wahrt die Modularität, sprich Erweiterbarkeit. Doch oft wird dieser Ansatz nicht konsequent genug umgesetzt. Denn Objekt Orientierter Code ist aufwendiger zu formulieren als eine ‚Quick and Dirty‘ Implementierung.
Sicherlich wird jeder schon den Fall gehabt haben, dass man in bestehenden Code ein neues Feature implementieren möchte und das ohne weiteres nicht im Sinne von OOP möglich war. Das einfachste Beispiel: Es muss nur eine Klasse geschrieben werden, die von einer bestehenden Klasse erbt und man überschreibt die Methode, in der man den Ablauf anders/neu gestalten möchte. Ich persönlich hatte oft den Fall, dass ich diese Methode gerne einfach nur erweitert hätte, anstatt sie wirklich zu überschreiben.

class myClass extends parentClass {
    public function foobar() {
        parent::foobar();
        /* implement own code */
    }
}

Doch selten war der Ansatz von OOP so konsequent umgesetzt, dass dies möglich war. In der Regel sitzt die Stelle, an der ich meinen Code einfügen möchte, irgendwo mittig im Funktionsrumpf der Methode der Elternklasse. Folglich macht es keinen Sinn mehr, die Urversion der Elternklasse aufzurufen und meinen Code anzuhängen/voranzustellen, weil ich den Quellcode der Elternklasse kopieren muss um meine Implementierung an der richtigen Stelle anbringen zu können.

class myClass extends parentClass {
    public function foobar() {
        /* copied code of the parent method */
        /* implement own code */
        /* copied code of the parent method */
    }
}

Somit generiere ich redundanten Code und damit sinkt nicht nur die Qualität, sondern auch Wartbarkeit und Erweiterbarkeit. Das ist besonders oft der Fall in der Modulentwicklung, in der man Extensions von Drittanbietern ergänzen möchte.

Es gibt Fälle, in denen es sehr schwer und manchmal auch vom Umfang her zu aufwendig oder einfach nicht zweckmässig ist, die Abstraktion bis in jeder Klasse und Methode bis zum Ende durch zu exerzieren. Meistens geht es aber doch und damit der Code weiterhin lesbar, wartbar und wiederverwendbar bleibt, kann man sich an einfachen Richtlinien orientieren und/oder auf bewährte Entwurfsmuster zurückgreifen, in denen wiederkehrende Probleme mit Erfolg und Wahrung des Objekt Orientierten Ansatzes gelöst wurden.

Richtlinien für das Klassendesign können sein:

  • Einfachheit

    Klassen sollten nie mehr als eine Aufgabe haben, zudem sollte diese Aufgabe klar und verständlich sein. Lässt man sich dennoch dazu verleiten, komplexere Aufgaben allgemein abzuhandeln und verzichtet auf eine Abstraktion, läuft man Gefahr die Funktionalität an anderer Stelle wieder aufbrechen zu müssen und hat letztendlich wenig von der Kapselung einer solchen Klasse (siehe redundanten Code meiden). Eine Hilfe kann es sein, wenn man es sich zum Ziel setzt, die Aufgabe jeder Klasse mit einem einfachen Satz zu definieren (was sehr schnell zu einer Herausforderung wird).

  • Implizierte Abhängigkeiten meiden

    Wenn man Code schreibt und in diesem auf Variablen, Methoden und/oder Objekte zugreifen möchte, die nicht von Haus aus in dem gegenwärtigen Namensraum gegeben sind, schafft man implizierte Abhängigkeiten. Zudem entsteht zusätzlicher Aufwand, da der Entwickler sicherstellen muss, dass zum Ausführungszeitpunkt diese Abhängigkeiten auswertbar sind. Viele Prozesse sind erst möglich, nachdem andere schon abgeschlossen wurden. Wir wollen sicherstellen, dass beim Aufruf einer Klasse mit Abhängigkeiten kein zusätzlicher Aufwand zum Prüfen und Verwalten dieser Abhängigkeiten entsteht. Ein bewährtes Werkzeug sind in diesem Fall Dependency Injections, die den Code reduzieren und die Lesbarkeit deutlich steigern. Wer Abhängigkeiten explicit und es zur Bedingung macht, die Abhängigkeiten z. B. bei der Objektinstanzierung im Konstruktor oder beim Methodenaufruf in der Parameterliste zu übergeben, umschifft unauffällige Stolperfallen.

  • redundanten Code minimieren

    Wir möchten keinen Code kopieren und an einer anderen Stelle wiederholt einsetzen. Fühlt man sich dennoch genötigt, dies zu tun, sollte man die Struktur der Abstraktion nochmal überdenken und überarbeiten. Wenn man die Klassen einfach hält und für klare kompakte Aufgaben konzipiert, wird man selten in die Verlegenheit kommen Code kopieren zu müssen. Somit wird sichergestellt, dass die Les- und Wartbarkeit einfach bleibt. Wer möchte schon bei einer Anpassung dies wiederholt an mehreren Stellen tun müssen, um ein einziges Ergebnis zu haben.

  • Conditions meiden oder richtig platzieren

    Komplex verschachtelte Tests sind ein Indiz für ungüngstig abstrahierte Abläufe, in der Regel führen Klassen Code aus und erfüllen Aufgaben. Es gibt wenige Bereiche, in denen tatsächlich Abfragen vorkommen und verarbeitet werden müssen. Natürlich ist man auf Fallunterscheidungen angewiesen, dennoch gibt es Konstrukte und Abschnitte, die für solche Aufgaben prädestiniert sind, z. Bsp: Factories, Bootstrap-Files.

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

Benachrichtige mich zu:
avatar

wpDiscuz
Weitere Beiträge zum Thema
Mit uns zur „Zukunft des E-Commerce“: Flagbit bei der Internet World in München
TemplaVoila: Element UNmappen
Flagbit relauncht die Webseite der Brunner Group
IT Fachanwalt Timo Schutt beim 19. E-Commerce Stammtisch