Archiv der Kategorie: art of code

CRUD – Theorie und Praxis

CRUD, dieses Vorgehen sollte eigentlich jeder kennen … falls nicht, CRUD ist die Kurzform für „Create, Read, Update and Delete“ und ist vereinfacht gesagt als Checkliste zu sehen und gilt nicht nur für PHP.

Du hast in deiner Anwendung zum Beispiel eine Liste aller User, die soll editierbar sein. Du kannst nun CRUD als Checkliste benutzen und einzeln abhaken:

  • Create: Kann ich neue User erzeugen? Check!
  • Read: Kann ich eine Liste aller User ausgeben UND kann ich im Editfall einen User darstellen? Check!
  • Update: Kann ich die Daten eines Users ändern? Check!
  • Delete: Kann ich einen User löschen? Check!

Hast du bei allen ein „Check!“, dann bist du technisch auf dem Mindestlevel angelangt. Herzlich Willkommen 😉

Soviel zu Theorie. In der Praxis sehe ich es leider oft, dass CRUD viel zu wörtlich genommen wird. Besonders das C und das U sehe ich oft als zwei Dinge in der Anwendung.

Warum nun ist das schlimm? Nun, ich arbeite mit Legacy-Anwendungen. Diese sind teilweise vor vielen Jahren begonnen und verrichten bis heute ihren Dienst. Innerhalb dieser Anwendungen gibt es immer wieder den Fall, dass eine Datensatzart die CRUD Bedingung erfüllen muss, d.h. ich habe eine Liste von (Beispiel) Usern oder Kunden, die kann man ändern, die kann man neu erzeugen, die kann man löschen usw.

Nun mein Appell an alle: Bitte, fasst C und U zusammen. Bitte!

Es gibt nichts schlimmeres, als dass man ein „create“ Script und ein „update“ Script hat, beide machen im Prinzip das gleiche (Prüfung der Daten, Normalisieren der Daten usw.), aber im Endeffekt hast du 2 Scripte. Du hast also „duplicate code“. Und das ist nicht nur „bad smell„, dies ist einfach nur „bad style“. Eine Änderung an der Logik der User (Stichwort neues Feld) und du musst beide Scripte aktualisieren. Falls deine Anwendung mehrere solcher Listen hat und das neue Feld mehrere betrifft darfst du die „2“ gern entsprechend faktorisieren.

Also, bitte, bau die ein „edit“ Script, prüfe die Variablen, normalisiere diese und mache alles fertig. Dann nur noch die Unterscheidung „neu“ oder „ändern“ und gut ist. Das sind aus meiner Erfahrung nur ein if-else (oder switch) und das entsprechende SQL-Kommando. Die Ausführung des Kommandos ist dann ja wieder das selbe und kann außerhalb der Verzweigung stehen.

Dieses eine Script läßt sich jetzt viel leichter skalieren, verstößt nicht mehr gegen den „copy paste detector“ und läßt dich einfach ruhiger schlafen.

Just my 2 cent ….

Hat YAGNI ausgedient?

Ich las eben einen interessanten Artikel im phpMagain online. In „Abwärtskompatibilität vs. langfristiges Planen“ geht es über einen Blogbeitrag von Anthony Ferrara, in der dieser u.a. darüber schreibt, dass er die Optionen seiner Funktionen als array anlegt, obwohl das ja teilweise gar nicht sein müsse. In die Zukunft gesehen macht es aber Sinn, da ja bald neue Optionen hinzukommen werden, da sich jede Software weiterentwickelt und seine Funktion somit flexibel ist und ihre Signatur sich nicht weiter ändern muss.

Allerdings, und das steht ja auch im Artikel des phpMagazins, wiederspricht dies dem YAGNI Prinzip, das – vereinfacht – besagt, dass du alles, was du aktuell nicht brauchst, auch nicht entwickeln sollst.

Ich finde, dass passt dann nur auf Software, die du einmal entwickelst und die dann einfach vor sich hin altert. Software, die du vorher im Detail planst und dann nie wieder ansiehst. Kurz, Software, die hoffentlich heute in der Form nicht mehr gebaut wird.

Heute verändert sich Software stetig und ständig, „und das ist auch gut so“, denn sonst würden wir alle niemals Updates installieren müssen. Aber im Gegenteil müssen wir heutzutage so viele Updates installieren, dass manchen Hersteller gar nicht mehr nervt fragt, sondern uns ganz bequem mit „Silent updates“ auf dem neuesten Stand hält.

IMHO werden Anwendungen und Webseiten heute um ein vielfaches schneller und öfter aktualisiert wie noch vor wenigen Jahren. Und Software, die aktualisiert wird, wird oft auch erweitert. Es werden ja nicht nur Sicherheitslücken geschlossen oder Bugs gefixed, es kommen oft auch neue Features und Funktionen hinzu, altbekanntes fällt manchmal weg, kurz: Die Software verändert sich und damit auch ihr Code, ihre Funktionen und dessen Signaturen.

Was hat das nun mit YAGNI zu tun? Nun, YAGNI würde besagen, dass man eine Funktion minimalst aufbauen soll, ein Beispiel, eine Funktion liefert uns Benutzerdaten aus einer Datenbank:

public function getUser() {
//...
}

Diese Funktion würde alle User zurückliefern. Im Laufe des Lebens der Anwendung merken wir, dass ein Filter auf „getUser()“ wohl sinnvoll wäre, also ändern wir die Signatur:

public function getUser($id)

liefert nun genau einen User mit einer speziellen Id.

public function getUser($id = -1, $name)

