Hmm. Vielleicht kann man ja für den Artikel eine Klasse schreiben, zu der man eine Zusatzklasse oder zumindest ein kleines Script irgendeiner Art laden kann, damit dann Kompatibilität bereitstellt wird, wenn der Bedarf entsteht?
Nein, Abwärtskompatibilität im Kontext von Software-Sicherheit muss mit ganz besonderer Behutsamkeit behandelt werden. Wenn man nicht in der Lage ist, das veraltete System selber weiter zu warten, sollte man es auf keinen Fall weiter einsetzen. Stattdessen sollte man in ein ständig aktuelles System investieren. Das ist unter Garantie die sehr viel einfachere und günstigere Lösung.
- Der Kontrollfluss muss vorhersehbar sein, mit eindeutigen Eintritts- und Austrittspunkten. D.h. insbesondere keine exit- oder die-Statements in der Schnittstellen-Implementierung.
Wie machst Du das denn, wenn Du auf einen bestimmten Request nur Header-Daten senden willst, aber garantiert keine Nutzdaten? Ist nach den
header()
-Aufrufen einexit
nicht gut?
Nein, nicht gut. Das garantiert dir zwar, dass nach dem exit-Statement keine Ausgabe mehr stattfinden kann, aber nicht, dass zuvor keine Ausgbabe stattgefunden hat. Darüber hinaus beendet ein exit die Ausführung von jeglichem Code, nicht nur von Solchem, der mit der Ausgabe zusammenhängt. Genau deshalb ist ein vorhersehbarer Kontrollfluss ja so wichtig. Bezugnehmend auf dein Beispiel, wird es eine Stelle im Code geben, da hat noch keine Ausgabe stattgefunden und da weißt du schon, es soll auch zu keine Ausgabe kommen. An dieser Stelle musst du den Kontrollfluss so umleiten, dass keine Ausgabe erzeugt wird, aber andere Funktionen nicht betroffen werden. Wenn man Gewissheit haben will, dann bietet sich wieder Unit-Test an.
- Der Datenfluss muss definiert sein, möglichst unidirektional mit starker Präferenz für Lokalität gegenüber globalem Zustand und einem verantwortungsbewusstem Einsatz von Nebenwirkungen.
Das habe ich nun überhaupt nicht mehr verstanden. Meinst Du, dass alles in einer Klasse mit lokalen Variablen und Eigenschaften der Klasse selbst abgebildet werden soll, ohne sich auf (super-)globale Variablen zu verlassen?
Ich dechiffrier das mal: Unidirektional heißt, dass eine neue Variable möglichst nur von vorherigen Variablen abhängt und das die Änderung einer Variablen nicht dazu führt, dass an anderen Stellen Variablen erneut synchronisiert werden müssen. Lokalität bedeutet, dass der Geltungsbereich von Variablen so klein wie möglich, so groß wie gewählt wird. Große Geltungsbereiche benötigen viel gedanklichen Overhead beim Lesen und Schreiben des Codes. Nebenwirkungen sind Aktionen, bei denen der Programmfluss synchronisiert werden muss. Das heißt, der Entwickler wird gezwungen eine Aussage über die konkreten Ablauf seines Programms zu treffen. Die header-Funktion ist ein gutes Fallbeispiel dafür. Wer kennt nicht die Fehlermeldung "Headers already sent...". Das ist ein bekannter Synchronisierungs-Fehler.
- Der Code sollte zwecks Lesbarkeit modernen Codingstandards folgen, für PHP ist das am häufigsten der PSR-Standard. Code-Linter können eine reihe an Codesmells entdecken und die Einhaltung gesetzter Standards verifizieren.
Was sind "moderne Codingstandards"?
Das sind Richtlinien, die dafür sorgen, dass Code lesbar und wartbar bleibt. Das läuft auf verschiedenen Ebenen ab: Auf der niedrigsten Ebene schreibt ein Codingstandard vor, wie der Code syntaktisch zu entwerfen ist. Soll mit Leerzeichen oder mit Tabulatoren eingerückt werden, wann kommt eine Leerzeile, soll die geschweifte Klammer ans Ende der Zeile oder an den Anfang der nächsten Zeile? Auf höheren Ebenen, werden dann auch Namenskonventionen und der Umgang mit Exceptions etc. festgelegt.
Vom "PSR-Standard" habe ich noch nichts gelesen. Werde ich nachholen. Was ein Linter ist, kenne ich von jsLint. "Codesmells" habe ich noch nie vorher gelesen. Kann Code einen Geruch haben? Ist das grundsätzlich etwas anderes als "Flavours"? Ja, und "gesetzte Standards" sind dann andere, als die "modernen Standards"?
Ein "gesetzter" Standard meine einfach einen Standard, den ich mir zum Ziel setze. Mit Codesmells bezeichnet man häufig beobachtete Programmiermuster, die dafür bekannt sind, dass sie Software-Fehler einführen oder für Verwirrung unter Entwicklern sorgen.
100%ige Sicherheit ist eine Illusion, aber (in)formelle Überprüfbarkeit ist die Mindestvoraussetzung, die wir schaffen müssen. Können wir das nicht leisten, dann hat unser Wiki an dieser Stelle besser eine Lücke.
Da verlangst Du mehr, als ich in der Lage bin. Zwar könnte ich mir überlegen, wie ich eine Klasse schreibe, die einen Login anhand einer Datenlage (Flatfile oder DB-Zugriff) prüfen und im Erfolgsfall eine Session mit passenden Daten bestücken kann, aber automatisierte Tests (Unit-Tests) oder gar formale Überprüfungen auf Sicherheit kann ich nicht leisten. Wie macht man das?
Kurze Antwort: Hands-on: https://phpunit.de/getting-started.html