>> Inhaltsverzeichnis >> Anleitung für Entwickler

Coding Principles

Allgemeines

Mit "Coding principles" sind grundsätzliche Regeln zum Schreiben und Formatieren von PHP-Code gemeint. Diese einheitlichen Regeln sollen helfen, Quellcode lesbar und übersichtlich zu erzeugen.

Wenn mehrere Autoren den gleichen Quellcode bearbeiten, ist es häufig so, dass jeder dieser Autoren eine andere Auffassung davon hat, wie sauberer Code aussehen sollte. Es gibt dutzende Möglichkeiten den gleichen Sachverhalt mit PHP auf verschiedene Arten auszudrücken. Damit der Quellcode trotzdem auf lange Sicht gut lesbar bleibt, ist es erforderlich, sich vorab mit allen Autoren auf einen gemeinsamen Standard zu einigen, wie Anweisungen aufgeschrieben werden sollten.

Die hier vorliegenden "Coding principles" liefern genau eine solche Festlegung. Diese Regeln sind zwar nicht verpflichtend, aber ich möchte sie Ihnen dennoch wärmstens empfehlen.

Einrückung und Kommentare

Der Quellcode sollte mit 4 Leerzeichen eingerückt werden. Verwenden Sie keine Tabulatoren, denn diese können auf unterschiedlichen System unterschiedlich dargestellt werden.

Als Kommentare sollten Sie ausschließlich die Schreibweise /* kommentar */ verwenden. Dies hat einen tieferen Sinn! Wenn Sie später einmal Skripte schreiben oder einsetzen wollen, welche Ihren Quellcode analysieren oder dokumentieren sollen, dann erleichtert Ihnen diese Schreibweise deutlich die Arbeit. Anders als die Schreibweisen // kommentar oder # kommentar, haben Sie hier einen festen Anfang und ein festes Ende. Kommentarzeilen sind somit mit einfachen regulären Ausdrücken deutlich leichter zu finden und Sie sparen sich immensen Aufwand beim Erzeugen dieser Skripte.

Im Folgenden ein Beispiel:

<?php 
$output = array();
/* iterate through input */
foreach ($input as $key => $element)
{
    $element strip_tags( (string) $element);
    if (preg_match("/\//"$key)) {
        $key preg_replace("/\//""."$key);
        Hashtable::set($output$key$element);
    } else {
        $output[$key] = $element;
    }
} /* end foreach */
?>

Deklaration und Gültigkeit von Variablen

In PHP existiert keine Variablendeklaration im Sinne anderer Sprache. Trotzdem haben Variablen eine gewisse Lebensdauer. Vor oder nach dieser Lebensdauer sollte die Variable nicht existieren, da heißt, ihr sollte kein Wert zugewiesen sein.

Viele typische Fehler in PHP rühren daher, dass Programmierer annehmen, eine Variable sei unbenutzt, von einem bestimmten Typ, oder würde an nach einer bestimmten Code-Zeile nicht mehr verwendet. PHP selbst stellt dies jedoch NICHT sicher und warnt Sie auch nicht, falls Sie sich irren sollten, es sei denn, Sie "bitten" explizit darum. Genau das sollten Sie unbedingt tun!

Wenn Sie sich daran halten, wird PHP Sie warnen, wenn Sie eine Variable außerhalb Ihrer Lebensdauer verwenden und Ihnen so möglicherweise viele Stunden aufwendigen Debuggings ersparen!

Variablen sollten in CamelCase benannt werden - also $debugSourcePath anstatt $debug_source_path. Der erste Buchstabe wird dabei stets klein geschrieben - im Gegensatz zu Klassennamen. Dort (und nur dort) sollte der erste Buchstabe groß geschrieben werden. Diese Festlegung der Schreibweise ist analog zu dem was in vielen anderen Sprachen, wie Java üblich ist.

<?php 
/* Beginn der Lebensdauer */
/* Die folgende Zeile warnt Sie, falls die Variable bereits existiert */
assert('!isset($variable); // Cannot redeclare $variable');

/* Variablen immer vor Benutzung initialisieren */
$variable 0;

/* ... weitere Anweisungen ... */