kann nun auch einen User nach Namen liefern, wenn wir id auf -1 setzen.

public function getUser($id = -1, $name, $nameAsLike)

kann nun auch – bei $nameAsLike=true und id=-1 – einen Namen „teilweise“ liefern.

Diese Liste ließe sich nun bestimmt weiter fortsetzen, ihr kennt das sicher alle. Sicher entspricht dies dem YAGNI Prinzip, denn im Laufe der Versionen der Software kam immer nur genau so viel dazu, wie unbedingt erforderlich war. Aber war das gut so?

Vorausschauender wäre es gewesen, sich kurz Gedanken zu machen und dann zu entscheiden

public function getUser(array $options=array())

Nun kann dort auch jeder der obigen Evolutionsschritte der Software eingebracht werden, die Signatur der Funktion braucht allerdings dazu nicht geändert zu werden und damit gibt es auch weniger potentielle Fehlerquellen im Rest des Codes.

Vielleicht müssen wir vom starren YAGNI weg, hin zu einem YDNNI, einem „You Defenitly Not Need It“, einem Paradigma, dass es erlaubt, vorausschauend zu Entwicklen, dass einem aber trotzdem untersagt, völlig Sinnfreie oder sogar Kontraproduktive Dinge zu entwickeln.

Die Sache mit dem array scheint sich langsam aber sicher dank oder trotz YAGNI zur „Best Practice“ durchzusetzen. Setzt ihr Optionen auch als array um oder benutzt ihr da völlig andere Wege?

 

Windows Developer System – Der Webserver (02)

Kommen wir in der Reihe des Windows Developer Systems nun zum Kern eures Entwickler-Systems, dem Webserver. Es gibt verschiedene Möglichkeiten, welchen Webserver man als Entwickler benutzt. Die Haupt Zielplattform wird sicherlich immer noch der gute, alte Apache Webserver sein. Da wir als Windows-ianer aber etwas verwöhnt sind, was Installation und Konfiguration von Software angeht benutzen wir für diesen Teil den Zend Server. Der hat den Vorteil, dass er komplett fertig als „One-Click-Installer“ reinkommt und nichts kostet außer ein paar Minuten Zeit.

Zuerst begibt man sich auf die aktuelle ZendServer Downloadseite und wählt die für sich passende Installation aus. Aktuell gibt es dort den ZS für PHP 5.3 und PHP 5.4 zur Auswahl.

Die Downloadseite des Zend Servers

Es wird zum Download AFAIK kein Account benötigt, falls doch ist dieser kostenfrei und auf jeden Fall die Mühe wert.

Nachdem ihr den Server runtergeladen habt, könnt ihr die Installation wie gewohnt starten. Der Server ist wirklich einfach zu installieren. Beim Zielverzeichnis können wir der Einfachheit halber Den Pfad “C:\” wählen, der Server wird dann unter “C:\zend” installiert. Die kurzen Dateipfade werden uns später die Arbeit etwas leichter machen, wenn es darum geht, Virtuelle Hosts aufzusetzen – dazu später mehr.

Das wirklich schöne am Setup des Zend Servers ist, dass im Schritt “Custom Setup” ganz unten die Option “MySQL Server” angewählt werden kann und damit nicht nur ein MySQL Server runtergeladen wird, sondern das Ganze auch fix und fertig serviert und konfiguriert wird. Wirklich praktisch!

Custom Setup des Zend Servers

Die restlichen Optionen müsst ihr nach euren Anforderungen setzen, ich belasse meist alles so wie es ist und füge nur die Option des MySQL Server hinzu, dann habe ich schon ein funktionierendes System.

Die Installation dauert je nach Optionen, Downloadgeschwindigkeit und CPU ein paar Minuten. Zeit für einen Kaffee 😉

Nach der Installation _kann_ es sein, dass manche Rechner neu starten müssen, andere jedoch nicht. Tut wie euch geheißen und ihr bekommt anschließend den kompletten Zend Server als Trial-Verison für 30 Tage. Keine Angst, nach Ablauf der 30-Tage verwandelt sich die “echte” Zend Server in die “Free”-Version, die genauso als Entwickler-Basis verwendbar ist – nur ein paar Profi-Features fehlen, das wirklich wichtige bleibt aber erhalten.

Je nach Präferenz könnt ihr in den Diensten von Windows nun auch den automatischen Start von “Apache” und “MySQL Server” auf “Automatisch” belassen oder auf “Manuell” setzen. Ich setze den Apache meist auf Manuell und starte diesen bei Bedarf, der MySQL Server läuft dagegen ständig, da ich öfters mal Datenbankabfragen aus meiner IDE starte, während ich programmiere. Aber auch hier: Eure Bier, macht’s, wie’s euch beliebt.

In eurer System-Tray (neben der Uhr) habt ihr nun auch ein schickes neues Icon, ein Klick drauf und ihr könnt den Server starten, stoppen oder restarten wie es euch gefällt. Ein Doppelklick führt zu einer netten Übersicht, die in der Praxis aber kaum Bedeutung hat.

Ob ihr nun glaubt oder nicht, euer Webserver mitsamt MySQL-Server ist nun installiert und einsatzbereit. Yes, it’s that easy!

Wenn der Apache gestartet ist erreicht ihr die Konfigurationsseite des ZendServers unter der URL

http://localhost:10081/ZendServer/

Beim ersten Aufruf (oder nach einem Update) müsst ihr den Üblichen EULA’s zustimmen und angeben, ob ihr den Server als “Development” Server benutzt oder als “Production”, dann ein Password für den Admin-Zugang eintragen und fertig ist der Server!

