am 11. Juni 2009
Nachdem wir die letzten Tagen kaum programmierlastige Themen hatten, hier mal wieder was zum Nachdenken. Und zwar geht es um einfache Parameter. Jeder kennt sie, jeder verwendet sie in Funktionen und Methoden. Parameter werden seit der Version 5 von PHP als Referenz übergeben auch wenn man den & Operator nicht explizit angibt. Zumindest gilt dies für Objekte. Primititve Typen verhalten sich anders. Hier arbeitet man mit Kopien.
Soviel zu den Grundlagen. Worauf ich eigentlich hinaus will, ich der Umgang in einer Methode mit denen ihr übergebenen Parametern. Sollte man die übergebenen Parameter verändern? Ich gebe mal ein Beispiel. Der ein oder andere kennt es vielleicht noch aus einem älteren Artikel.
function normalizeObject( $object )
{
$object = doSth( $object );
return $object;
}
$object = normalizeObject( $object );
In diesem Beispiel wird das per Parameter übergebene Objekt verändert und wieder zurückgegeben. Sieht eigentlich aus wie eine Standardmethode, wie sie in jedem Stück Software auch vorkommen kann. Aber warum macht der Mann an der Tastatur so einen Aufstand?
Ich verändere den übergebenen Parameter, ohne jemand einen Anhaltspunkt zu geben, dass ich dies mache. In meinem Beispiel macht das absolut nichts aus, denn ich hantiere danach wieder mit dem Objekt und überschreibe die geschehenen Änderungen wieder. Wenn wir aber die gegebene Funktion ein wenig verändern, dass sieht es schon ganz anders aus.
function normalizeObject( $object )
{
$object = doSth( $object );
return $object;
}
$object2 = normalizeObject( $object );
Führt man dieses Programm aus, so verändern wir nicht nur $object2, sondern auch $object, ohne das wir das mitbekommen. In den meisten Fällen wäre die Anwendung der Funktion eher die erste, deswegen macht man sich kaum Gedanken, aber wenn man es dann doch mal anders macht, so kann man die Seiteneffekte nicht abschätzen.
Tut mir also den Gefallen, alle Parameter unangetastet lasst. Wenn ihr sie verändern wollt, dann cloned sie einfach vorher.
function normalizeObject( $object )
{
$workingObject = clone( $object );
$workingObject = doSth( $workingObject );
return $workingObject;
}
$object2 = normalizeObject( $object );
Sieht zwar ein wenig aufwändiger aus, aber es wird euch wirklich helfen, wenn ihr mal wieder einen Fehler finden müsst, der durch so eine Fehlkonstruktion passiert. Wenn ich ehrlich bin, würde ich sogar diesen Umgang mit primitiven Typen vorschlagen. Es ist zwar nicht notwendig, aber wenn man sich mal dran gewöhnt hat, dann stabilisiert man seine Programme auf diese Weise. Wer also Ahnung im Umgang mit dem PHP_CodeSniffer hat, der sollte mal eine Regel schreiben, die so etwas verbietet.