/* Wird die Variable nicht mehr benötigt, sollte sie explizit gelöscht werden */
unset($variable);
/* Ende der Lebensdauer */
?>

If und Else

Bei Verzweigungen schreiben Sie bitte immer die Klammern { } um jeden Block. PHP erlaubt zwar, auf diese Klammern zu verzichten wenn der Block nur eine einzelne Anweisung enthält, dies ist jedoch fehleranfällig, weil es häufig vorkommt, dass später eine zweite Zeile hinzugefügt wird und die nicht vorhandenen Klammern dann leicht "übersehen" werden.

Falls eine Verzweigung sehr lang ist (mindestens 10 Zeilen), dann sollten Sie zur besseren Lesbarkeit nach der schließenden Klammer den Kommentar /* end if */  ergänzen. Dies hilft bei längeren Codes zu identifizieren, zu welcher Anweisung eine Klammer gehört.

<?php 
if ($test1) {
    /* ... */
} elseif ($test2) {
    /* ... */
} else {
    /* ... */
/* end if */
?>

Switch

Beachten Sie für die Switch-Anweisung die Einrückung und die Zeilenumbrüche, diese dienen der Lesbarkeit.

Vermeiden Sie das Verwenden von "fall trough", da dies zu einem schwer lesbaren Code führen kann. Falls es sich nicht vermeiden lässt, dann sollten Sie diesen Sonderfall unbedingt mit dem Kommentar /* fall through */ anstatt der sonst üblichen break-Anweisung dokumentieren.

Der Default-Fall sollte stets vorhanden sein. Dies dient der Klarheit des Codes.

Falls zwei Fälle den gleichen Code enthalten, kann dies ausgedrückt werden durch die Schreibweise case 1: case 2: ... break;. Dies ist eine sinnvolle Abkürzung und Sie sollten davon Gebrauch machen, wenn es sich anbietet.

<?php 
switch ($variable)
{
    case 1:
        /* ... */
    break;
    case 2: case 3:
        /* ... */
    break;
    case 4:
        /* ... */
    break;
    case 5:
        /* ... */
    break;
    case 6:
        /* ... */
    /* fall through */
    default:
        /* ... */
    break;
} /* end switch */
?>

For, Foreach und While

Achten Sie hier wiederum auf die Zeilenumbrüche, diese dienen der Lesbarkeit.

PHP hat ein eher ungewöhnliches "Feature". Die Lebensdauer von Schleifenvariablen endet NICHT wie bei anderen Sprachen üblich mit dem Verlassen der Schleife, sondern die Variable besteht weiterhin mit dem ihr zugewiesenen Wert. Das heißt außerdem, dass Schleifenvariablen in PHP, anders als in anderen Sprachen, den Wert einer anderen, bereits existierenden Variablen überschreiben können. PHP zeigt Ihnen dazu keinerlei Warnung. Um dieses Verhalten und das potentielle Risiko, welches damit verbunden ist, zu vermeiden, sollten Sie den Beginn einer For- oder Foreach-Schleife wie eine Variablendeklaration behandeln und prüfen, ob diese bereits existieren. Bei Verlassen einer Schleife sollten Sie die Schleifenvariablen explizit löschen, um Seiteneffekte zu vermeiden.

Achten Sie darauf, dass Foreach zwingend ein Array erwartet. Prüfen Sie gegebenenfalls vor Eintritt in die Schleife mit der Funktion is_array() ob die Variable den erwarteten Typ hat und verzweigen Sie andernfalls in eine geeignete Fehlerbehandlung.

Bei While-Schleifen, achten Sie darauf, Ausstiegspunkte, welche Sie mit break- oder continue-Anweisungen einfügen, stets ausreichend zu dokumentieren.

Im Folgenden finden Sie drei Beispiele:

<?php 
/* Beispiel: FOR-Schleife */
assert('!isset($i); // Cannot redeclare $i');
for ($i 0$i sizeOf($input); $i++)
{
    /* ... */
/* end for */
unset($i);

/* Beispiel: FOREACH-Schleife */
assert('!isset($key); // Cannot redeclare $key');
assert('!isset($element); // Cannot redeclare $element');
foreach ($input as $key => $element)
{
    /* ... */
/* end foreach */
unset($key);
unset($element);

/* Beispiel: WHILE-Schleife */
while ($test)
{
    /* ... */
/* end while */
?>

Klassen und Funktionen

Für die Namen von Klassen und Funktionen sollte einheitlich CamelCase verwendet werden. Dabei wird bei Funktionen der erste Buchstabe immer klein geschrieben. Bei Klassen wird der erste Buchstabe immer groß geschrieben. Diese Regel gilt analog zu Java und anderen wichtigen Sprachen.

In PHP ist es üblich, dass die Namen von privaten Funktionen und Methoden mit einem Unterstrich beginnen um den Quellcode lesbarer zu gestalten. Falls Sie diese Schreibweise benutzen möchten, verwenden Sie diese ausschließlich zur Kennzeichnung von privaten Funktionen und Methoden.

Um die Lesbarkeit zu verbessern ist es empfehlenswert, den Namen einer Funktion wenn möglich aus einem Verb im Imperativ und einem Substantiv im Singular zusammenzusetzen, zum Beispiel: "getBeer()" oder "setContent()". Ist der Rückgabewert ein Listenobjekt oder ein Array, so verwenden Sie ein Substantiv im Plural, zum Beispiel: "getLines()".

Zur Dokumentation von Klassen und Funktionen sollten PHP-Doc Kommentare (http://www.phpdoc.org/) verwendet werden. Diese sollten stets Pflicht sein. Lassen Sie es sich zur Gewohnheit werden jede neue Funktion, welche Sie schreiben stets sofort zu dokumentieren, solange Ihnen alle Details noch frisch im Gedächtnis sind. Beim Schreiben der Dokumentation werden Sie gezwungen, Ihre Arbeit inhaltlich Revue passieren zu lassen und erkennen dadurch früher gedankliche Fehler, Irrtümer oder fehlerhafte Voraussetzungen.

Die Dokumentation einer Funktion sollte stets enthalten: welche Eingabedaten die Funktion erwartet (zum Beispiel: "eine ganze Zahl zwischen 0 und 5"), welchen Zweck die Funktion hat - also, was diese tut. Außerdem welche Rückgabewerte die Funktion hat (zum Beispiel: "ein ganze Zahl zwischen 1 und 6, oder false, falls ein Fehler auftritt").

Es ist allgemein üblich, Quellcodes in englischer Sprache zu dokumentieren. Sofern Sie des Englischen mächtig sind, sollten sich daran halten.

Wenn Sie UML-typische Stereotype verwenden möchten, so stellen Sie diese dem Namen der Funktion oder Klassen voran und verwenden Sie die für Stereotype üblichen Klammern.

Es ist üblich, dass Variablen stets "private" sind und der Zugriff darauf stets über die Set- und Get-Funktionen erfolgt. Zum Beispiel würde der Zugriff auf eine private Variable "$foo" über die Funktionen mit den Namen "setFoo()" und "getFoo()" erfolgen. Beachten Sie, dass Klassenvariablen stets initialisiert werden müssen - notfalls initialisieren Sie diese mit der Konstanten "null".

<?php 
/**
 * «Stereotype» name
 *
 * The purpose of this class is ...
 *
 * @access      public
 * @package     package
 * @subpackage  subpackage
 */
class MyClass extends BaseClass
{

    /**#@+
     * @access  private
     */

    /** @var array */  private $var1 = array();
    /** @var int   */  private $var2 0;
    /** @var View  */  private $var3 null;
    /** @var array */  private $var4 = array();
    /** @var array */  private $var5 = array();

    /**#@-*/
    
    /**
     * «Stereotyp» Constructor
     *
     * This function accepts the following input ...
     *
     * This function does ...
     *
     * It returns the following values ...
     *
     * @param  string  $filename  path to file.ext
     */
    public function __construct ($filename)
    {
        /* ... */
    }

    /**
     * «Stereotype» name
     *
     * This function accepts the following input ...
     *
     * This function does ...
     *
     * It returns the following values ...
     *
     * @access  public
     * @param   string  $id  alpha-numeric, unique identifier
     * @return  int
     */
    public function getVar ($filename)
    {
        /* ... */
    }

}
?>

Autor: Thomas Meyer, www.yanaframework.net