Zend Server Dashboard direkt nach Installation

Im Punkt “Configurations” könnt ihr einzelne Komponenten (de-)aktivieren und auch alle Teile der php.ini bearbeiten, inkl. Erklärungen. Grade für Neulinge im Bereich Webserver sehr praktisch. Der Server kann nach allen Änderungen die Ihr braucht per Klick neu gestartet werden.

Der größte Teil unter dem Mneüpunkt “Applications” fällt übrigens nach dem Ende der Trial-Phase weg und betrifft eh nur Cloud-“Zeug”, was erstmal nicht von belang sein soll. Wir wollen ja unser lokales System aufbauen und die Grundlage dafür ist nun vorhanden.

Schaut euch also nun in Ruhe euren neuen lokalen Webserver an. Im nächsten Teil geht es weiter mit der Konfiguration der Virtuellen Hosts und was man damit schönes machen kann.

include oder require?

Was soll der PHP-Entwickler benutzen, include oder require bzw. include_once oder require_once?
Und wo liegt da eigentlich der Unterschied?

Die Frage kommt oft, deshalb an dieser Stelle mal ganz klipp und klar und kurz:

require bzw. require_once benutzen, denn: Sowohl include wie auch require binden eine Datei ein, aber, sollte ein Fehler in der includierten Dateie sein, so bricht require mit einem E_COMPILE_ERROR ab, während include fröhlich mit einer WARNING weitermacht.

Im Sinne der Vermeidung von code-smells fällt eure Wahl also auf require bzw. require_once.

Windows Developer System – Die Grundlagen (01)

Ich stelle euch hier vor, wie ihr Stück für Stück eine professionelle PHP-Entwicklungsumgebung unter Windows erstellt und das ganze ohne besonders viel Aufwand. Die meisten Tutorials in dieser Richtung – zumindest die, die ich kenne – gehen immer davon aus, dass ihr Linux benutzt – und wenn doch mal Windows erwähnt wird, dann meist mit dem Seitenhieb, doch mal endlich ein „richtiges“ Betriebssystem zu benutzen.

Ich selbst habe 2 Maschinen, beide mit Windows7, und dieses Tutorial basiert daher natürlich auf dem Betriebssystem Windows. Ihr könnt aber davon ausgehen, dass ihr, wenn ihr unter Windows entwickeln wollt, keine Einschränkungen gegenüber den Linux-Leuten habt, ihr habt nur andere Kommandos – auch wenn die Pinguine euch manchmal was anderes erzählen wollen. Am Ende ist doch eh nur der Code wichtig und der läuft sowohl unter Windows wie unter Linux.

Anfangen möchte ich mit einem Überblick und nötigen Grundlagen, alles weitere kommt dann Stück für Stück. In jedem Teil findet sich ein Inhaltsverzeichnis mit den jeweils anderen Folgen dieser Serie.

Auf jeden Fall wünsch ich euch viel Spaß beim lesen und viel Erfolg beim Umsetzen.

Inhaltsverzeichnis:

Windows Developer System – Die Grundlagen

Zuallererst brauchen wir natürlich ein Windows, welches auch immer. Es sollte im Prinzip auf jedem Windows ab XP funktionieren, testen kann ich – wie oben schon erwähnt – nur auf Win7; Kommentare zu anderen Windows-Varianten wie z.B. Vista, XP oder sogar Win2000 wären nett 😉

Linuxianer oder Mac-User dürfen natürlich gern mitlesen. Bei den Anleitungen zur Installation werde ich aber gnadenlos Windows-lastig sein, dafür könnte sich das Mitlesen bei der Benutzung von PEAR und den damit verbundenen Code-Analyse-Tools aber lohnen. Mein Tipp: Dabeilesen ist alles 😉

Eure Festplatte sollte noch ein paar MB oder besser GB Platz haben, natürlich vor allem für die „große“ Software wie den Webserver und die lokale Datenbank, als auch für eine professionelle IDE … die Puristen unter euch können natürlich auch weiterhin im Notepad2, Notepad++ oder dem Programmers Notepad arbeiten; viele Features einer IDE können einem Entwickler in der täglichen Arbeit allerdings sehr viel lästige Arbeit abnehmen (siehe die 10 Regeln für Entwickler – Punkt 3).

Die Frage an dieser Stelle lautet: „Warum sollte ich das machen?“. Die Antwort ist trivial: Weil es deine Arbeit verbessert und erleichtert, weil es dir viele Möglichkeiten gibt, dich selbst und deine Fähigkeiten zu verbessern. Und bestimmt noch mehrere Dutzend Antworten, die dir aber auch alle im Laufe dieses Tutorials klar werden. Darum!

Von hier aus geht es nun also nahtlos weiter zum nächsten Punkt, dem downloaden und installieren des lokalen Webservers.

Method-Chaining in eigenen PHP-Projekten einsetzen

Klassen und Objekte kennt ja nun mittlerweile fast jeder, ein PHP-Framework wie ZendFramework oder CodeIgniter haben sich sicherlich auch schon viele zumindest mal angesehen … will ich hoffen. Nun, auch wenn man die Frameworks nicht direkt einsetzt, so kann man doch viel von ihnen lernen. Viele der Techniken, die in bekannten PHP-Frameworks eingesetzt werden, entstanden entweder aus dem großen Ästhetischen Faible, den nun mar jeder Entwickler hat oder schlicht aus Faulheit der Programmierer 😉

