tutorials.de Buch-Aktion 05/2012
  • [PHP] High Quality PHP-Code – Teil 1 Code-Style

    Hi, ich habe schon einiges an PHP-Code gesehen (und auch selber geschrieben) und vieles davon ist alles andere als schön. Ich möchte euch in diesem Tutorial zeigen, wie man die Code-Qualität steigern und damit anderen den Support, das Debugging, die Weiterentwicklung, etc. erleichtern kann. Und so ganz nebenbei, die PHP-Profis kochen auch nur mit Wasser .

    Das Wichtigste am Code ist ein einheitlicher Stil.
    Dazu zählen folgende Aspekte:
    • Maximale Zeilenlänge
    • Art der Zeilenumbrüche (Windows oder UNIX/Linux)
    • Zeichen für die Einrückung (Tabs oder Spaces)
    • Wenn Spaces zur Einrückung genutzt werden, die Anzahl pro Schritt
    • Konventionen für Operatoren
    • Konventionen für die Variablennamen
    • Konventionen für die Funktions- und Methodennamen
    • Konventionen für Kontrollstrukturen (if und switch)
    • Konventionen für Schleifen (for, foreach, while, do)
    • Konventionen für Klassen- und Methodenrümpfe (Position der geschweiften Klammer)
    Das hört sich nach viel viel trockenem und unnützem Zeugs an. Ihr werdet recht schnell feststellen, dass das Einhalten von Code-Styles recht einfach ist und Vorteile bringt.

    1. Zeilenlänge, Zeilenumbrüche und Einrückung

    Ihr solltet euch an eine maximale Zeilenlänge halten und diese in keinem Fall überschreiten. Damit kann man unnützes horizontales Scrollen in der IDE verhindern. Früher war diese Grenze bei 80 Zeichen pro Zeile, Mittlerweile sind 120 Zeichen üblich.
    Die anderen beiden Dinge sind für die Darstellung in Editoren bzw. IDEs wichtig. Da die meisten PHP-Skripte unter einen unixoiden Betriebssystem laufen werden, empfiehlt es sich immer UNIX/Linux Zeilenumbrüche zu benutzen (auch wenn Notepad damit nicht umgehen kann).
    Werden für die Einrückungen Tabs benutzt, so kann sich der Code optischen von IDE zu IDE unterscheiden. Je nachdem wie die Schrittweite für Tabs eingestellt ist. Aus diesem Grunde sollte man hier Spaces verwenden, Dabei sollte eine Einrückungsstufe vier Leerzeichen entsprechen.


    2. Operatoren

    Es gibt mehrere Möglichkeiten um Operatoren von Operanden zu trennen.
    Variante eins: Platzsparen. Kann man machen sieht aber nicht gut aus.
    Code php:
    1
    2
    
    $my_var = $a.$h."foo".$m."j".$x.$i."bar".$z;
    $line_count = $z1+$z2/6*13-$xv29+pow(38,2);
    Wer schafft es diese zwei Zeilen innerhalb von 30 Sekunden zu verstehen? Ich jedenfalls nicht.

    Um das ganze besser lesbar zu gestalten, trennen wir die Operatoren mit Leerzeichen.
    Code php:
    1
    2
    
    $my_var = $a . $h . "foo" . $m . "j" . $x . $i . "bar" . $z;
    $line_count = $z1 + $z2 / 6 * 13 - $xv29 + pow(38, 2);
    Zumindest ist Zeile zwei besser Verständlich.


    3. Konventionen für Variablen-, Funktions- und Methodennamen

    Die Namen von Variablen, Funktionen und Methoden sollten auch einheitlich "gestaltet" werden. Mit zunehmender Erfahrung hat sich herausgestellt, dass Camel-Case am verständlichsten ist. Des Weiteren sollten sie in Englisch geschrieben sein.

    Achtet im folgenden Beispiel, mal darauf,welchen Code ihr schneller erfasst habt.

    Code php:
    1
    2
    3
    
    function generate_my_code($paramter_one) {
        echo "foobar".$my_var;
    }

    Code php:
    1
    2
    3
    
    function echoFooBar($firstParameter) {
        echo "baz" . $firstParameter;
    }
    Ich habe bewusst unterschiedliche Beispiele genommen, nur die Grundstruktur ist bei beiden gleich.
    Beispiel 1: Namen mit Unterstrichen
    Beispiel 2: Namen in Camel-Case


    4. Kontrollstrukturen und Schleifen

    Auch bei den ganzen if's, for's gibt es Stilregeln. Diese Regeln bestimmen die Position der Bedingungen und der geschweiften Klammern. Von der if...endif; Syntax rate ich ab, da man dort den Block nur schwer erkennt. Analog gilt gleiches für for und foreach.
    Auch hier kann man den Code wieder platzsparend gestalten, aber das ist aus meiner Sicht unübersichtlich.

    Code php:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    if($a==$b){
    }
    switch($x){
    case "z":
    doSomething();
    break;
    default:
    DoSomethingElse();
    }
    Fügen wir hier einfach mal ein Paar Leerzeichen ein:
    Code php:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    if ($a == $b) {
    }
    switch ($x) {
        case "z":
            doSomething();
            break;
        default:
            DoSomethingElse();
    }


    5. Konventionen für Klassen- und Methodenrümpfe

    Und auch hier sind die Positionen der (geschweiften) Klammern und Leerzeichen bei Parametern interssant.

    Hier will ich nur zwei Beispiele zeigen, da ich mich sonst zu oft wiederhole.
    Code php:
    1
    2
    3
    
    function myFunction($firstParam,$secondParam){
        // some code
    }

    Code php:
    1
    2
    3
    4
    
    function myFunction($firstParam, $secondParam)
    {
        // some code
    }

    Bevor ich zum Schlusswort komme nochmal ein komplettes Beispiel:
    Platzsparend
    Code php:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    <?php
    class MyObject{
    private $array;
    private $string;
    public function __contruct($firstParam,$secondParam=null){
    if(is_array($firstParam)){
    $this->array=$array;
    }
     
    if($secondParam!==null && is_string($secondParam)){
    $this->string=(string)$secondParam;
    }
    }
    }

    Und das ganze mit einheitlichem Code-Stil:
    Code php:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
    class MyObject
    {
        private $array;
        
        private $string;
        
        public function __contruct($firstParam, $secondParam=null)
        {
            if (is_array($firstParam)) {
                $this->array=$array;
            }
     
            if ($secondParam!==null && is_string($secondParam)) {
                $this->string=(string)$secondParam;
            }
        }
    }

    Einige denken jetzt sicher "ach der Code ist nur für mich, da brauche ich so etwas nicht". Das dachte ich auch einmal, aber im Laufe der Zeit wurde die Pflege des Codes immer schwieriger. Und auch bei einem Hilferuf (z.B. hier im Forum) ist es für die Helfenden leichter das Problem zu lösen, wenn sie sauberen Code zu sehen bekommen.

    Das ganze würde nur wenig bringen, wenn es dafür nicht Unterstützung durch Tools gäbe.
    Das Tool PHP_CodeSniffer führt eine statische Code-Analyse durch und sagt euch, wo ihr gegen den Code-Stil verstoßen habt. Persönlich nutze ich eine modifizierte Version des Zend Conding Standards.

    Das war es zu Teil 1 meiner Serie. Im zweiten Teil wird es um objektorientierte Programmierung (OOP) und Unit-Tests gehen.


    Gruß Kyoya Stefan

    PHP-Developer bei der Mayflower GmbH


    Kommentare 15 Kommentare
    1. Avatar von Bratkartoffel
      Bratkartoffel -
      Hi,

      Danke für diese Einführung, die dürfte vorallem für Neulinge recht interessant sein.

      Ein Thema, das du anschneidest, wurde bei uns im Team schonmal größer diskutiert:
      Werden für die Einrückungen Tabs benutzt, so kann sich der Code optischen von IDE zu IDE unterscheiden. Je nachdem wie die Schrittweite für Tabs eingestellt ist. Aus diesem Grunde sollte man hier Spaces verwenden, Dabei sollte eine Einrückungsstufe vier Leerzeichen entsprechen.
      Einheitlicher wird es sicherlich, wenn man anstatt der Tabs mit Leerzeichen arbeitet. MEiner Meinung nach ist es aber gerade ein Vorteil von Tabs, dass sich jeder selbst die Schrittweite einstellen kann, ohne dass man den Source verändern muss. Ich arbeite zu Hause auf einen relativ kleinen Monitor, hier habe ich eine Schrittweite von 2. In der Arbeit habe ich nen größeren Widescreen-Monitor, hier hab ich die Schrittweite 6.

      Grundsätzlich finde ich, dass dieser Punkt größtenteils Ansichtssache ist. Wichtig ist nur, wenn man sich für eine Art entschieden hat, dann sollte man diese auch im kompletten Projekt durchziehen. Ansonsten wird das ganze ziemlich unübersichtlich, wenn die Zeilen teils mit 2 Leerzeichen eingerückt und teils mit einem Tab und Schrittweite 6 angezeigt werden...

      Habe übrigens auch noch einen Link zu verschiedenen Konventionen gefunden, die man beim Programmieren befolgen kann. Ich persönlich bevorzuge den K&R Stil, arbeite auch viel mit C.

      Grüße,
      BK
    1. Avatar von cheesi
      cheesi -
      Hier auch noch ein Tip (vor allem in der kommerziellen Programmierung):
      Variablen IMMER klein schreiben
      Konstanten IMMER groß schreiben

      Eine ganz einfach Regel, die den Lesefluss um einiges steigert
    1. Avatar von Kyôya
      Kyôya -
      Zitat Zitat von cheesi Beitrag anzeigen
      Variablen IMMER klein schreiben
      Konstanten IMMER groß schreiben
      Variablen immer klein? Du meinst mit Sicherheit nur den ersten Buchstaben, danach gehst in CamelCase weiter. Zumindest, wenn man Code für kommerzielle bzw. OSS Projekte erstellt.
      Bei Konstanten gebe ich dir recht. Man globale Konstanten meiden (PHP-Funktion define), da sie die Testbarkeit des Codes negativ beeinflussen. Aber dazu gibts im nächsten Teil mehr
    1. Avatar von Sebastian Schmidt
      Sebastian Schmidt -
      Vieles kann einem Netbeans mit der Tastenkombo Alt+Shift+F abnehmen ich benutze das schon seid Jahren. Als Klassenvariablen kann man auch $mVarname nehmen und als Übergabevariablen $aVarname, so wird immer klar wo man was und welche Variable her hat

      Aber sonst netter Text, vielen Dank

      P.S. Ich finde { in der gleichen Zeile besser weniger Code, weniger scrollen, in der Datei insgesamt.
    1. Avatar von bn
      bn -
      Schlecht lesbar sind im Übrigen auch "Buckelwüsten" ala
      PHP-Code:
      $vorname "Max";
      $nachname "Mustermann";
      $strasse "Musterstraße";
      $hausnr "10";
      $plz "01234";
      $ort "Musterstadt";
      $sprache "deutsch"
      besser lesbar:
      PHP-Code:
      $vorname  "Max";
      $nachname "Mustermann";
      $strasse  "Musterstraße";
      $hausnr   "10";
      $plz      "01234";
      $ort      "Musterstadt";
      $sprache  "deutsch"
      Ob Variablen nun englisch benannt sein müssen, darüber lässt sich streiten. Letztlich sind wir hier in Deutschland und sofern es sich nicht gerade um eine Open Source Software handelt, ist Deutsch für die meisten die einfachere Sprache (weil Muttersprache). Wichtig ist auf jeden Fall Konsistenz. Englische und deutsche Variablennamen vermischt sind zu vermeiden.

      Grüße BN
    1. Avatar von cheesi
      cheesi -
      Zitat Zitat von Kyôya Beitrag anzeigen
      Variablen immer klein? Du meinst mit Sicherheit nur den ersten Buchstaben, danach gehst in CamelCase weiter. Zumindest, wenn man Code für kommerzielle bzw. OSS Projekte erstellt.
      Bei Konstanten gebe ich dir recht. Man globale Konstanten meiden (PHP-Funktion define), da sie die Testbarkeit des Codes negativ beeinflussen. Aber dazu gibts im nächsten Teil mehr
      Jap genau Richtig gedacht falsch ausgedrückt
    1. Avatar von _Grubi
      _Grubi -
      Hey,

      durchaus nützlich, so eine kurze Einführung, allerdings hätte ich 2 Dinge beim einheitlichen Code-Beispiel zu bemeckern
      1. wenn du von einheitlichen geschreiften Klammer sprichst, dann sollten die öffnenden Klammern eine Zeile hoch rutschen (class, function) oder eins runter (if).
      2. bei Operatoren/Operanden hast du noch gesagt, dass es mit Leerzeichen gleich besser wird, aber das hast du in dem Beispiel wieder außer Acht gelassen (=, !==). Ich bin der Meinung, dass die Leerzeichen her sollten. Manche sind auch der Meinung, dass bei einem Cast nach der schließenden Klammer ein Leerzeichen sollte. In Java ist das Konvention, in PHP keine Ahnung.

      Aber ansonsten schöne Übersicht.
    1. Avatar von MArc
      MArc -
      Gute Arbeit und sicherlich nuetzlich fuer wahre blutige Anfaenger, aaaber:
      Ich weiss ehrlich gesagt nicht, was das ganze mit 'High Quality PHP-Code' zu tun haben soll.
      Du gibst ja schliesslich nur Tipps, um von einem Code voller Anfaengerfehler (Deine Beispiele: Keine Einrueckungen usw.) einen Code zu machen, der *ueberhaupt* lesbar ist. Auch ist das nur eine Konvention von vielen, die in PHP genutzt werden kann. Du solltest daher gleich zu Begin dazuschreiben, dass deine Tipps Regeln aus einer Konvention ist, die entweder so unter einem Titel standardisiert oder aus Deinen persoenlichen Vorlieben entstanden sind; nicht, dass der Leser noch denkt, dass dies ungeschriebene goldene Regeln sind.
    1. Avatar von enne
      enne -
      Hi,

      ich hätte auch ein oder zwei Anmerkungen.
      Ist es Absicht, dass im ersten Code-Beispiel im dritten Abschnitt eine Variable benutzt wird die es in der Funktion gar nicht gibt?

      Achja im Abschnitt 2.. da steh ich jetzt wohl grad aufm Schlauch... Wie rechne ich den
      Code :
      1
      
      $z2 / 6 * 13
      1. z2 druch das Produkt von 6 mal 13 oder
      2. z2 druch 6 mal 13?

      Ich meine mich daran zu erinnern, dass die Multiplikation zuerst ausgeführt wird... aber sicher bin ich mir gerade nicht...

      @_Grubi
      Ich finde es gar nicht so schlimm Klassen und Funktionen/Methoden von Kontrollstrukturen abzuheben, dadurch dass man die öffnende geschweifte Klammer nicht in die selbe Zeile schreibt.
    1. Avatar von Kyôya
      Kyôya -
      Zitat Zitat von _Grubi Beitrag anzeigen
      1. wenn du von einheitlichen geschreiften Klammer sprichst, dann sollten die öffnenden Klammern eine Zeile hoch rutschen (class, function) oder eins runter (if).
      2. bei Operatoren/Operanden hast du noch gesagt, dass es mit Leerzeichen gleich besser wird, aber das hast du in dem Beispiel wieder außer Acht gelassen (=, !==). Ich bin der Meinung, dass die Leerzeichen her sollten. Manche sind auch der Meinung, dass bei einem Cast nach der schließenden Klammer ein Leerzeichen sollte. In Java ist das Konvention, in PHP keine Ahnung.
      Ok bei Punkt zwei gebe ich dir recht, da hab ich beim Schreiben ein wenig geschlampt. Danke für den Hinweis

      Zitat Zitat von MArc Beitrag anzeigen
      Ich weiss ehrlich gesagt nicht, was das ganze mit 'High Quality PHP-Code' zu tun haben soll.
      Das ist der Grundstein für guten PHP-Code. Weitere Spielerein kommen noch.

      Hätte nicht gedacht, dass der Beitrag so gut ankommt.

      Gruß Kyoya Stefan
    1. Avatar von Maniac
      Maniac -
      Da gebe ich Kyoya auch recht, ich versuche mich in meinen Projekten auch an diese Konvention zu halten.
      Jedoch mache ich noch folgendes um immer zu wissen welchen Datentyp die Variable enthält:

      PHP-Code:
      // für ein Array
      $aMyArray = array();

      // für ein Object
      $oMyObject = new Class();

      // für einen String
      $sMyString 'Ich bin ein String';

      // für einen boolean
      $bMyBool false;

      // für gemischten Datentyp
      $mMyMixed = array|string|object 
      Und natürlich sollte man auch seinen Code richtig kommentieren, da
      1. die Lesbarkeit erhöht wird und man den Code schnell interpretieren kann
      2. andere sich schneller einarbeiten können - man selbst noch weiß was man vor einiger zeit programmiert hat.

      Damit auch IDE's und PHP-Docs die Kommentare richtig lesen können und auch dementsprechend die Codevervollständigung funktioniert sollte man auch eine einheitliche Schreibweise an den Tag legen.
    1. Avatar von eifel
      eifel -
      Danke für das Thema "Code Style", ich halte es für wichtig, selbst wenn man "nur" für sich programmiert. Hat man den Code ein paar Monate nicht angepackt und wenig dokumentiert/kommentiert, versteht man ihn manchmal selbst nicht mehr.

      Es macht auch mehr Freude "schönen" Code zu schreiben, also wenn er schon rein optisch anspricht, übersichtlich ist usw. Je konsequenter ein Stil durchgehalten wird, umso größer ist die Lesbarkeit.

      Gibt es Editoren, die uns bei der Einhaltung eines Stils besonders unterstützen ?
    1. Avatar von einfach nur crack
      einfach nur crack -
      Ich glaube kaum, dass man Namen in Camel-Case besser lesen kann als mit Unterstrichen. Leider ist das ein ästhetisches Problem, was mich in PHP immer wieder ärgert, da PHP von Haus aus keine schöne Konvention hat, da Funktionen mit Unterstrichen geschrieben werden, Methoden hingegen in Camel-Case. Außerdem sieht eine Kombination aus –> oder :: mit einem Namen, der Unterstriche verwendet, immer etwas eigenartig aus, obwohl ich diese Form bevorzuge.
      Wenn man sich mal Sprachen wie Ruby oder Python ansieht, dann wirkt PHP etwas unvollkommen und undurchdacht (was es wohl auch ist).

      Nachtrag: Meine Skripte sehen so aus:
      Code PHP:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      
      class DoSomethingObject
      {
        #
        # @param   (object) $block: Closure
        # @return  (array):
        #
        public function get_something_from_database(Closure $block)
        {
          return $block($this);
        }
      }
       
      $new_object = new DoSomethingObject();
      $new_object->get_something_from_database(function ($object)
      {
        # some code ...
      });
       
      # if-then-else
      if($a === $b)
      {
        # ...
      }
      else
      {
        # ...
      }
       
      # switch-case
      switch($a)
      {
        case 1:
          break;
        
        case 2:
          break;
      }
       
      # foreach
      foreach($b as $c => $d)
      {
        # ...
      }
       
      # while
      while($e)
      {
        # ...
      }
    1. Avatar von timestamp
      timestamp -
      Zitat Zitat von enne Beitrag anzeigen
      Code :
      1
      
      $z2 / 6 * 13
      1. z2 druch das Produkt von 6 mal 13 oder
      2. z2 druch 6 mal 13?
      1
      Wie in der Mathematik üblich, bei gleicher Rangfolge von links nach rechts. Also $z2 geteilt durch 6 und das dann mal 13. Ansonsten müssen Klammern her:

      Code :
      1
      
      $z2 / (6*13)
    1. Avatar von andreano
      andreano -
      Hallo,
      erst mal Danke ! Ich bin zwar ein Anfänger, aber ich versuche seit anfang an einen "sauberen code" zu schreiben.

      to Kyôya,
      einige deiner Beispiele habe ich mir schon seit Anfang an angewöhnt, die anderen folgen noch.

      to bn, Maniac, einfach nur crack, thombe, Yaslaw
      für eure Beispiele und Hilfe kann ich mich nur von ganzen Herzen Bedanken!

      Gruß Aleks
    Kommentare Kommentar schreiben

    Klicke hier, um dich anzumelden

    Welche Farbe hat eine reife Zitrone?