• Arrays und “Strings”

    von am 29. Dezember 2009

    So das Jahr ist fast rum. Morgen wird es den letzten Beitrag 2009 geben. Da ich morgen einen kleinen Jahresrückblick vorbereitet habe, habe ich heute noch mal die Chance mich ein wenig über PHP aufzuregen. Ja genau: ein kleines „What the fuck“ zum Jahresende. Eigentlich ist es ein wtf über das ich mich schon eine Weile aufrege, habe aber heute erst Lust darüber zu schreiben.

    Ihr wisst ja, dass ich ein Freund der statischen Code-Analyse bin. Ich habe auch schon einige Artikel über den PHP_CodeSniffer veröffentlicht. Leider macht es einem PHP immer mal wieder besonders schwer Code zu analysieren. Schwache Typisierung, mein Freund „mixed“ oder variable Variablen machen einem zum Beispiel oft einen Strich durch die Rechnung. Tja dass ich halt der Preis, den man sich erkauft hat und dafür eine schnell erlernbare Sprache entwickelt hat. Das passt schon irgendwie. Zumindest rege ich mich nicht mehr drüber auf.

    Betrachten wir aber mal einen ganz einfachen Fall eines Sniff für den Code Sniffer. Finde mir alle kleingeschriebenen Konstanten. Ganz einfach? Naja ich würde sagen Konstanten sind einfach zu finden. Doch leider fällt mir da mindestens ein Fall ein, bei dem das absolut nicht klappt. Nehmen wir den folgenden Ausdruck:

    $array[ersterEintrag] = "1";

    Tja, ist ersterEintrag denn jetzt als String zu interpretieren oder ist es eine Konstante? Oder wenn es beides sein könnte, was nehme ich dann zuerst.

    Ich finde es ja toll, dass eine Sprache Rücksicht auf uns Entwickler nimmt, aber das geht doch ein Stück zu weit. Warum ist es genau an dieser Stelle erlaubt einen String nicht in Anführungszeichen zu setzen? Was unterscheidet dies von allen anderen Anwendungsfällen? Ich würde sagen NICHTS! Ich tippe mal drauf, dass sich schon viele Fehler in Programmen eingeschlichen haben, weil irgendjemand die Konstante ersterEintrag definiert hat und damit alle Arrays kaputt gemacht hat. Wobei? Wenn man konsequent mies programmiert, dann könnte sich das Problem selbst rauskürzen. Egal. Tut mir den Gefallen und verwendet immer Anführungszeichen um eure Strings herum, denn sonst bekommt ihr eines Tages Besuch von mir und bekommt den Hintern versohlt.

    Nils Langner

    Auch wenn Ihr es mir nicht glauben werdet, aber ich habe nichts gegen PHP. Ich rege mich einfach nur gerne auf. Ok so schlimm ist es auch nicht. Eigentlich wollte ich schon immer einen Blog haben und da ...

    Zum Profil von Nils Langner

    16 Kommentare »


    • Spider
      am 29. Dezember 2009 um 08:33 Uhr

      AMEN … ich versuch das seit Monaten irgendwie dem Azubi zu erklären, dieser weigert sich einfach das zu verinnerlichen.
      Ich habe es ihm zwar nun “befohlen” in dem ich es in die Coding Vorschriften mit aufgenommen habe.
      Aber Sinn der Sache ist es ja nicht, solche elementaren Inhalte auf zu zwingen.

      -Spider

      PS: Die selbe Qual mit dem ?> Tag, an einer Sinn freien Stelle.


    • juhu
      am 29. Dezember 2009 um 10:15 Uhr

      Mein Reden. Popo Haue für alle, die Strings nicht in Hochkommas schreiben. :-)


    • Tobi
      am 29. Dezember 2009 um 10:45 Uhr

      Ich wusste nicht, dass so etwas überhaupt geht. JavaScript ist ja z.T. ähnlich tolerant.

      Interessant wäre es ja schon hier ein Tool zu schreiben, das solche Fehler erkennt. Die Abstrakte Interpretation bietet hier ja zahlreiche Möglichkeiten. Vielleicht experimentiere ich da mal.

      Grüße
      Tobi


    • Andre Moelle
      am 29. Dezember 2009 um 11:00 Uhr

      Führt dieser Code wirklich nicht zu einer Notice?!


    • Martin Kuckert
      am 29. Dezember 2009 um 12:38 Uhr

      Es würde schon reichen, dass error_reporting auf E_ALL hochzuschrauben. Wie Andre schon sagt, führt diese Verwendung eines Strings – natürlich – zu einer Notice.


    • unset
      am 29. Dezember 2009 um 12:38 Uhr

      Mhmm, bei mir führt das zu einer Notice:


      error_reporting(E_ALL | E_STRICT);
      ini_set('display_errors', 1);

      $foo = array();
      $foo[bar] = 'zapp';


    • Nils Langner
      am 29. Dezember 2009 um 12:45 Uhr

      Na dann bin ich mal dafür, dass wir E_STRICT als Standard mit PHP ausrollen :)


    • XGremliN
      am 29. Dezember 2009 um 18:58 Uhr

      Wenn wir hier schon so strikt sind, sollten Zahlen nicht wie im o.g. Beispiel als Strings zugewiesen werden, sondern als String.
      Also:
      $array['ersterEintrag'] = 1;


    • XGremliN
      am 29. Dezember 2009 um 18:59 Uhr

      Da hat sich doch der Fehlerteufel eingeschlichen ;-)
      Muss natürlich heißen: “…sondern als Zahl.”


    • Christoph
      am 30. Dezember 2009 um 00:05 Uhr

      Wer macht denn sowas? ;)
      Ich kann juhu nur zustimmen: Einfach, konsequent, eindeutig.


    • Norbert Bartels
      am 31. Dezember 2009 um 12:23 Uhr

      ersterEintrag ist eine Konstante. Jedoch wurde diese zuvor nicht definiert und daher entspricht der Inhalt der Konstante ihrem Namen als String. Daher funktioniert diese Sache auch so schön.

      http://de2.php.net/manual/en/language.constants.syntax.php

      Im 3. Abschnitt ist es beschrieben.

      Viele Grüße


    • Simon
      am 1. Januar 2010 um 23:12 Uhr

      Naja, das stimmt so nicht, was du da schreibst.
      PHP interpretiert ersterEintrag schon als Konstante. Wenn er sie aber nicht findet, dann gibts eine Notice und DANN wird die Konstante zum String…

      Unschön ist es aber trotzdem


    • René
      am 1. Januar 2010 um 23:21 Uhr

      @Nils: Ab PHP 6 soll E_STRICT in E_ALL enthalten sein (siehe Zeile 480 in http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/php.ini-development?view=markup).

      Davon mal abgesehen, wird laut Dokumentation ein E_NOTICE statt eines E_STRICT geworfen (http://php.net/manual/en/language.types.array.php#language.types.array.foo-bar). Leider werden auch E_NOTICE in vielen PHP-Konfigurationen gefiltert.

      Meist fallen derartige Fehler spätestens beim Build (in den Unit-Tests) der PHP-Anwendung auf. Egal, wie die Entwickler PHP konfiguriert haben, beim Build wird eine sehr restriktive Konfiguration verwendet, wo auch E_NOTICE- und E_STRICT-Fehler auffallen. Und solange das Build nicht fehlerfrei durchläuft, solange kann auch die Anwendung nicht released werden (so zumindest die Theorie).

      Im Zeitalter von OOP sollte man prinzipiell auf die Definition globaler Konstanten verzichten. Sowas kann man wunderbar mittels Klassenkonstanten abbilden. Das hat 2 Vorteile: Selbst wenn ein Entwickler böses tut und obige Array-Anweisung verwendet, kann zumindest keine globale Konstante den Code kaputt machen. Die define()-Anweisung scheint nicht gerade optimal für die Performance einer PHP-Anwendung zu sein. Je mehr man darauf verzichtet, um so mehr tut man Gutes für die gesamte Performance (siehe http://www.andreas-haerter.de/Blog_post-Bessere-Performance-durch-Klassenkonstanten-statt-define.html).


    • KingCrunch
      am 4. Januar 2010 um 23:38 Uhr

      So als Anmerkung:
      1. Link kaputt
      2. Nett, dass der Author des Artikels nur Thesen in den Raum wirft ^^
      3. Immerhin gibts ab 5.3 jetzt auch namespace-Konstanten ;) Künstlich über Klassen für Konstanten Namensräume zu erzeugen klingt irgendwie dreckig.


    • René
      am 5. Januar 2010 um 09:32 Uhr

      > 1. Link kaputt

      Schade, dass die Blog-Software zwar Links erkennt, aber die schließende Runde Klammer mit dazu zählt. :-( Zum Glück gibt es aber noch Menschen, die die Technik des “Mark & Copy & Paste” mit der Maus beherrschen. ;-)

      > 2. Nett, dass der Author des Artikels nur Thesen in den Raum wirft

      Wenn die Betonung pauschal auf “nur” liegt, stimme ich nicht zu. Was genau wird als These betrachtet (vorausgesetzt, man hat die Links gelesen)?

      > 3. Immerhin gibts ab 5.3 jetzt auch namespace-Konstanten ;) Künstlich
      > über Klassen für Konstanten Namensräume zu erzeugen klingt irgendwie
      > dreckig.

      Schon ne eigenartige Wortwahl. Aber als “dreckig” würde ich das nicht bezeichnen. Mal davon abgesehen: Es gibt Business-Anwendungen, die können nicht von heute auf morgen auf PHP 5.3 migriert werden. Da helfen dann Klassenkonstanten mehr als massenhaft define()-Anweisungen. Wer derartigen Code schreibt (eine statische Klasse als Konstanten-Container), ist selbst Schuld. Wo wir schon bei PHP 5.3 sind: Es gibt nen neues Schlüsselwort “const”, was define() ebenfalls vorzuziehen ist.


    • KingCrunch
      am 6. Januar 2010 um 01:46 Uhr

      2. Es wird unkommentiert in den Raum geworfen, dass per ‘define’ deklarierte Konstanten langsamer sind. Die Erklärung klingt zwar schlüssig, was mir aber fehlt ist zum Beispiel wie sich das bemerkbar macht. Wenn die Differenz unter 10% liegt, nehme ich dafür keinen Designbruch in Kauf. Dies gilt sowohl mit, als auch ohne APC, wobei hier noch zu bemerken ist, dass APC nichtmal standardmässig mitgeliefert wird und deshalb für viele Fälle unerheblich ist (noch ;) PHP6 kommt bestimmt).

      3. Jep, über das Wort “dreckig” hab ich auch gegrübelt, entspricht aber dem klassischen “Quick&Dirty” ;) Von “massenhaft define()-Anweisungen” habe ich nicht geredet, Klassenkonstanten haben durchaus ihre Berechtigung, aber das ist eben _nicht_ Konstanten in Namensräume zu verpacken. So als Faustformel hielt für mich immer her: Wenn Die Konstante nur von/für eine Klasse (oder dessen Erben) gebraucht wird, isse ne Klassenkonstante. Globale Variablen sind nunmal irgendwie … global ^^

      == “Wo wir schon bei PHP 5.3 sind: Es gibt nen neues Schlüsselwort “const”, was define() ebenfalls vorzuziehen ist.”

      Das meinte ich doch mit “Namespace-Konstanten”. Und ja, das is vermutlich vorzuziehen. Ja: Es ist wesentlich lesbarer (wunderte mich eh, wieso das jetzt erst kommt). Vielleicht: Performance. Das müsste man erstmal prüfen.

      Nur so als Anekdote. Versuch mal folgendes:
      < ?php
      namespace abc\de;
      const HALLO = ‘Welt’;
      define (‘abc\de\HALLO’,'Welt’);
      das wirft ein Fehler ;) Ich für mich habs mal “Namespace-Injektion” getauft und funktioniert für Klassen (‘class_alias()’) genauso. Muss noch mal schaun, ob das auch irgendwie für Funktionen funktioniert.

      Abschlussfrust: Wieso gibt es keinen Autoloader für Funktionen oder Namensräume?!

    RSS Feed für Kommentare zu diesem Artikel. TrackBack URL

    Hinterlasse einen Kommentar

    Werbung
    PHP Magazin
    Ausgabe 02/2010

    Dieses Mal mit Artikeln zu den Themen OpenSocial und Apache Shindig, Graphentheorie, Smarty3

    t3n
    Ausgabe 19

    Social Media (R)evolution. Weitere Themen sind noSQL, Crowdsourcing ...

    PHP Journal
    Ausgabe 2/2010

    PHP & Windows optimal nutzen, die besten PHP-CMS im Überblick, Google-API mit Zend Framework nutzen.

    Wir wurden schon öfters gefragt, ob man uns nicht irgendwie unterstützen kann. Die Antwort war immer einfach: Klar! Am einfachsten ist es eure nächsten Einkäufe bei Amazon über unsere Link abzuwickeln. Damit würdet ihr uns schon sehr helfen. Über Co-Autoren freuen wir uns aber noch mehr.