Egal, eines der – wie ich finde – tollen Features in vielen Frameworks ist die Möglichkeit, mehrere Funktionen eines Objektes hintereinander aufrufen zu können, ja, es sieht schon fast wie ein normaler Satz aus, was dann im Editor steht und seinen Dienst verrichtet. Diese Möglichkeit der sog. “Fluent Interfaces” nennt man “Method-Chaining” (und wieder im Bullshot-Bingo gewonnen, *strike*).

Kleines Beispiel, kennen wir alle, unsere Basisklasse:

class Base1 {
function macheEins() {
// some magic here
}
function macheZwei($parameter) {
// more magic here
}
}

Das ganze rufe ich nun auf:

$myBaseClass = new Base1();
$result1 = $myBaseClass->macheEins();
$result2 = $myBaseClass->macheZwei($result1);

Was passiert? Das Ergebnis des Aufrufs von “macheEins” ist der Parameter für “macheZwei”. Das ganze sieht strukturiert aus und ist lesbar, was also soll man besser machen können? Nein! Bitte jetzt nicht sagen, man könne doch sowas machen:

$myBaseClass = new Base1();
$result2 = $myBaseClass->macheZwei($myBaseClass->macheEins());

Sicher, es funktioniert, aber: NEIN! Macht das nicht! Warum? Ganz einfach: Debugge das mal, viel Spaß. Denn wenn man erst einmal mit so einem falschen Verhalten anfängt, dann verschachteln sich schnell auch mal 5 oder 8 Funktionen ineinander und finde dann mal den Fehler, viel Spaß! Also: Ganz klares “So nicht!”.

Aber wie dann?

Zunächst müssen uns im klaren sein, was die Klasse macht. Offenbar braucht “macheZwei” ein Ergebnis einer Berechnung einer anderen Funktion der Klasse. Dieses Ergebnis könnte man doch genauso innerhalb der Klasse speichern und dann benutzen.

class Base2 {
private $valueHolder;
function macheEins() {
$this->valueHolder = someMagic;
return $this->valueHolder;
}
function macheZwei() {
return $this->valueHolder * someMoreMagic;
}
}

Schon erfüllt die Klasse auch die Anforderungen, aber … so richtig “fluent” will das ganze nicht werden, obwohl ja nun im Aufruf von “macheZwei” der Übergabeparameter fehlt. Was nun? Und wie sieht denn so ein “Fluent Interface” mit “Method-Chaining” nun aus? Der Aufruf sähe in unserem Beispiel in etwa so aus:

$myBaseClass = new BaseFluent();
$result2 = $myBaseClass->macheEins()->macheZwei();

Aber unsere derzeitige Klasse unterstützt das nicht! Wie bekommen wir unsere Klasse nun “Fluent”?

Nun, dazu müssen wir diese massiv umbauen. Der größte Umbau ist, dass die einzelnen Methoden nicht mehr direkt die Ergebnisse liefern, sondern “nur” das Objekt selbst zurückgeben … und darin liegt auch schon der ganze Trick. Den Methodenaufruf kann ich immer nur auf einem Objekt machen. Eine Methode, die mir einen Basisdatentypen zurück liefert, kann ich dafür nicht gebrauchen, da ich auf diesem Basistypen (int, String, array, …) keine weiteren Methoden meiner Klasse aufrufen kann.

Nehmen wir mal an, im letzten Code stünde statt “new BaseFluent” ein “new Base2”. Dann würde der Aufruf:

$result2 = $myBaseClass->macheEins()->macheZwei();

folgendes bedeuten: Rufe die Methode “macheEins” auf dem Objekt “myBaseClass” auf, diese gibt den Datentyp von valueHolder zurück (nehmen wir mal an, es wäre ein integer mit dem rein zufälligen Wert 42), rufe dann auf dem Objekt 42 die Methode “macheZwei” auf … *meep* Fehlermeldung, “42” ist kein Objekt, hat daher generell keine Methoden und erst recht keine spezielle Methode mit dem Namen “macheZwei” also Fehler und Script Abbruch.

Der Trick besteht nun darin, dass die Methoden des Objektes nicht mehr die eigentlichen Ergebnisse zurückgeben, sondern das Objekt der Klasse selbst; darauf darf man ja dann auch wieder Methoden derselben Klasse aufrufen, also bauen wir flugs die Klasse um:

class BaseFluent {
private $valueHolder;
function macheEins() {
$this->valueHolder = someMagic;
return $this;
}
function macheZwei() {
$this->valueHolder *= someMoreMagic;
return $this;
}
function getValueHolder() {
return $this->valueHolder;
}
}

Man erkennt nun, wohin die Reise geht. Getter und Setter werden implementiert, um die Daten zu holen, die Methoden geben uns $this zurück, worauf wir weiterhin Klassenmethoden aufrufen können und wir haben nun unser “Fluent Interface” für “Method-Chaining” in PHP realisiert; war doch gar nicht schwer und hat auch gar nicht weh getan, oder?

In der freien Wildbahn trefft ihr auf diese Art des Codens übrigens ganz stark beim ZendFramework an, bei CodeIgniter geht es wohl auch, denke ich (ich mache mich da erst seit kurzem fit und bitte alle CI-Fans, meine Unwissenheit zu entschuldigen). Es macht aber auch Spaß, dass bei eigenen Klassen umzusetzen, die sowieso umgearbeitet werden sollen. Sieht einfach viel übersichtlicher aus. Und noch ein Tipp: Mehr als zwei Verkettungen sollten untereinander stehen, also so:


$myBaseClass->macheEins()
->macheZwei()
->macheDrei()
->undNochMehr();

Viel Erfolg damit …

