am 16. September 2008
Nachdem der gestrige Eintrag eher in die Hose ging – ja man sollte noch einmal drüber lesen – versuche ich heute ein wenig mehr Zeit rein zustecken um fehlerfrei zu bleiben. Dabei wird das Thema des Tages nicht unbedingt was neues für viele Entwickler sein. Es geht um die Auswertung von logischen Ausdrücken in PHP. Da eine solche Frage teil unseres Bewerbertests ist und heute wieder einer die Chance bekommt Teil unseres Teams zu werden, habe ich gedacht ich könnte doch mal dieses „Problem“ auflösen.
Eigentlich ist es ganz trivial. Wenn ich eine Aneinanderreihung von Verundungen (Konjunktion) habe, also eine Konjunktive Normalenform, dann wird der komplette Ausdruck falsch, sobald eine der Aussagen falsch ist. Bei Veroderungen ist es genau andersherum. Sobald eine der Ausdrücke wahr ist, ist die ganze Aussage wahr.
Da man auf diese Art eine logische Aussage sehr schnell berechnen kann, hat PHP diese Regeln bereits eingebaut. Als erstes Beispiel soll folgender Code gelten.
<?php
$b = false;
$c = true;
$a = $b && $c && $d; // da $b false ist, kann der ganze Ausdruck nicht mehr wahr werden
$a = $b || $c || $d; // da $c wahr ist, kann der ganzer Ausdruck nicht mehr falsch werden
?>
PHP ist hier, wie eigentlich alle Programmiersprachen relativ intelligent – oh mein Gott, dass gerade ich diesen Satz einmal sagen werde – PHP hört also auf den Ausdruck weiter zu evaluieren, sobald das Ergebnis feststeht. Im ersten Fall wäre dies bereits noch der Überprüfung von $b und im zweiten nach $c. In meinem Beispiel kann dies auch zum Glück noch nicht zu Problemen führen. Unberechenbar wird das ganze dann erst, wenn man versucht in einer solchen logischen Verkettung Wertzuweisungen vorzunehmen.
<?php
$a = 0;
$b = 0;
if ( $a > 0 && ++$b > 0 ) echo „a“;
if ( $b > 0 && ++$b > 0 ) echo „b“;
?>
So oder so ähnlich sieht unsere Frage im Bewerbertest aus und leider sagen die meisten, dass dieses Programmstück den Buchstaben „b“ ausgibt. Macht es aber nicht. Wie ich bereits beschrieben habe, schaut sich PHP den ++$a Ausdruck gar nicht mehr an, denn egal welchen Wert er annimmt, der Gesamtausdruck bleibt falsch. Man sollte also nur Zuweisungen in einem solchen Ausdruck machen, wenn man ganz genau weiß, was man macht. Wenn man also will, dass beide Ausdrücke ausgewertet werden, dann muss man die Auswertung vorher machen und später nur noch die Relationen prüfen.
<?php
$a = 0;
$b = 0;
++$b;
if ( $a > 0 && $b > 0 ) echo „a“;
if ( $b > 0 && ++$b > 0 ) echo „b“;
?>
Als kurzes Fazit würde ich noch gerne jedem PHP Entwickler mitgeben, dass es eigentlich kaum der Fall sein sollte, dass es Vorteile mit sich bringt, wenn man Zuweisungen innerhalb eines logischen Ausdrucks macht. Auch wenn es manchmal sinnvoll sein kann, so ist es doch für andere Programmierer sehr schwer zu verstehen und sollte deswegen in Maßen eingesetzt werde.