Heute möchte ich einmal etwas über das Clean Code Developer (CCD) Projekt erzählen. Worum es dabei geht lässt sich schnell auf den Punkt bringen: besseren Code zu schreiben. Dafür wurden verschiedene Best-Practises gesammelt und strukturiert.
Grundlage bietet das Wertesystem des CCD. Dies besagt, dass guter Code folgende Eigenschaften erfüllt: Evolvierbarkeit, Korrektheit, Produktionseffizienz und Reflexion.
Evolvierbarkeit bedeutet, dass ein Code auch bei Änderung der Anforderungen anpassbar sein muss. Diese Flexibilität hat natürlich ihre Grenzen jedoch sollte man sie immer im Hinterkopf behalten. Korrektheit besagt, dass der Code eben das tun soll was er auch tun sollte. Produktionseffizienz beinhaltet wie lange die Entwicklung dauert und welche Ressourcen dabei verbraucht werden. Und Reflexion bedeutet, dass man sein Wissen und seine Erkenntnisse auch über den Code immer wieder überdenken und neu bewerten muss, da besonders auch in der Informatik sich viele Rahmenbedingungen ändern und auch immer neues Wissen geschaffen wird.
Um diese Ziele zu erreichen wurden verschiedene Prinzipien und Praktiken gesammelt und in sechs verschiedene Grade eingeteilt. Diese Grade kann man sich ähnlich wie die Grade beim Budosport vorstellen. Entsprechend dem Grad trägt man auch verschiedenfarbige Armbänder. Die Grade sind: Rot, Orange, Gelb, Grün, Blau, Weiß. Wobei der Weiße Grad ausdrückt, dass man die Prinzipien und Praktiken der unteren Ränge alle vereinigt. Was jedoch das besondere und wie ich finde auch gute an den Graden des CCD-Systems ist, dass man sich nicht auf dem weißen Grad ausruhen kann, sondern dass man danach einfach wieder mit dem roten Grad weitermacht. Weil man erreicht eben nie die Stufe des Allwissenden sondern soll sich bewusst sein, dass das Leben ein ewiger Kreislauf von Lernen ist. Klingt spirituell ist aber eher sehr praktisch orientiert. Weil wir lernen eben jeden Tag hinzu.
Heute hatte ich einen interessanten Effekt in Bezug auf die Vererbung von statischen Klassenvariablen.
Gegeben sei folgende Klasse, welche einige Config-Daten halten soll:
abstract class Config
{
private static $definitions = array();
protected static function addDefinition ($key, $value)
{
self::$definitions[$key] = $value;
}
protected static function getDefinition ($key)
{
return self::$definitions[$key];
}
}
Die Sicherheitsabfragen und Dokumentation habe ich zum einfacheren Verständniss mal entfernt. Dann haben wir zwei weitere Klassen, welche von unserer abstrakten Config klasse erben.
class Config_A extends Config
{
public static function addA ($key, $value)
{
self::addDefinition($key, $value);
}
public static function getA ($key)
{
return self::getDefinition($key);
}
}
class Config_B extends Config
{
public static function addB ($key, $value)
{
self::addDefinition($key, $value);
}
public static function getB ($key)
{
return self::getDefinition($key);
}
}
Nun bestücken wir unsere Klassen mal mit Daten:
Config_A::addA ('treiber', 'configA');
Config_B::addB ('treiber', 'configB');
echo Config_A::getA ('treiber');
Nun würde man erwarten, dass auch wieder ein ‘configA’ heraus kommt. Da die statische Klassenvariable jedoch in der abstrakten Oberklasse liegt verwenden beide Unterklassen die selbe Variable. Die Ausgabe lautet nämlich: ‘configB’.
Wie kann man das Dilema also Lösen? Mein erster Ansatz war: Wir verschieben die Variable in die Unterklassen.
abstract class Config
{
protected static function addDefinition ($key, $value)
{
$definitions = self::getDefinitions();
$definitions[$key] = $value;
}
protected static function getDefinition ($key)
{
$definitions = self::getDefinitions();
return $definitions[$key];
}
abstract protected static function getDefinitions ();
}
class Config_A extends Config
{
private static $definitions = array();
protected static function getDefinitions()
{
return self::$definitions;
}
...
}
Analog dazu wird Config_B implementiert.
Jedoch sind abstrakte statische Methoden nur in PHP 5.0.x und 5.1.x erlaubt. Eine weitere Lösung wäre es, aus den Klassen einfach Instanzklassen zu machen. Bei meinem Framework mag ich es jedoch lieber nicht so viele Objekte zum Konfigurieren umher zu jonglieren sondern einfach den Zustand des Systems mit einer statischen Klasse zu verändern.
Letztendlich habe ich folgende Lösung umgesetzt:
abstract class Config
{
protected static $definitions = array();
protected static function addDefinition ($class, $key, $value)
{
self::validateDefinitions($class);
self::$definitions[$class][$key] = $value;
}
protected static function getDefinition ($class, $key)
{
self::validateDefinitions($class);
return self::$definitions[$class][$key];
}
private static function validateDefinitions ($class)
{
if (! isset(self::$definitions[$class])) {
self::$definitions[$class] = array();
}
}
}
class Config_A extends Config
{
public static function addA ($key, $value)
{
self::addDefinition(__CLASS__, $key, $value);
}
public static function getA ($key)
{
return self::getDefinition(__CLASS__, $key);
}
}
So das ist der erste Eintrag.
Noch ein Blog. Wozu? Die Geschichte dazu ist ganz einfach erklärt:
Vor kurzem bin ich auf die Clean Code Developer Initiative gestossen. Dabei geht es darum sich als Software-Entwickler auch weiter zu entwickeln und einen besseren Code zu erzeugen. Dafür gibt es verschiedene Ränge. Ich werde das ganze Projekt sicher noch in einem weiteren Artikel weiter beleuchten. Auf jeden Fall ist eine Regel des grünen Grades, dass man sein Wissen auch weitergeben soll. Dafür ist dieser Blog gedacht.
Ich möchte einige Erfahrungen aus meinem Projektalltag weitergeben und auch bestimmte Themen aus der PHP-Welt beleuchten oder einfach meine Gedanken dazu kund tun. Und auf diese Weise mit der Entwicklergemeinde in Kontakt treten.
Nun denn, dann bin ich mal gespannt was daraus wird