10 Regeln für Entwickler

Es gibt viele „Regeln“ zum Programmieren, viele „Goldene Regeln“; das hier sind meine.

  1. Glaube nicht, wisse!
    Glauben heißt, nicht zu wissen. Sei kein Gläubiger, sei ein Wissender! Hebe dich von der Schar derer ab, die nur Oberflächliches kennen, jene, die nur auswendig lernen, was in den „xyz for dummies“ Büchern steht. Du bist anders, du bist smart: Du verstehst, was da steht!
     
  2. „Know your Enemy“
    ”Kenne deinen Feind”; lerne Sachen, die du hasst; verdamme nicht einfach Dinge, die neu oder anders sind: Lerne Sie, verstehe, warum diese Dinge so sind, warum ein Autor das auf diese Weise gelöst hat und wieso nicht anders. Verinnerliche neues, sei bereit für die Änderung, wiege alle Optionen ab: Und dann nimm die am besten passende!
     
  3. Notepad? Benutz eine IDE!
    Benutze eine IDE; Lerne die Features “deiner” IDE kennen und nutze diese Gnadenlos aus! Verstehe, dass jeder „seine“ IDE braucht und das keine IDE wirklich besser ist als eine andere: Es kommt nur auf den Entwickler an, der den Code schreibt!
     
  4. Benutze Standards
    Standards wurden von schlauen Menschen entwickelt, damit diese auch mit Code zurecht kommen, den weniger schlaue Hacker schrieben; du benutzt deinen eigenen Standard nicht, weil du ein guter Entwickler bist; Du benutzt deinen eigenen Stil, weil du die Standards bisher nicht verstanden hast! (siehe 1,2)
     
  5. Object to go
    Klassen erleichtern dir das Leben: Sie lösen eine Aufgabe und das machen Sie effizient; ist die Klasse gut, macht Sie das sogar auf einer abstrakten Ebene und du kannst die Klasse nicht nur für dieses Problem einsetzen, sondern für alle ähnlichen Probleme. Aus (1) erkennst du, wie toll das ist, du nimmst die Klasse mit und bist fast am Ziel. Klassen und Objekte sind dein Freund: Benutze Sie auch!
      
  6. Kommentiere weise
    Kommentiere deine Funktionen, deine Klassen, eine extrem schwer zu verstehende Stelle im Code oder eine Stelle, in der du mal von der internen Norm abweichen musstest; Kommentiere nichts triviales; Kommentiere keine Kommentare -> das ist Code, kein Chat!
     
  7. Hacke nicht, komponiere
    Programmier kann jeder, wahrhaft entwickeln ist eine Kunst. Die richtige Wahl der Werkzeuge, das Arrangement der Funktionen, die Sitzordnung des Frameworks, die kurze Ruhe vor dem Beginn des Deployments … Du programmierst nicht, du komponierst Code und diese Kunst kann keiner Würdigen … außer ein anderer Codeponist.
     
  8. Bleib auf dem Teppich
    Ja, du bist der tollste Coder der Welt, aber keiner nimmt es zur Kenntnis? Liegt daran, dass keiner deinen Code lesen kann. Lesbarkeit ist wichtig, vor allem für dich selbst. Lies dich mal nach 12 Monaten und 4 Zwischenprojekten wieder in deinen „hochoptimierten“, „perfekten“ und „commentless“ Code ein … und dann weißt du, dass du (3),(4),(5) und (6) nicht verstanden hast. Sechs, setzen … Anfänger!
     
  9. Teile und herrsche
    Wussten schon die Römer, nur du weisst es wieder nicht. Teile dein Wissen, denn wenn du nicht fähig bist zu lehren, dann hast du es nicht richtig verstanden (siehe 1 und 2). Bringe dein Team auf deinen Wissenstand und messe dich regelmäßig mit stärkeren, mit schlaueren, mit „Wissenden“ … denn nur im direkten „Code-Wettkampf“, sei es nun mündlich oder als Code-Kata, kannst du erst über dich hinaus wachsen, deine Schwächen erkennen (und die hast du, glaube mir) und damit erst bist du in der Lage, dich zu verbessern. Wisse, dass du nichts weist; Plato wusste das auch … und du lernst das auch noch vom Kollegen nebenan!
     
  10. Don’t Panic
    Die wichtigste Regel und ich hoffe, ich muss dazu nichts mehr sagen!
Dies sind meine Regeln,
es gibt viele Regeln, aber diese sind meine…
Wie sehen deine aus???

KISS – oder wie umständlich muss es noch werden?

Passend zum DRY-Artikel nun der zum Thema KISS. Nein, nicht die Rock-Band-KISS, sondern ein Prinzip der Softwareentwicklung, das besagt: „Mache es so einfach wie möglich!“.

Immer wieder sehe ich Code, der akademisch bestimmt mit Note 1 ausgezeichnet wird. In Java, C++, Delphi oder anderen compilierenden Sprachen hat das ganze auch durch seinen Sinn und seine Daseinsberechtigung. Aber in PHP sieht die Sache anders aus.

PHP ist eine Interpretersprache und wird es auf absehbare Zeit auch erstmal bleiben. Interpretersprachen haben im Grundprinzip eines gemeinsam: Sie durchlaufen den Code während der Ausführung Zeile für Zeile, Schritt für Schritt. Und genau da liegt der Schwachpunkt: Je mehr Zeilen ein Code hat, desto länger braucht der Interpreter, den Code zu durchlaufen. Je länger der Interpreter braucht, umso größer wird die „Time-to-Response„, also diejenige Zeit, die zwischen Anforderung an den Server (Aufruf der Seite) und Antwort des Servers (Auslieferung der Seite, also des generierten Quelltextes) liegt. Und diese Zeit sollte „as small as possible“ sein (wer wartet schon gern auf seine Seite).

