Facebook
Twitter
Google+
Kommentare
6

Logische Ausdrücke in PHP

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.

Über den Autor

Nils Langner

Nils Langner ist der Gründer von "the web hates me" und auch der Hauptautor. Im wahren Leben leitet er das Qualitätsmanagementteam im Gruner+Jahr-Digitalbereich und ist somit für Seiten wie stern.de, eltern.de und gala.de aus Qualitätssicht verantwortlich. Nils schreibt seit den Anfängen von phphatesme, welches er ebenfalls gegründet hat, nicht nur für diverse Blogs, sondern auch für Fachmagazine, wie das PHP Magazin, die t3n, die c't oder die iX. Nebenbei ist er noch ein gern gesehener Sprecher auf Konferenzen. Herr Langner schreibt die Texte über sich gerne in der dritten Form.
Kommentare

6 Comments

  1. Ich bin irgendwie verwundert das bei Einstellungstest obige Konstrukte abgefragt werden. Wie du ja selber im nächsten Absatz schreibst, würdest du dringend davon abraten so etwas zu schreiben. Wieso fragst du dann solch ein theoretisches Konstrukt ab? Was soll der Bewerber da zeigen? Was bringt es für einen Mehrwert wenn er diese Aufgabe richtig löst?

    Ich glaube nicht das solche Test dazu führen mittelmäßige von guten bis sehr guten Programmierern zu unterscheiden. Dafür sind doch ganz andere Dinge wichtig, was meist auch von den Testern selbst bestätigt wird. Wieso findet das aber selbst so wenig Beachtung, im Gegensatz dazu aber solche Nebensächlichkeiten?

    Reply
  2. Hallo Ulf, keine Sorge, das ist nur ein Teil einer Aufgabe, in der es einfach darum geht ein paar Probleme in einem Stück Source Code zu finden. Da wir relativ viel Legacy Code haben kommt dieser Fall bei uns leider relativ häufig vor. Die restlichen 13 Fragen gehen eher in Richtung Design Pattern, OOP, UML und auch SQL.
    Aber vielleicht hast du ja auch noch einen Tipp, was deiner Meinung nach gefragt werden sollte.

    Reply
  3. Hallo Nils,
    nö, leider habe ich keine Tipps für bessere Fragen. Ich kann nur auf frustrierende Fragen für den Bewerber hinweisen und oben genannte Frage gehört für mich eindeutig dazu.

    Design Pattern, OOP, UML klingt grundsätzlich gut. Natürlich kommt es auch immer auf die Stelle der offerierten Position an, aber es gibt nichts Schlimmeres eine gute Stelle auszuschreiben darauf eine gute Bewerbung zu schreiben und dann einen Praktikanten-Test zu machen.

    Just my thoughts…

    Viele Grüße
    Ulf

    Reply
  4. Genau genommen ist das Verhalten des PHP-Interpreters nicht so genau definiert, es kommt drauf an wie der Compiler/Interpreter die if-Abfrage auflöst. Schlaue Interpreter könnten durchaus erst die 2. AND-Bedingung prüfen, wenn sie feststellen, dass die Prüfung hier viel einfacher ist als bei der ersten Bedingung. Außerdem gibt es in PHP noch die Operatorreihenfolge, und da steht „++“ vor „AND“ 🙂 Alles nicht so einfach 🙂

    Also die einzig richtige Antwort des Bewerbers wäre: „Code sofort refaktorisieren“. Obiger Code ist ja fast so schlimm, wie Schleifenzähler zu manipulieren 🙂

    VG
    Jan

    Reply
  5. Das ist zwar schon ein älterer Beitrag (kam aber gerade per Twitter rein 😉 ), aber wo wird $a in dem ersten Beispiel denn weiter hochgezählt wie beschrieben?

    Also gibt das erste Beispiel nichts aus und das zweite „b“

    Reply

Leave a Comment.

Link erfolgreich vorgeschlagen.

Vielen Dank, dass du einen Link vorgeschlagen hast. Wir werden ihn sobald wie möglich prüfen. Schließen