Dieses Problem potenziert sich meist, da der normale User erstmal eine (allgemeine) Startseite ansurft und sich dann durch die Seite bewegt; dabei ruft er meist spezialisierte Seiten mit mehr Aufgaben für den Server auf. Mehr Aufgaben, mehr Inhalt, mehr Code, länger warten, nicht gut!

Warum nun das ganze hier im Zusammenhang mit PHP?
In PHP lassen sich selbstverständlich schöne Objektorientierte Konstrukte bilden, die auch von vielen Seiten als „richtig“ proklamiert werden. Ein Beipiel sei dies (in Pseudocode, nicht wundern):



holeBenutzerdaten();
// mach was damit


// ab hier nun die funktionen, diese liegen alle
// in unterschiedlichen klassen, dateien usw.

function holeBenutzerdaten()
{
prüfeEingabe();
ladeBenutzerdaten();
return;
}

function prüfeEingabe()
{
prüfeSpezifischeEingabe;
ladeIrgendwasUnwichtiges;
prüfeNochmal;
}

function prüfeSpezifischeEingabe()
{
prüfeObEingabeValideIst
ja: prüfeDieEingabeNochmalMitWasAnderem
nein: ladeFehlerbehandlung; gibFehlerAnFehlersystem; zeigeFehler;
}

// So, und nun noch 20 Dateien mehr und ca. 60 Funktionsaufrufe

Nicht schön, denn hier wird, anstatt das Problem zu erledigen, von einer Funktion zur nächsten gesprungen. Unschön dabei: Jede Zeile kostet Zeit und die gilt es in einem guten Projekt so gering wie nur möglich zu halten.

Es gilt das Prinzip: So viel wie nötig, so wenig wie möglich! Nicht mehr, nicht weniger. Dazu aber noch später mehr.

Und nun Beispiel 2: Die reine Lehre sagt, dass veränderliche Werte in Variablen abgelegt werden sollen und diese Variablen dann an einen einheitlichen Ort. Nennen wir das mal „Config-Dateien“, dann kann sich jeder was drunter vorstellen. Diese Config-Files kennen wir alle, meist stehen da mindestens die MySQL Zugangsdaten drin, manchmal auch noch was anderes, zumeist belangloses. Das ist soweit auch gut und richtig und sollte – in einem gewissen Rahmen – auch gemacht werden … allerdings sollte man es dabei nicht übertreiben.

In diesem Beispiel möchte ich zeigen, wie man – unter dem Aspekt des Konfigurierens und Auslagerns – eine ganz simple Sache sehr kompliziert machen kann … und dafür in gewissen Kreisen sicherlich noch großen Beifall ernten wird.

Urspung des ganzen ist ein Aufruf, ähnlich wie dieser:


mysql_query("SELECT * FROM user");

Warum schreibt nun in die Config-Dateien nicht rein, wie die Tabellen heißen und benutzt dann nicht den statischen Wert, sondern die Variable? Und warum nehmen wir dann nicht eine Funktion? Die kann man dann immerhin noch mit Unit Tests auf ihre korrekte Funktion testen!? Das sieht dann so aus:


public function getTbluser() { return 'meineUserTabelleInMysql'; }

und die kann man dann so nutzen:


mysql_query("SELECT * FROM ".getTbluser());

Toll, oder? Ändert sich nun der Tabellenname, dann muss man das nur an einer Stelle ändern und gut ist. Kommt doch dem DRY-Prinzip zugute.
Noch besser wäre es doch, wenn wir nun auch alle Feldnamen in festlegen … weil … die können sich ja auch ändern. Also los, Feldnamen auch. *tipptipptipp* Toll. Ach ja, die Variablennamen könnten sich ja mal ändern. Also auch die rein und per $$ eingebungen, damit es auch geht.

Und der Code sieht dann doch gleich viel … übersichtlicher aus:


mysql_query("SELECT ".getTblUserField1().",".getTblUserField2()." FROM ".getTblUser()." WHERE ".getTblUserFieldSort()." = $$configFileTblUserFeldSort");

Super, oder? Kommt man nun noch dazu, diese ganzen, sich ständig verändernden SQL Kommandos noch zu ersetzen, dann hat man doch ein völlig einfach konfigurierbares System vor sich, oder etwa nicht?

Ihr merkt es schon, ich drifte ins Zynische ab – aber nur gaaanz leicht, das mag daran liegen, dass ich von diesem Code in letzter Zeit zu viel gesehen habe – , nochmal also zur Klarstellung:
Nein, so macht man es nicht!

Warum nicht? Dazu gibt es gleich mehrere Punkte.
Zum einen kann man es nicht mehr lesen. Das ist ein sehr wichtiger Punkt, unterschätzt das nicht, denn zum einen sitzt ihr nicht bis in alle Ewigkeit an einem Code – nichts ist schlimmer, als nach Monaten wieder alten Code lesen zu müssen und nicht zu verstehen – und zum anderen werdet ihr an der Qualität eures Codes auch innerhalb der Entwicklungsabteilung gemessen! Schwer verständlichen Code zu schreiben mag einen Marketing-Menschen noch leicht beeindrucken können, ein guter Programmierer dagegen wird euch – wenn ihr Glück habt nur leise – verfluchen.

Zum anderen muss der Interpreter jedesmal wieder in die entsprechende Funktion springen und das braucht Zeit. Nein, viel ist das nicht, wenn das nur eine Tabelle ist, nur ganz, ganz wenig Zeit, wirklich. Allerdings: Hat man erst so eine schöne Funktion, die einem die entsprechenden Tabellen und Felder referenziert, dann benutzt man das doch nicht nur für die Abfrage selbst, nein, auch im Code kommen dann anstelle der Feldnamen die Funktionsnamen vor.


$res = mysql_query("SELECT ".getTblUserField1().",".getTblUserField2()." FROM ".getTblUser()." WHERE ".getTblUserFieldSort()." = $$configFileTblUserFeldSort");
$name = $res[getTblUserField1()];
// anstelle von
// $name = $res['name'];

(ja, ich weiß, dass da ein mysql_fetch_irgendwas fehlt)

Und das für jede Tabellenabfrage im Code … und jedes Feld … in jeder Abfrage … und dazu noch in jedem Kontrollkonstukt im Code, also jeder for-Schleife, jeder Ausgabe, in jedem if, in jedem switch und und und … Leute, das summiert sich. Da kommen schnell dutzende Funktionssprünge vor und das sind Zeiten, die nicht sein müssen!

Warum sollte meine Anwendung langsamer sein, als es sein müsste. Die wird von ganz allein langsamer, sobald nämlich immer mehr Benutzer gleichzeitig was wollen, dann summieren sich die Zeiten nicht nur, nein, die multiplizieren sich mit jedem Request! Also, jeder Flaschenhals ist es wert, dass er refaktorisiert wird. Warum nicht gleich von Anfang an alles richtig machen?

Und mal ehrlich: Wie oft ändern sich die Tabellennamen und man ihr als Entwickler müsst wirklich nur die Configs ändern? Na, ehrlich, komm *inDieSeiteStubs* Na also, noch nie gesehen, jede Umstellung der Tabellennamen hatte schon immer eine mehrstündige Umstellungsphase begründet … zusammen mit dem Verlust einiger wichtiger Gramme Körpergewicht 😉

Und hatten wir nicht eben erst erwähnt, wie wichtig die Lesbarkeit des Codes ist? Sicher, ihr habt das Projekt grade erst begonnen und wisst noch alles aus dem Kopf. Aber, wie gesagt, ihr seit meist nicht allein an einem Projekt und – selbst wenn – auch nicht immer „am Stück“ dabei. Euer Kollege würde gern wissen, warum ein bestimmter Request langsam ist oder gar nicht funktioniert und schaut im Code noch und trifft auf so einen Query. Nun muss erstmal mühsam der eigentliche, der „echte“ Query zusammengebaut werden, denn der Kollege hat keine Ahnung, welche Felder ihr ansprecht.

Aber der Tabellenname könnte sich doch mal ändern!
Warum sollte sich der Tabellenname ändern? Ja, auf Shared-Hosting-System kommt es schon mal vor, dass man in einen Webspace viele Webanwendungen packt und da kann es auch vorkommen, dass mehrere Anwendungen ihre Benutzertabelle eben ‚user‘ nennen. Warum auch nicht, es ist der passendste Name dafür! In solchen Fällen – wenn ich also weiß, dass so eine Situation eintreten kann – benutze ich die Option eines Praefix, der jedem Tabellennamen vorgestellt wird und an zentraler Stelle definiert ist.


// Im Config-File
define('DB_PRAEFIX','myPraefix_');

// Im Code
mysql_query("SELECT * FROM ".DB_PRAEFIX."user");

Das hat den Vorteil, dass man den SQL immer noch lesen kann und auch die Tabelle auf dem DB-Server wiederfindet, auch wenn man keine Kenntnis über den Inhalt von DB_PRAEFIX hat. Der Code bleibt lesbar und so ziemlich jeder Entwickler weiß auch, warum ihr das macht.

DAS ist es zum Beispiel, was dass KISS Prinzip sagt: Macht es einfach! Nicht nur euch, sondern auch anderen. Nein, ihr sollt nun dabei nicht vergessen, Sicherheitsmechanismen einzubauen oder Usereingaben zu filtern, wir wollen auch nicht zurück ins PHP3 Monolithen-Zeitlalter, aber dazu bedarf es keiner Funktion, die eine Funktion aufruft, die eine Funktion aufruft, die wiederum … ihr ahnt es schon.

Meine KISS Anforderungen sind ungefähr diese

  • – Die Gesamttiefe der Funktionsaufrufe darf 3 Ebenen nicht überschreiten (die aufgerufene Seite nicht eingeschlossen). Je weniger, desto besser.
  • – Funktionen sollten so wenig wie nötig aufgerufen werden
  • – Funktionen sollten etwas machen, nicht nur Namen liefern (return ‚tbluser‘; )
  • – Funktionen sollten das machen, wofür sie da sind. Nicht mehr!

„Klar“, sagt nun jeder, „aber wie bekomme ich dies oder das dann hin, das geht dann gar nicht mehr“.
Bei vielen dieser Fragen kann man sagen, es ist die berühmte Ausnahme von der Regel und sicherlich ist hier und da eine Ausnahme sicherlich ratsam. Man soll schließlich das ganze gerede und die ganzen schönen Buzzwords nicht als „In-Stein-gemeisselt“ verstehen. Leider zeigen viele dieser Ausrufe aber auch, wie groß die Abhängigkeit von bestimmten Frameworks oder Programmierparadigma ist.

Ich will hier keine Diskussion auslösen über Sinn und Unsinn von Frameworks oder Paradigmen, ich zeige – wie so oft in der Softwarearchitektur – das Optimum. Der Rest liegt bei euch, der Weg ist das Ziel 😉

Über eure konstruktive Meinung dazu würde ich sehr freuen – obwohl ich mehr mit empörten Kommentaren rechne *schnellUnterDenTischDuck*!

Pattern? Sowas mache ich nicht!

Der PHP Hacker fragt „Haben Pattern versagt?“ und hier ist mein Senf dazu.

Mag jetzt auch mal ein wenig den Stil der „anonymen Programmierer“ haben, aber ich programmiere nicht mit dem Ziel, ein bestimmtes Pattern umzusetzen, sondern mit dem Ziel, ein bestimmtes Problem zu lösen. Dies mache ich auf dem – für mich – besten Wege und der Weg ist für jedes Problem, sogar für jeden Kunden, anders. Meist weiß ich gar nicht, dass ich gerade ein bestimmtes Pattern umsetze oder dass der Weg, wie ich etwas mache, schon einen „XY Pattern“ namen hat.

Schande über mich – ich würde bei dem im Artikel genannten Recruiter wohl keinen Job bekommen – aber meine Fragen wären wirklich:

  1. Muss man Pattern (auswendig) kennen, um gut programmieren zu können?
    Sicher sind Kentnisse über „best practices“ – und aus diesen sind die Pattern ja entstanden – hilfreich, aber muss ich deswegen gleich „in Pattern denken“? Sicher nicht.
  2. Ist es sinnvoll, auf Biegen und Brechen ein Pattern umzusetzen, auch wenn die Problemlösung darunter leidet?
    Ganz klar: Nein! Das Pattern sollte sich immer der Problemlösung unterwerfen! Was nützt es mir, dass mein Code in 2.000 Zeilen das XY Pattern sauberst umgesetzt hat, die Problemlösung aber nur 20 Zeilen lang gewesen wäre (und kein Spagetthi-Code ist!).
  3. Muss ich mich nun schämen weil ich das XY Pattern nicht kenne oder bin ich etwa kein guter Programmierer?
    Ich denke, es kommt drauf an. Wenn man die „best practices“ versucht umzusetzen und sauberen, lesbaren, skalierbaren und funktionsfähigen Code schreibt, dann muss man nicht unbedingt sagen können, dass dies nun teilweise X, Y und Z Pattern darstellt. Es kommt IMHO drauf an, dass der Code die o.a. Kriterien erfüllt und nicht zwanghaft Punkt 2 umsetzt.

Das wäre mein – wie gesagt – mein Senf dazu. Was denkt ihr darüber?

Mein Beitrag zum Developers Shame Day

Mein Beitrag zum Developers Shame Day am 03.11.2010:

Oh, wie ich mich schäme, der Code ist von Oktober 2002, stammt aus einem Teil, der für ein Onlinerollenspiel vorgesehen war (damals gab es das Wort Browserspiel noch gar nicht – trotzdem wollte ich sowas bauen; leider war das Projekt damals viel zu groß für mich).

Im Großen und Ganzen habe ich allerdings grade dadurch, dass ich diesen Code geschrieben habe, davon genervt war, wieviel „Arbeit“ das immer wiederkehrende Tippen von < und > überdrüssig war und hiermit erste, zarte Schrittchen im Bereich PHP und Klassen getätigt habe überhaupt erst näher zu OOP in PHP 3+4 und Verwendung von Template Engines (direkt im Anschluss war es FastTemplate, kurz dannach Smarty … bis heute) … soviel zum Thema „sich weiterentwickeln durch schlechten Code“!

Hab sowas mal bei thedailywtf gesehen, hatte es aber in dem Moment doch schon zu sehr verdrängt, als dass da was geklingelt hätte.


class pageproducer
{
function getDoctypeInfo()
{
return "\n\n";
}

function getStartingTag($tagname)
{
return "<".$tagname.">\n";
}

function getEndingTag($tagname)
{
return "\n";
}

function getMetaTagEquiv($name,$content)
{
return "";
}

function getTitle($name)
{
return "".$name."";
}

function getCSS($cssurl)
{
return "";
}

function getHeader()
{
$header = $this->getMetaTagName( "keywords", "") . "\n";
$header .= $this->getMetaTagName( "description", "") . "\n";
$header .= $this->getMetaTagName( "robots", "") . "\n";
$header .= $this->getMetaTagName( "revisit-after", "") . "\n";
$header .= $this->getMetaTagEquiv( "Content-Type", "text/html; charset=iso-8859-1") . "\n";
$header .= $this->getMetaTagEquiv( "expires", "0") . "\n";
$header .= $this->getTitle(HEAD_NAME) . "\n";
$header .= $this->getCSS("rpg.css") . "\n";
return $header;
}

function getHeadSection()
{
$head = $this->getStartingTag("head");
$head .= $this->getHeader();
$head .= $this->getEndingTag("head");
return $head;
}


}

Ich persönlich finde das Konstrukt wirklich schlimm und oberpeinlich; ich komme also heute mit Papiertüte über dem Kopf zur Arbeit 😉 Aber was soll’s, mittlerweile sieht mein Code nicht mehr so aus; mittlerweile übergebe ich das Charset als Parameter #muhaha 😉

Mal ernsthaft: Ich finde die Idee des Ganzen „Developers Shame Day“ sehr gut. Gut für Newbies, dass auch wir „Pros“ mal „Newbies“ und „Script-Kiddies“ waren; gut für uns „Pros“, um unsere eigenen Wurzeln zu reflektieren und nicht zu vergessen.