Versionen von Entwickler.CodingStyle

Unwichtige Korrekturen ausblenden - Änderungen im Wiki Quelltext

 
 
01.04.2011 23:21 Uhr von tthelen -
Zeilen 1-2 hinzugefügt:

(:redirect 'http://docs.studip.de/develop/Entwickler/CodingStyle':)

 
 
15.07.2010 14:33 Uhr von mlunzena -
Zeile 11 gelöscht:
Zeile 16 hinzugefügt:
Zeilen 18-19 hinzugefügt:

Dieser Absatz ist nicht-normativ.

 
 
15.07.2010 13:37 Uhr von mriehe -
Zeilen 16-34 hinzugefügt:

Pagelevel-Doc-Block für copy&paste

(:source lang=php:)
/**
 * filename - Short description for file
 *
 * Long description for file (if any)...
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * @author      name <email>
 * @license     http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
 * @category    Stud.IP
 */
 
 
26.04.2010 22:42 Uhr von mlunzena - Das ist nicht korrekt. Zum Zeitpunkt der Abstimmung gab es dieses Beispiel noch nicht.
Zeilen 15-34 gelöscht:

Pagelevel-Doc-Block für copy&paste

(:source lang=php:)
/**
 * filename - Short description for file
 *
 * Long description for file (if any)...
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * @author      name <email>
 * @copyright   2010 Stud.IP Core-Group
 * @license     http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
 * @category    Stud.IP
 */
 
 
22.04.2010 17:59 Uhr von mriehe - das is der doc-block, so wie er in den abgestimmten code-konventionen steht. nicht löschen!
Zeilen 16-35 hinzugefügt:

Pagelevel-Doc-Block für copy&paste

(:source lang=php:)
/**
 * filename - Short description for file
 *
 * Long description for file (if any)...
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * @author      name <email>
 * @copyright   2010 Stud.IP Core-Group
 * @license     http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
 * @category    Stud.IP
 */
 
 
21.04.2010 10:10 Uhr von mlunzena - Page-level block entfernt. Copyright-Angabe kann so nicht gemacht werden.
Zeilen 15-34 gelöscht:

Pagelevel-Doc-Block für copy&paste

(:source lang=php:)
/**
 * filename - Short description for file
 *
 * Long description for file (if any)...
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * @author      name <email>
 * @copyright   2010 Stud.IP Core-Group
 * @license     http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
 * @category    Stud.IP
 */
 
 
31.03.2010 16:29 Uhr von mriehe -
Zeile 34 bearbeitet:
  • /
geändert in:
 */
 
 
27.03.2010 16:39 Uhr von mriehe -
Zeilen 1-4 bearbeitet:

Stud.IP Coding Standard

Geltungsbereich

geändert in:

Stud.IP Coding Standard

Geltungsbereich

Zeilen 13-15 bearbeitet:

Ziele

Coding Standards sind in jedem Softwareprojekt wichtig, insbesondere wenn viele Entwickler daran arbeiten. Coding Standards helfen sicherzustellen, dass der Code von hoher Qualität ist, weniger Fehler hat und einfach zu warten ist.

geändert in:

Ziele

Coding Standards sind in jedem Softwareprojekt wichtig, insbesondere wenn viele Entwickler daran arbeiten. Coding Standards helfen sicherzustellen, dass der Code von hoher Qualität ist, weniger Fehler hat und einfach zu warten ist.

Pagelevel-Doc-Block für copy&paste

(:source lang=php:)
/**
 * filename - Short description for file
 *
 * Long description for file (if any)...
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * @author      name <email>
 * @copyright   2010 Stud.IP Core-Group
 * @license     http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
 * @category    Stud.IP
*/
 
 
16.06.2009 08:30 Uhr von mlunzena -
Zeilen 1-34 bearbeitet:
geändert in:

Stud.IP Coding Standard

Geltungsbereich

Dieses Dokument bietet Richtlinien für die Formatierung von Code und Dokumentation für Entwickler, die an Stud.IP mitarbeiten. Die folgenden Bereiche werden vom Stud.IP Coding Standard abgedeckt:

Ziele

Coding Standards sind in jedem Softwareprojekt wichtig, insbesondere wenn viele Entwickler daran arbeiten. Coding Standards helfen sicherzustellen, dass der Code von hoher Qualität ist, weniger Fehler hat und einfach zu warten ist.

 
 
22.04.2009 09:06 Uhr von mlunzena -
Zeilen 30-31 bearbeitet:
geändert in:
 
 
05.05.2008 00:01 Uhr von chueser -
Zeilen 1-1203 bearbeitet:

Vorschlag für einen StudIP Coding Standard: PEAR Coding Standard

Diskussion über den PEAR Coding Standard

Einleitung
Zusammenfassung
Änderungswünsche & mehr

Inhaltsverzeichnis: PEAR Coding Standard

Einrückungen und Zeilenlänge
Kontrollstrukturen
Funktionsaufrufe
Klassen-Definition
Funktionsdefinitionen
Kommentare
Code einbinden
PHP-Code-Tags
Kopf-Kommentare
CVS-Nutzung
Beispiel-URLs
Namens-Konventionen
Dateiformate
E_STRICT-kompatibler Code
Richtlinen zur Fehlerbehandlung
Best practices
Beispieldatei inklusive Docblock-Kommentaren

Diskussion über den PEAR Coding Standard

Einleitung

Die Einhaltung eines Coding Standards ist ein wichtiger Bestandteil guter Projektarbeit. Gerade in Open Source Projekten mit vielen Entwicklern wird damit gewährleistet, dass Source Code eine hohe Qualität erhält/behält, weniger Bugs enthält, und einfacher zu warten ist.

Darüber hinaus gibt es jedoch auch andere wichtige Faktoren:

  • Kommunikation
  • funktionierender Code
  • übersichtlicher Code
  • Module und Modultests
  • Wiederverwendbarkeit des Codes
  • einfache Wartung des Codes
  • Code, der leicht zu erweitern ist
  • Unterstützung von Refactoring

um nur einige zu nennen. Ein Coding Standard unterstützt alle genannten Punkte. Neue Entwickler können sich schnell einarbeiten, denn wenn jeder den Code des anderen versteht, kann man auch schnell Bug-Fixes vornehmen oder Module des anderen verwenden ohne das Rad neu zu erfinden.

Um diese Ziele zu erreichen, muss eine PHP-Applikation:

  • leicht zu lesen sein
  • leicht verständlich sein
  • gut dokumentiert sein
  • durch verschiedene Programmierer wartbar
  • frei von typischen Fehlern

sein. Im besten Falle kann sogar der Anwender die Module der PHP-Applikation verstehen und weiter verwenden.

Das Ziel von leicht verständlichem Source-Code ist erreicht, wenn jedes Mitglied des Teams, jedes Modul aus dem Stehgreif erklären kann. Nicht zuletzt soll jede Arbeit am Projekt, dem Code und der Dokumentation Spaß machen. Je höher der Frustfaktor ist, je unübersichtlicher Strukturen und Code sind, desto höher ist die Wahrscheinlichkeit, das die Arbeit keinen Spaß mehr macht. Das gilt es auf jeden Fall zu verhindern.

Wenn sich ein Projekt an Coding Standards hält, dann sind einige gute Effekte zu beobachten:

  • Entwickler können in jeden Code hineienschauen und sofort heraus finden was dort vor sich geht.
  • Die Lebenszeit eines Softwareprojektes wird verlängert und überlebt die Lebenszeit der erfahrenen Entwickler.
  • Neue Leute können sich schnell einarbeiten.
  • PHP Einsteiger brauchen keinen persönlichen Style enwickeln und diesen bis zum bitteren Ende verteidigen.
  • PHP Einsteiger werden davor bewahrt die gleichen Fehler wieder und wieder zu machen.
  • In konsistenten Umgebungen werden weniger Fehler gemacht.

Ich freue mich auf eine früchtetragende Diskussion mit guten Ergebnissen hinsichtlich der Verwirklichung des StudIP Coding Standards.

PEAR Coding Standard
Note: Sehr zu empfehlen!

Zusammenfassung

(:table border=1 width=100% align=center cellspacing=0 :)

(:cellnr width=20% align=center bgcolor=#CCCCCC :) Feature (:cell width=50% align=center bgcolor=#CCCCCC :) Ausprägung (:cell width=30% align=center bgcolor=#CCCCCC :) Euer Kommentar (mit Namen bitte)

(:cellnr align=left bgcolor=#EEEEEE :) Einrückungen (:cell align=left bgcolor=#EEEEEE :)

  • 4 Leerzeichen, keine Tabulatoren

(:cell align=left bgcolor=#EEEEEE :)

  • find ich gut so (chueser)
  • find ich nicht gut so (ssuchi)
  • warum nicht? (chueser)

(:cellnr align=left bgcolor=#EEEEEE :) Zeilenlänge (:cell align=left bgcolor=#EEEEEE :)

  • ca. 75 - 85 Zeichen

(:cell align=left bgcolor=#EEEEEE :)

  • kollidiert schnell mit den Vorschriften zur Lokalisierung (ssuchi)
  • wieso gibt es diese vorschriften? (mlunzena)

(:cellnr align=left bgcolor=#EEEEEE :) Kontrollstrukturen (:cell align=left bgcolor=#EEEEEE :)

  • Leerzeichen zwischen den Schlüsselwörtern und der öffnenden Klammer
  • immer geschweifte Klammern verwenden
  • öffnende geschweifte Klammer in gleicher Zeile

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Funktionsaufrufe (:cell align=left bgcolor=#EEEEEE :)

  • kein Leerzeichen zwischen dem Funktionsnamen, der öffnenden Klammer und dem ersten Parameter

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Klassen-Definition (:cell align=left bgcolor=#EEEEEE :)

  • öffnende Klammer einer Klassen-Deklaration beginnt auf einer neuen Zeile

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Funktionsdefinitionen (:cell align=left bgcolor=#EEEEEE :)

  • öffnende Klammer einer Funktionsdefinition beginnt auf einer neuen Zeile
  • Argumente mit Standardwerten werden am Ende der Argumentenliste platziert
  • wenn möglich, immer einen aussagekräftigen Wert zurückliefern

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Kommentare (:cell align=left bgcolor=#EEEEEE :)

  • vollständige Inline-Dokumentation (Docblocks): File, Includes, Konstanten, Variablen, Methoden, Klasse
  • unbedingt (!) auch abseits der offziellen API-Dokumentation Kommentare im Quellcode einsetzen
  • Als Daumenregel gilt, wenn Sie auf einen Code-Abschnitt schauen und denken: „Wow, Ich würde nicht versuchen herauszufinden, wie es funktioniert“, sollten Sie auf jeden Fall einen Kommentar ergänzen, bevor Sie vergessen, wie es funktioniert.

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Code einbinden (:cell align=left bgcolor=#EEEEEE :) (:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) PHP-Code-Tags (:cell align=left bgcolor=#EEEEEE :)

  • immer die Langform <?php ?> benutzen

(:cell align=left bgcolor=#EEEEEE :)

  • während deiner Präsentation hatten wir schon angemerkt, dass das natürlich nicht für die Templates gilt.. (mlunzena)
  • sehe ich keinen Sinn drin, bisher wird fast immer die Kurzform benutzt (ssuchi)
  • funktioniert unabhängig vom Betriebssystem und PHP-Konfiguration (s.u.) (chueser)

(:cellnr align=left bgcolor=#EEEEEE :) Kopf-Kommentare (:cell align=left bgcolor=#EEEEEE :)

  • Alle Quellcode-Dateien sollen einen „Page-level“ Docblock am Datei-Anfang besitzen und einen „Class-level“ Docblock unmittelbar vor jeder Klasse.
  • Docblock = short decription + long description + tag list

(:cell align=left bgcolor=#EEEEEE :)

  • Finde ich sehr gut. Bitte auch einheitlich wie weiter unten beschrieben. Momentan ist „Page-level“ Docblock in vielen Dateien sehr unterschiedlich. (mriehe)

(:cellnr align=left bgcolor=#EEEEEE :) CVS-Nutzung (:cell align=left bgcolor=#EEEEEE :)

  • $Id$-CVS-Schlüsselwort in jede Datei.

(:cell align=left bgcolor=#EEEEEE :)

  • in diesem Fall ist wohl das SVN- Schlüsselwort gemient. (mriehe)

(:cellnr align=left bgcolor=#EEEEEE :) Beispiel-URLs (:cell align=left bgcolor=#EEEEEE :) (:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Namens-Konventionen (:cell align=left bgcolor=#EEEEEE :)

  • beschreibende Klassennamen und Abkürzungen vermeiden
  • Klassennamen beginnen immer mit einen Großbuchstaben
  • Klassenhierarchie spiegelt sich im Klassennamen wieder, jede Ebene der Hierarchie wird durch einen einzelnen Unterstrich getrennt
  • Funktionen und Methoden im „Camel Caps“
  • Funktionsnamen sollte der Package-Name vorangestellt werden
  • erster Buchstabe nach Prefix wird klein geschrieben, und jeder Buchstabe eines neuen „Wortes“ wird großgeschrieben
  • privaten Klassenelemente wird ein Unterstrich vorangestellt

(:cell align=left bgcolor=#EEEEEE :)

  • private Klassenelemente sollten keinen Unterstrich vorangestellt bekommen; das ist doch PHP5! (mlunzena)

(:cellnr align=left bgcolor=#EEEEEE :) Dateiformate (:cell align=left bgcolor=#EEEEEE :) (:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) E_STRICT-kompatibler Code (:cell align=left bgcolor=#EEEEEE :)

  • Der Code darf keine Fehler oder Warnungen erzeugen, wenn das Fehler-Reporting von PHP auf E_STRICT eingestellt ist.

(:cell align=left bgcolor=#EEEEEE :)

  • das dürfte kaum durchsetzbar sein.. (mlunzena)
  • vielleicht nicht für den alten code, aber auf jeden fall für alle neuen änderungen und plugins. würde das debuggen sehr vereinfachen… (mriehe)

(:cellnr align=left bgcolor=#EEEEEE :) Richtlinen zur Fehlerbehandlung (:cell align=left bgcolor=#EEEEEE :) (:cell align=left bgcolor=#EEEEEE :)

(:tableend:)

Änderungswünsche & mehr

(:table border=1 width=100% align=center cellspacing=0 :)

(:cellnr width=20% align=center bgcolor=#CCCCCC :) Feature (Name) (:cell width=50% align=center bgcolor=#CCCCCC :) Ausprägung (:cell width=30% align=center bgcolor=#CCCCCC :) Euer Kommentar (Namen)

(:cellnr align=left bgcolor=#EEEEEE :) Namenskonvention für Accessor-Methoden (chueser) (:cell align=left bgcolor=#EEEEEE :)

  • getter Methoden: get+Variablenname
  • setter Methoden: set+Variablenname
  • erster Buchstabe des Variablennamens groß schreiben

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Anzahl Klassen in einem File (chueser) (:cell align=left bgcolor=#EEEEEE :)

  • nur eine Klasse pro File (wegen Eindeutigkeit der Packages)

(:cell align=left bgcolor=#EEEEEE :)

  • Da seh ich nicht den Sinn, in Java ok, aber das ist PHP, warum sollte man das machen? Es gibt doch gar keine "import" Anweisung? (mlunzena)
  • Ich finde das sehr sinnvoll, so findet man dann auch leichter, wo die Klassen sind. (tgloeggl)
  • Ich stimme da tgloeggl vollkommen zu. (mriehe)

(:cellnr align=left bgcolor=#EEEEEE :) File-Name bei Files die eine Klasse enthalten (chueser) (:cell align=left bgcolor=#EEEEEE :)

  • Name des Files gleich dem Klassen-Namen

(:cell align=left bgcolor=#EEEEEE :)

  • In PHP gibt's doch aber auch Dateien, die keine Klassen enthalten.. Wie sollte das denn funktionieren? Grundsätzlich macht es keinen Sinn, einfach nur alles so zu machen wie in Java. Java ist nicht unbedingt immer ein Vorbild. Ansonsten sollte man eben Java nehmen. (mlunzena)
  • Hä? Alles Dateien mit der Endung .class.php enthalten genau eine Klasse, alle anderen Dateien sind normale Skripte wie bisher. (tgloeggl)
  • Ich stimme da tgloeggl vollkommen zu. (mriehe)

(:cellnr align=left bgcolor=#EEEEEE :) Regeln zur Lokalisierung (ssuchi) (:cell align=left bgcolor=#EEEEEE :)

  • sollten aus dem alten Code Style übernommen werden
  • müssen Vorrang vor Formatierungsregeln haben (z.B. Zeilenlänge), sonst kommt nur Murks bei der Übersetzung raus

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) phpDocumentor (chueser) (:cell align=left bgcolor=#EEEEEE :)

  • Dokumentation einheitlich mit phpDocumentor-Style & -Tags. (chueser)

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Sichtbarkeitsschlüsselwörter (chueser) (:cell align=left bgcolor=#EEEEEE :)

  • public, protected, private für Klassenvariablen und -methoden einsetzen.

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Paketstruktur (chueser) (:cell align=left bgcolor=#EEEEEE :)

  • Hier geht es um die Paketzugehörigkeit durch @package / @subpackage.
    • Funktionen, Konstanten and globale Variablen sind vom Filesystem in Files gruppiert, die wiederum mit @package-Tag innerhalb eines Page-Level DocBlocks in Pakete gruppiert werden.
    • Methoden und Klassenvariablen sind von PHP in Klassen gruppiert, die wiederum mit @package-Tag innerhalb eines Class-Level DocBlocks in Pakete gruppiert werden.
phpDocumentor parst die Struktur andernfalls nicht.

(:cell align=left bgcolor=#EEEEEE :)

(:tableend:)

PEAR Coding Standard

Einrückungen und Zeilenlänge

Benutzen Sie Einrückungen mit 4 Leerzeichen, keine Tabulatoren. Damit helfen Sie, Probleme zu vermeiden, die mit Diffs, Patches und anderen CVS-Funktionen entstehen.

Wir empfehlen einen Zeilenumbruch bei ca. 75 - 85 Zeichen durchzuführen, um die Lesbarkeit zu erhöhen.

Kontrollstrukturen (if, for, while, switch usw.)

Bsp für if-Kosntruktionen:

<?php
if ((condition1) || (condition2)) {
    action1;
} elseif ((condition3) && (condition4)) {
    action2;
} else {
    defaultaction;
}
?>

Kontroll-Ausdrücke sollten ein Leerzeichen zwischen den Schlüsselwörtern und der öffnenden Klammer haben, um sie von Funktionsaufrufen unterscheiden zu können.

Sie sollten unbedingt geschweifte Klammern verwenden, auch wenn sie technisch nur optional sind. Damit verbessern Sie die Lesbarkeit und vermeiden logische Fehler, wenn neue Zeilen hinzugefügt werden.

Bsp für switch-Ausdrücke:

<?php
switch (condition) {
case 1:
    action1;
    break;

case 2:
    action2;
    break;

default:
    defaultaction;
    break;
}
?>

Funktionsaufrufe

Funktionen sollten ohne Leerzeichen zwischen dem Funktionsnamen, der öffnenden Klammer und dem ersten Parameter aufgerufen werden. Leerzeichen sollten gesetzt werden zwischen Komma und jedem Parameter. Zwischen dem letzten Parameter, der schliessenden Klammer und Semikolon sollten keine Leerzeichen gesetzt werden.

Beispiel:

<?php
$var = foo($bar, $baz, $quux);
?>

Wie oben gezeigt, sollte ein Leerzeichen vor und hinter das Gleichheitszeichen gesetzt werden, wenn der Rückgabewert der Funktion einer Variable zugewiesen wird. Wenn ein Block zusammenhängender Zuweisungen durchgeführt wird, empfehlen wir mehrere Leerzeichen einzufügen, um die Lesbarkeit zu verbessern:

<?php
$short         = foo($bar);
$long_variable = foo($baz);
?>

Klassen-Definition

Die öffnende Klammer einer Klassen-Deklaration beginnt auf einer neuen Zeile:

<?php
class FooBar
{

    //... ihr Code

}
?>

Funktionsdefinitionen

Funktionsdeklarationen folgen dem „K&R-Stil“ (Programmierstil der C-Erfindern Brian W. Kernighan und Dennis Ritchie):

<?php
function fooFunction($arg1, $arg2 = '')
{
    if (condition) {
        statement;
    }
    return $val;
}
?>

Argumente mit Standardwerten werden am Ende der Argumentenliste platziert. Eine Funktion sollte immer einen aussagekräftigen Wert zurückliefern, soweit wie es möglich ist.

Beispiel:

<?php
function connect(&$dsn, $persistent = false)
{
    if (is_array($dsn)) {
        $dsninfo = &$dsn;
    } else {
        $dsninfo = DB::parseDSN($dsn);
    }

    if (!$dsninfo || !$dsninfo['phptype']) {
        return $this->raiseError();
    }

    return true;
}
?>

Kommentare

Sie müssen vollständige Inline-Dokumentation bereitstellen (Docblocks).

Sie sollten auch abseits der offziellen API-Dokumentation Kommentare im Quellcode einsetzen. Als Daumenregel gilt, wenn Sie auf einen Code-Abschnitt schauen und denken: „Wow, Ich würde nicht versuchen herauszufinden, wie es funktioniert“, sollten Sie auf jeden Fall einen Kommentar ergänzen, bevor Sie vergessen, wie es funktioniert.

Kommentare im C-Stil (/* */) und von Standard-C++ (//) sollten verwendet werden. Kommentare im Perl/shell-Stil (#) sollten Sie vermeiden.

Code einbinden

Immer wenn Sie eine Klassendatei unbedingt inkludieren müssen, dann benutzen Sie require_once. Benötigen Sie hingegen eine Datei nur bedingt, z.B. in Factory-Methoden, verwenden Sie include_once. Beide stellen sicher, dass die Datei nur einmal eingebunden wird. Beide Funktionen benutzen die gleiche Liste zur Verwaltung der bereits eingebundenen Dateien. Sie müssen sich über eine Mischung aus beiden Funktionsaufrufen keine Gedanken machen - eine Datei, die per require_once eingebunden wurde, wird nicht erneut eingebunden mit include_once.

Anmerkung: include_once und require_once sind Anweisungen, nicht Funktionen. Deshalb sollten die Dateinamen nicht in Klammern eingeschlossen werden.

PHP-Code-Tags

Benutzen Sie immer <?php ?> um Ihren PHP-Code zu markieren, niemale die Kurzform <? ?>. Die erste Variante funktioniert unabhängig vom Betriebssystem und der PHP-Konfiguration.

Kopf-Kommentare

Alle Quellcode-Dateien sollen einen „Page-level“ Docblock am Datei-Anfang besitzen und einen „Class-level“ Docblock unmittelbar vor jeder Klasse.

Beispiele:

<?php

/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */

/**
 * Short description for file
 *
 * Long description for file (if any)...
 *
 * PHP versions 4 and 5
 *
 * LICENSE: This source file is subject to version 3.0 of the PHP license
 * that is available through the world-wide-web at the following URI:
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
 * the PHP License and are unable to obtain it through the web, please
 * send a note to license@php.net so we can mail you a copy immediately.
 *
 * @category   CategoryName
 * @package    PackageName
 * @author     Original Author <author@example.com>
 * @author     Another Author <another@example.com>
 * @copyright  1997-2005 The PHP Group
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
 * @version    CVS: $Id:$
 * @link       http://pear.php.net/package/PackageName
 * @see        NetOther, Net_Sample::Net_Sample()
 * @since      File available since Release 1.2.0
 * @deprecated File deprecated in Release 2.0.0
 */ 

/*
 * Place includes, constant defines and $_GLOBAL settings here.
 * Make sure they have appropriate docblocks to avoid phpDocumentor
 * construing they are documented by the page-level docblock.
 */

/**
 * Short description for class
 *
 * Long description for class (if any)...
 *
 * @category   CategoryName
 * @package    PackageName
 * @author     Original Author <author@example.com>
 * @author     Another Author <another@example.com>
 * @copyright  1997-2005 The PHP Group
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
 * @version    Release: @package_version@
 * @link       http://pear.php.net/package/PackageName
 * @see        NetOther, Net_Sample::Net_Sample()
 * @since      Class available since Release 1.2.0
 * @deprecated Class deprecated in Release 2.0.0
 */
class Foo_Bar
{
}

?>

Erforderliche Tags

Kurzbeschriebung

Die Kurzbeschreibung muss in allen Docblocks existieren. Sie umfasst einen Satz, und sollten keinesfalls nur aus dem Namen des beschreibenden Objektes stehen.

PHP Version

Folgende Zeile muss in den Page-level-Docblock eingefügt werden. Sie beschreibt, unter welcher PHP-Version der Quellcode läuft:

  • PHP version 4
  • PHP version 5
  • PHP versions 4 and 5

@license

Sie können verschiedene Lizenzen für ihr Package verwenden. Sie müssen eine auswählen und diese sowohl im Page-level-, wie auch dem Class-level-Docblock einfügen:

  • @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
  • @license http://www.freebsd.org/copyright/freebsd-license.html BSD License (2 Clause)
  • @license http://www.debian.org/misc/bsd.license BSD License (3 Clause)
  • @license http://www.freebsd.org/copyright/license.html BSD License (4 Clause)
  • @license http://www.opensource.org/licenses/mit-license.html MIT License
  • @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
  • @license http://www.php.net/license/3_0.txt PHP License 3.0

@link

Die Link-Angabe muss im Page-level- and Class-level-Docblock erfolgen. Sie müssen den Eintrag für „PackageName“ natürlich durch den Namen Ihres Packages ersetzen. Auf diese Weise ist sicher gestellt, dass die API-Dokumentation die Links auf die Package-Homepage enthält.

  • @link http://pear.php.net/package/PackageName

@author

Es gibt keine klare Regel, wann jemand zur Liste der Quellcode-Autoren hinzugefügt werden sollte. Allgemein sollten sie substanziell beigetragen haben, ca. 10% bis 20% des Codes. Sie können Ausnahmen machen, wenn Methoden neu geschrieben wurden oder neue Logik beigesteuert wurde.

Einfache Code-Neuformatierungen oder Bug-Fixes sollten nicht zur Aufnahme in die Liste führen.

@since

Dieses Tag ist erforderlich, wenn eine Datei oder Klasse nach dem ersten Release zum Package ergänzt wurde. Verwenden Sie es nicht beim ersten Release.

@deprecated

Dieses Tag ist erforderlich, wenn eine Datei oder Klasse nicht mehr benutzt wird, aber für die Rückwärtskompatibilität noch verfügbar ist.

Optionale Tags

@copyright

Sie können dieses Tag setzen, wenn Sie Copyright-Anmerkungen ergänzen wollen. Das Format des Tags: Die vierstellige Jahreszahl bzw. bei mehreren Jahren, nur das erste und letzte Jahr getrennt mit einem Querstrich; danach der Copyright-Inhaber, also die betreffenden Personen, Firma oder z.B. die PHP Group.

Beispiele:

  • @copyright 2003 John Doe and Jennifer Buck
  • @copyright 2001-2004 John Doe
  • @copyright 1997-2004 The PHP Group
  • @copyright 2001-2004 XYZ Corporation

License Summary

If you are using the PHP License, use the summary text provided above. If another license is being used, please remove the PHP License summary. Feel free to substitute it with text appropriate to your license, though to keep things easy to locate, please preface the text with LICENSE: .

@see

Fügen Sie ein @see-Tag hinzu, wenn Sie auf andere Abschnitte in der Package-Dokumentation verweisen. Wenn Sie mehrere Einträge hinzufügen, verwenden Sie nicht mehrere Tags, sondern trennen diese in einem Tag per Komma.

Abfolge und Leerzeichen

Um die langfristige Lesbarkeit zu gewährleisten, sollten Texte und Tags dem gegebenem Beispiel folgen. Diese Festlegungen entsprechen dem JavaDoc-Standard.

Verwendung von @package_version@

Es gibt zwei Wege @package_version@ zu ersetzen. Das ist abhängig davon, ob Sie die Package-Datei package.xml von Hand erzeugen oder das Package PackageFileManager benutzen.

Wenn Sie die Datei direkt bearbeiten, ergänzen Sie ein <replace>-Tag für jede Datei. Das XML sieht dann ähnlich wie dieses aus:

<file name="Class.php">
  <replace from="@package_version@" to="version" type="package-info" />
</file>

Wenn PackageFileManager verwenden, rufen Sie addReplacement() für jede Datei auf:

<?php
$pkg->addReplacement('filename.php', 'package-info',
                     '@package_version@', 'version');
?>

Übergangsregeln

Für existierende kleine Packages

Existierende Packages mit nur wenigen Dateien sollten die DocBlöcke im nächst möglichen Release enthalten.

Für existierende große Packages

Existierende Packages mit vielen Dateien sollten die neuen DocBlöcke sobald wie möglich integrieren. Auf jeden Fall aber mit den nächsten Major-Release.

Neue und unveröffentliche Packages

Neue Packages und existierende Package, für welche noch kein Release existiert, müssen über die DocBlöcke verfügen, wenn ihr erstes Release erscheint.

CVS-Nutzung

Ergänzen Sie das $Id$-CVS-Schlüsselwort in jeder Datei.

Beispiel-URLs

Benutzen Sie example.com, example.org und example.net für alle Beispiel-URLs und Email-Adressen entsprechend RFC 2606.

Namens-Konventionen

Klassen

Verwenden Sie beschreibende Klassennamen und vermeiden Sie Abkürzungen. Klassennamen beginnen immer mit einen Großbuchstaben. Die Klassenhierarchie in PEAR spiegelt sich auch im Klassennamen wieder, jede Ebene der Hierarchie wird durch einen einzelnen Unterstrich getrennt.

Beispiele für Klassennamen:

  • Log
  • Net_Finger
  • HTML_Upload_Error

Funktionen und Methoden

Funktionen und Methoden sollten dem „Studly Caps“-Stil folgen (auch bekannt als „Bumpy Base“ oder „Camel Caps“). Funktionsnamen sollte der Package-Name vorangestellt werden, um Kollisionen mit anderen Funktionsnamen zu vermeiden. Der erste Buchstabe nach dem Prefix wird klein geschrieben, und jeder Buchstabe eines neuen „Wortes“ im Namen wird großgeschrieben.

Beispiele:

  • connect()
  • getData()
  • buildSomeWidget()
  • XML_RPC_serializeData()

Privaten Klassenelemente wird ein Unterstrich vorangestellt.

Zum Beispiel:

  • _sort()
  • _initTree()

$this->_status

Anmerkung: Unter PHP 5 gilt: Klassenelemente, welche protected sind, werden nicht mit einem Unterstrich versehen:

  • protected $somevar
  • protected function initTree()

Konstanten

Konstanten werden immer vollständig groß geschrieben, mit Unterstrichen zwischen den Worten. Ihre Namen müssen mit dem Klassen- bzw. Package-Namen beginnen. Zum Beispiel beginnen alle Konstanten des DB::-Packages mit DB_.

Anmerkung: Die Konstanten true, false und null werden als einzige Ausnahme immer klein geschrieben.

Globale Variablen

Wenn Ihr Package globale Variablen benötigt, sollte deren Name mit einem Unterstrich beginnen, gefolgt vom Package-Namen und einem weiteren Unterstrich. Zum Beispiel benutzt das PEAR-Package die globale Variable $_PEAR_destructor_object_list.

Dateiformate

Alle Skripte in PEAR müssen:

  • als ASCII gespeichert werden.
  • mit dem Zeichensatz ISO-8859-1 kodiert werden.
  • den UNIX-Konventionen folgen. „Unix-Konventionen“ bedeutet:
    • Zeilen dürfen nur mit dem Line-Feed-Zeichen (LF) enden. Das Zeichen entspricht dem Ordinal-Wert 10, Octal 012 und hexadezimal 0A. Benutzen Sie kein Carriage-Return-Zeichen (CR) wie unter Apple Macintosh-Computern oder die CRLF-Kombination unter Windows.
    • Fügen Sie ein Zeilenende-Zeichen nach dem schliessendem PHP-Tag (?>) ein. Das bedeutet, der Cursor im Editor steht eine Zeile nach dem schliessendem Tag.

E_STRICT-kompatibler Code

Jeder Code muss E_STRICT-kompatibel sein. Das heisst, er darf keine Fehler oder Warnungen erzeugen, wenn das Fehler-Reporting von PHP auf E_STRICT eingestellt ist.

Die Entwicklung existierender Packages, die dieser Konvention noch nicht entsprechen, müssen dies auch noch nicht. Erst wenn eine neue major-Version eines Packages erscheint, dann muss diese Version der E_STRICT-Konvention entsprechen.

Richtlinen zur Fehlerbehandlung

Richtlinen zur Fehlerbehandlung

Dieser Abschnitt beschreibt wie Fehler in PEAR-Packages behandelt werden sollen, die für PHP 5 und 6 entwickelt werden. Fehler werden über Exceptions abgewickelt, sie wurden mit PHP 5.0 und der Zend Engine 2 eingeführt.

Was ist ein Fehler?

Ein Fehler ist definiert als ein unerwartet, nicht korrekter Programmzustande, der nicht wieder behoben werden kann. Zur Vereinfachung dieser Definition gilt, dass die Behebung des Fehlers nicht innerhalb einer Methode möglich ist. Eine unvollständige Behebung gilt trotzdem als Behebung.

Beispiel 4-1. Eine typische Fehlersituation

<?php
/**
 * Verbinde zur angegebenen Datenbank
 *
 * @throws Example_Datasource_Exception wenn der Verbindungsaufbau fehlschlägt
 */
function connectDB($dsn) {
    $this->db =& DB::connect($dsn);
    if (DB::isError($this->db)) 
    {
        throw new Example_Datasource_Exception(
                "Unable to connect to $dsn:" . $this->db->getMessage()
        );
    }
}
?>

In diesem Beispiel soll die Methode die Verbindung mit der Datenbank mit dem gegegebenem DSN herstellen. Die Methode ruft ihrerseits nur PEAR::DB, wenn dieses Package einen Fehler wirft, kann nur eine Exception erzeugt und geworfen werden, ohne weiter Einfluß nehmen zu können.

Beispiel 4-2. Fehlerbehandlung mit Behebung

<?php
/*
 * Verbinde mit einer der möglichen Datenbanken
 *
 * @throws Example_Datasource_Exception wenn keine der gewählten
 *         Datenbank angesprochen werden konnte.
 *
 * @throws Example_Config_Exception wenn keine Datenbanken
 *         konfiguriert wurden
 */

function connect(Config $conf) 
{
    $dsns =& $conf->searchPath(array('config', 'db'));
    if ($dsns === FALSE) throw new Example_Config_Exception(
        'Unable to find config/db section in configuration.'
    );

    $dsns =& $dsns->toArray();

    foreach($dsns as $dsn) {
        try {
            $this->connectDB($dsn);
            return;
        } catch (Example_Datasource_Exception e) {
            // Warn-/Logging-Code um den Verbindungsfehler
            // aufzuzeichnen
        }
    }
    throw new Example_Datasource_Exception(
        'Unable to connect to any of the configured databases'
    );
}
?>

Das zweite Beispiel zeigt, wie eine Exception empfangen und behandelt wird. Die verwendete connectDB()-Methode kann nur einen Fehler melden, wenn die Verbindung fehlschlägt. Die übergeordnete Methode connect() hingegen weiss, dass das Objekt auch mit einer der anderen Datenbank-Verbindungen lauffähig ist. Deshalb kann der Fehler als behoben angesehen werden und die Exception wird nicht weitergeleitet.

Beispiel 4-3. Unvollständige Behebung

<?php
/**
 * loadConfig wertet die angegebene Konfiguration aus. Wenn die
 * Konfiguration unkorrekt ist, dann wird auf die Standard-
 * zurückgegriffen
 *
 */
function loadConfig(Config $conf) 
{
    try {
        $this->config = $conf->parse();
    } catch (Config_Parse_Exception e) {
        // Warn-/Logging-Code
        // Unvollständige Fehlerbehebung
        $this->config = $this->defaultConfig;
    }
}
?>

Die Fehlerbehebung führt zu Seiteneffekten, deshalb ist sie nicht vollständig. Das Programm kann weiterlaufen, die Exception gilt als behandelt und muss nicht weitergeleitet werden. Wie im vorherigen Beispiel sollte die aufgetretene Exception aber trotzdem geloggt werden oder eine andere Form der Warnung stattfinden.

Fehler-Benachrichtigung PHP 5 PEAR-Packages

Fehlerhafte Zustände in PEAR-Packages für PHP 5 müssen über Exceptions gemeldet werden. Nicht mehr verwendet werden sollten Fehlercodes oder ein PEAR_Error-Objekt. Diese Regel gilt natürlich nicht, wenn das Package kompatibel mit PHP 4 bleiben muss. In diesem Fall gelten die Konvention der PEAR Coding Standards unter PHP 4 weiter.

Eine Exception sollte immer geworfen werden, wenn ein fehlerhafter Zustand auftritt, entsprechend der Definition im vorherigen Abschnitt. Die geworfene Exception sollte genügend Informationen enthalten, um den Fehler debuggen zu können und schnell dessen Grund herauszufinden. Bedenken Sie, dass in Produktionsumgebungen keine Exception an den Endanwender durchdringen sollten. Deshalb muss man sich keine Gedanken machen über die Komplexität der Fehlermeldung.

Die Basis-Klasse PEAR_Exception enthält eine wörtliche Beschreibung des Fehlers, womit der Programmzustand beschrieben wird, der zum Fehler führte, und - optional - Execptions, die durch untergeordnete Programmaufrufe herbei geführten wurden und die ursprüngliche Ursache des Fehlers darstellen können.

Die Arten von Informationen die in einer Exception enthalten sein müssen, hängt von der Art des Fehlers ab. Es gibt drei Varianten von Exceptions:

  1. Fehler, die während der Vorabprüfung auftreten können.
  2. Fehler, die durch untergeordneten Bibliotheksaufrufe auftreten und durch Fehlercodes oder -Objekte signalisiert werden
  3. Nicht-korrigierbare Exceptions von untergeordneten Bibliotheken.

Fehler, die während der Vorabprüfung auftreten können, sollten eine Beschreibung der fehlgeschlagenen Prüfung enthalten. Wenn möglich sollte der fehlerhafte Wert mit angegeben werden.

Beispiel 4-4.

<?php
function divide($x, $y)
{
    if ($y == 0) {
        throw new Example_Aritmetic_Exception('Division by zero');
    }
}
?>

Fehler, die durch untergeordneten Bibliotheksaufrufe auftreten und durch Fehlercodes oder -Objekte signalisiert werden, sollten in Exceptions umgewandelt werden, wenn diese nicht behoben werden können. Die Fehlerbeschreibung sollte die originale Fehlerinformationen enthalten bzw. entsprechend konvertiert werden. Am Beispiel der obigen connect()-Methode:

Beispiel 4-5.

<?php
/**
 * Verbinde zur angegebenen Datenbank
 *
 * @throws Example_Datasource_Exception wenn der Verbindungsaufbau fehlschlägt
 */
function connectDB($dsn) {
    $this->db =& DB::connect($dsn);
    if (DB::isError($this->db)) {
        throw new Example_Datasource_Exception(
                "Unable to connect to $dsn:" . $this->db->getMessage()
        );
    }
}
?>

Nicht-korrigierbare Exceptions von untergeordneten Bibliotheken sollten weitergeleitet oder erneut geworfen werden. Wenn sie weitergeleitet werden soll, dann behandeln Sie die Exception nicht weiter. Wenn Sie die Exception erneut werfen, dann müssen Sie die originale Exception in der neuen Exception verpacken.

Beispiel 4-6. Eine Exception neu verpacken

<?php
function preTaxPrice($retailPrice, $taxRate) 
{
    try {
        return $this->divide($retailPrice, 1 + $taxRate);
    } catch (Example_Aritmetic_Exception e) {
        throw new Example_Tax_Exception('Invalid tax rate.', e);
    }
}
?>

Beispiel 4-7. Eine Exception weiterleiten

<?php
function preTaxPrice($retailPrice, $taxRate) 
{
    return $this->divide($retailPrice, 1 + $taxRate);
}
?>

Die Entscheidung, ob eine Exception neu verpackt oder weitergeleitet werden soll, ist eine Frage der Software-Architektur. Exceptions sollten weitergeleitet werden, ausser in zwei Fällen:

  1. Die originale Excpetion ist von einem anderen Package. Wenn diese weitergeleitet wird, dann würden Details der Implementierung nach aussen dringen.
  2. Die Methode kann nützliche Debug-Informationen ergänzen.

Exceptions und der normale Programmfluß

Exceptions sollten niemals als Bestandteil des normalen Programmflußes benutzt werden. Wenn alle Logik zur Behandlung von Exceptions entfernt würde (try-catch-Statements), dann sollte der verbliebende Code den "wahren Pfad" repräsentieren – dem Programmfluß, wenn keinerlei Fehler auftreten würden.

Diese Forderung entspricht der Erwartung, dass Exceptions nur bei fehlerhaften Zuständen geworfen werden sollten und niemals bei regulären Zuständen.

Ein Beispiel für die falsche Benutzung der Exception-Weiterleitung ist die Rückgabe eines Wertes eines rekursiven Aufrufs:

Beispiel 4-8.

<?php
/**
 * Rekursive Suche in einem Baum nach einem String
 * @throws ResultException
 */
public function search(TreeNode $node, $data)  
{
    if ($node->data === $data) {
         throw new ResultException( $node );
    } else {
         search( $node->leftChild, $data );
         search( $node->rightChild, $data );
    }
}
?>

Im Beispiel wird die ResultException benutzt, um "schnell" wieder aus der Rekursion heraus zu kommen. Das ist im Fehlerfall tatsächlich praktisch, in diesem Fall, aber nur ein Beispiel für einen faulen Programmierer. Die Klassen-Hierarchie von Exceptions

Alle Exceptions, die von Packages geworfen werden, müssen von PEAR_Exception abstammen. PEAR_Exception bietet zusätzliche Fähigkeiten, um andere Exceptions zu verpacken. Sie finden diese nicht in der obersten PHP Exception-Klasse, sind aber notwendig, um die oben gestellten Anforderungen zu erfüllen.

Zusätzlich sollte jedes PEAR-Package seine eigene Exception-Klasse definieren; der Name der Klasse entspricht dem Muster: <Package_Name>_Exception. Jede Exception sollte von dieser Klasse abgeleitet werden. Exceptions dokumentieren

Da PHP, im Gegensatz zu Java, es nicht erfordert, mögliche Exceptions in der Funktionssignatur aufzunehmen, ist deren sorgfältige Dokumentation im Methodenkopf wichtig.

Beispiel 4-9. Exceptions werden dokumentiert mit dem @throws-Schlüsselwort

<?php
/**
 * Diese Methode sucht nach Aliens.
 *
 * @return array Array von Alien-Objekten.
 * @throws AntennaBrokenException wenn die Impedanz-Leser anzeigt, dass die
 *         Antenne nicht funktioniert
 *
 * @throws AntennaInUseException wenn ein anderer Prozess die Antenne
 *         bereits benutzt
 */
public function findAliens($color = 'green');
?>

In vielen Fällen wandelt die mittlere Schicht einer Anwendung Exceptions von untergeordneten Methoden in aussagekräftiger, anwendungsspezifische Exceptions. Das sollte ebenfalls angesprochen werden:

Beispiel 4-10.

<?php
/**
 * Lade Session-Objekte in den Shared-Memory
 *
 * @throws LoadingException Jede untergeordnete IOException wird als
 *         LoadingException neu verpackt.
 */
public function loadSessionObjects();
?>

In anderen Fällen kann ihre Methode als Filter fungieren, der nur bestimmte Exceptions weiterleitet. Dann sollten Sie dokumentieren, welche Exceptions nicht von Ihrer Methode abgefangen werden.

Beispiel 4-11.

<?php
/**
 * Führt eine Reihe von Datenbankanfragen aus (atomar, nicht innerhalb einer Transaktion).
 * @throws SQLException Low-level SQL-Fehler werden direkt weitergeleitet.
 */
public function batchExecute();
?>

Exceptions als Teil der API

Exceptions spielen eine kritische Rolle in der API ihrer Bibliothek. Entwickler, die Ihre Bibliothek verwenden, sind abhängig von der angemessenen Beschreibung wo und warum Exceptions auftreten in Ihrem Package. Auch die sorgfältige Planung der Fehlermeldungen ist ein wichtiger Faktor für die Erhaltung der Rückwärts-Kompatibilität.

Da Exceptions ein integraler Bestandteil der API ihres Packages sind, darf bei Änderungen daran die Rückwärts-Kompatibilität (BC) nicht grundlos gebrochen werden.

Dinge, die zum Bruch führen:

  • Jede Änderung an Methoden, die Exceptions werfen.
  • Wenn eine Exception-Klasse verwendet wird, die höher in der Vererbungskette liegt, als die ursprüngliche. Zum Beispiel, wenn Sie in einer neueren Version eine PEAR_Exception werfen würden, in der alten aber z.B. PEAR_IOException verwendet haben.

Dinge, die nicht zum Bruch führen:

  • Wenn eine abgeleitete Klasse der originalen Exception verwendet wird. Zum Beispiel, wenn Sie in der aktuellen Version eine PEAR_IOException werfen, und in älteren Versionen PEAR_Exception. Natürlich nur unter der Voraussetzung, dass PEAR_IOException von PEAR_Exception) abgeleitet ist.

Best practices

Es gibt einige andere Dinge, die nicht vom PEAR Coding Standard betroffen sind, sondern von den persönlichen Gewohnheiten abhängen und nicht die Lesbarkeit unmittelbar berühren. Das betrifft z.B. die Frage 'Einfache oder doppelte Anführungszeichen'. Es handelt sich um Konstrukte, welche die Programmierung vereinfachen ohne konkrete Probleme zu verursachsen. Welche dieser 'üblichen' Praktiken genutzt wird, diese Entscheidung ist dem Programmierer überlassen. Wichtiger ist die konsequente Anwendung der eigenen Entscheidung in einem Package. Respektieren Sie die Entscheidung des verantwortlichen Programmierers, wenn Sie fremde Packages verändern.

Beispieldatei inklusive Docblock-Kommentaren

Der Quellcode von PEAR-Packages wird von tausenden von Menschen gelesen. Genauso kann es passieren, dass andere einmal an Ihrem Package entwicklen werden. Um es ihnen leichter zu machen, ist die Formatierung des Quellcode und der Docblöcke standarisiert. Damit können Andere Informationen einfacher finden, das sie wissen, wo sie suchen müssen.

Jeder Docblock im Beispiel enthält viele Details wie Sie die Kommentare schreiben sollten. Diese Instruktionen sind aus zwei Gründen wichtig. Erstens können Benutzer und Entwickler schneller verstehen, was Ihr Code tut. Zweitens wird auf der PEAR-Webseite die Quellcode-Dokumentation für jedes Release von jedem Package bereitgestellt und Sie sollten auch dafür sorgen, dass diese Möglichkeit sinnvoll genutzt werden kann.

Bitte achten Sie auch auf den Einsatz von vertikalen und horizontalen Leerräumen. Sie sind Bestandteil der Standards.

Die „Fold Markers“ (// {{{ und // }}}) sind optional. Wenn Sie nicht benötigt werden, entfernen Sie die Einstellung foldmethod=marker aus dem Block mit Vim-Einstellungen.

<?php

/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */

/**
 * Kurze Beschreibung des Datei-Inhalts
 *
 * Lange Beschreibung des Datei-Inhaltes, wenn erforderlich.
 *
 * PHP versions 4 and 5
 *
 * LICENSE: This source file is subject to version 3.0 of the PHP license
 * that is available through the world-wide-web at the following URI:
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
 * the PHP License and are unable to obtain it through the web, please
 * send a note to license@php.net so we can mail you a copy immediately.
 *
 * @category   CategoryName
 * @package    PackageName
 * @author     Original Author <author@example.com>
 * @author     Another Author <another@example.com>
 * @copyright  1997-2005 The PHP Group
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
 * @version    CVS: $Id:$
 * @link       http://pear.php.net/package/PackageName
 * @see        NetOther, Net_Sample::Net_Sample()
 * @since      File available since Release 1.2.0
 * @deprecated File deprecated in Release 2.0.0
 */

/**
 * Das ist ein "Docblock-Kommentar", auch bekannt als "docblock"/"Docblock"
 * Der Klassen-Docblock weiter unten enthält eine Beschreibung wie sie
 * geschrieben werden.
 */
require_once 'PEAR.php';

// {{{ constants

/**
 * Methoden geben diesen Wert im Erfolgsfall zurück.
 */
define('_NET_SAMPLE_OK', 1);

// }}}
// {{{ GLOBALS

/**
 * Die Anzahl der erzeugten Objekte
 * @global int $GLOBALS['NET_SAMPLE_Count']
 */
$GLOBALS['_NET_SAMPLE_Count'] = 0;

// }}}
// {{{ Net_Sample

/**
 * Ein Beispiel wird Code entsprechend der PEAR-Standards aussieht
 *
 * Anmerkung des Übersetzers: Quelltext-Kommentare sollten natürlich
 * durchgängig in Englisch erfolgen!
 *
 * Ein Docblock-Kommentar beginnt mit "/**" am Anfang.  Beachten Sie, das "/"
 * beginnt mit der normalen Einrückung und die Sterne darunter stehen in der
 * selben Textspalte wie der erste Stern. Der letzte Zeile des Kommentar-Blocks
 * sollte unmittelbar das zu dokumentierende Element folgen,
 * Vermeiden Sie zusätzliche Leerzeilen. Ergänzen Sie eine Leerzeile
 * zwischen Absätzen im Kommentartext, genauso zwischen Kommentartext und dem
 * ersten @-Tag. Ein Zeilenumbruch im Kommentartext sollte nach 80 Zeichen
 * erfolgen.
 *
 * Docblöcke können nur für eine begrenzte Anzahl an Elementen verwendet
 * werden (Klassen, Eigenschaften, Methoden, Konstanten, Include und
 * globale Variablen. In der Dokumentation zu phpDocumentor finden Sie mehr
 * Informationen dazu:
 * http://phpdoc.org/docs/HTMLSmartyConverter/default/phpDocumentor/tutorial_phpDocumentor.howto.pkg.html
 *
 * Der Javadoc Style Guide ist eine exzellente Quelle wie man Kommentare
 * formulieren sollte. Letztlich sind diese Informationen eine Zusammenfassung
 * davon, andererseits gibt es aber auch einige Abweichungen davon.
 * http://java.sun.com/j2se/javadoc/writingdoccomments/index.html#styleguide
 *
 * Diese erste Zeile jedes Docblocks ist eine Zusammenfassung. Sie sollte
 * genau einen Satz umfassen, ohne Punkt am Ende. Zusammenfassungen für
 * Klassen, Eigenschaften und Konstanten sollten nicht deren Namen enthalten
 *
 * Die unten aufgeführten Tag werden üblicherweise für Klassen benutzt.
 * Die Tags @category bis @version sind erforderlich. Die Übrigen
 * sollten ergänzt werden, wenn erforderlich. Verwenden Sie die Tags
 * in der Reihenfolge, wie hier aufgeführt. phpDocumentor bietet
 * weitere Tags, verwenden Sie diese, wenn erforderlich.
 *
 * @category   CategoryName
 * @package    PackageName
 * @author     Original Author <author@example.com>
 * @author     Another Author <another@example.com>
 * @copyright  1997-2005 The PHP Group
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
 * @version    Release: @package_version@
 * @link       http://pear.php.net/package/PackageName
 * @see        NetOther, Net_Sample::Net_Sample()
 * @since      Class available since Release 1.2.0
 * @deprecated Class deprecated in Release 2.0.0
 */
class Net_Sample
{
    // {{{ properties

    /**
     * Der Zustand von foo's universe
     *
     * Potentielle Werte sind 'good', 'fair', 'poor' und 'unknown'.
     *
     * @var string
     */
    var $foo = 'unknown';

    /**
     * The status of life
     *
     * Vergessen Sie nicht, dass private Elemente mit einem
     * Unterstrich beginnen müssen.
     *
     * @var bool
     * @access private
     */
    var $_good = true;

    // }}}
    // {{{ setFoo()

    /**
     * Registriert den Zustand des Foo-Universums
     *
     * Die Zusammenfassung für eine Methode sollte besser in der 3. Person 
     * Einzahl statt in der 2. Person formuliert werden.
     * Das Verb sollte am Anfang stehen.
     *
     * Die Zusammenfassung sollte mehr Informationen liefern, die über den
     * Methodennamen hinaus gehen. Die besten Methodennamen sind
     * selbst beschreibend, sie sagen was die Methode im Grunde macht.
     * Wenn die Zusammenfassung den Methodennamen nur in Form eines
     * Satzes wiederholt, liefert sie keine zusätzlichen Informationen.
     *
     * Beispiele für die Zusammenfassung:
     *   + Sets the label              (empfohlen)
     *   + Set the label               (vermeiden)
     *   + This method sets the label  (vermeiden)
     *
     * Als nächstes werden die üblichen Tags für Methoden angeführt.
     * Ein @param-Tag muss für jeden Parameter angegeben werden.
     * Die Tags @return und @access sind wahlfrei. Das @throw-Tag
     * muss angegeben werden, wenn die Methode Exceptions wirft.
     * Das Tag @static ist erforderlich, wenn die Methode statisch
     * aufgerufen werden kann. Die übrigen Tags brauchen Sie nur
     * angeben, wenn diese benötigt werden. Bitte geben Sie die
     * Tags in der Reihenfolge an, wie sie hier aufgeführt sind.
     * phpDocumentor bietet weitere Tags, benutze Sie diese, wenn
     * es sinnvoll ist.
     *
     * Das @param-Tag umfasst den Datentypen, den Parameter-Namen, gefolgt
     * von einer Beschreibung. Per Konvention sollte die Beschreibung beginnen
     * mit dem Datentyp, dem ein Artikel ("a", "an" oder "the") vorangestellt
     * werden kann. Setzen Sie zwei Leerzeichen zwischen dem Namen
     * des Parameters und seiner Beschreibung für eine bessere Lesbarkeit.
     *
     * Wenn Sie einen Satz schreiben, starten Sie nicht mit einem
     * Großbuchstaben und beenden Sie ihn nicht mit einem Punkt:
     *   + the string to be tested
     *
     * Wenn Sie mehr als einen Satz schreiben, setzen Sie einen Punkt und
     * beginnen Sie den zweiten Satz mit einem Großbuchstaben:
     *   + the string to be tested. Must use UTF-8 encoding.
     *
     * Das @return-Tag sollte den Datentyp und eine Beschreibung des
     * zurückgegebenen Wertes enthalten. Der Datentyp kann einer von PHP's
     * Datentyp sein (int, float, bool, string, array, object, resource, mixed)
     * und sollte den primär zurückgegebenen Wert enthalten. Z.B.
     * eine Methode gibt korrekterweise ein Objekt zurück und nur im
     * Fehlerfall 'false', dann sollten Sie 'object' angeben statt
     * 'mixed'. Verwenden Sie 'void' wenn nicht zurückgegeben wird.
     *
     * Hier ein Beispiel für Quellcode-Texte:
     * <code>
     * require_once 'Net/Sample.php';
     *
     * $s = new Net_Sample();
     * if (PEAR::isError($s)) {
     *     echo $s->getMessage() . "\n";
     * }
     * </code>
     *
     * Hier ein Beispiel für Nicht-PHP-Code:
     * <samp>
     * pear install net_sample
     * </samp>
     *
     * @param string $arg1  the string to quote
     * @param int    $arg2  an integer of how many problems happened.
     *                       Rücken Sie nachfolgende Zeilen in der Beschreibung
     *                       entsprechend ein.
     *
     * @return int  the integer of the set mode used. FALSE if foo
     *               foo could not be set.
     * @throws exceptionclass  [description]
     *
     * @access public
     * @static
     * @see Net_Sample::$foo, Net_Other::someMethod()
     * @since Method available since Release 1.2.0
     * @deprecated Method deprecated in Release 2.0.0
     */
    function setFoo($arg1, $arg2 = 0)
    {
        /*
         * Das ist ein "Block Kommentar". Das Format entspricht
         * den obigen Kommentaren, mit der Ausnahme, das der Kommentarbeginn
         * nur einen Stern enthält.
         * phpDocumentor wertet diese nicht aus.
         */
        if ($arg1 == 'good' || $arg1 == 'fair') {
            $this->foo = $arg1;
            return 1;
        } elseif ($arg1 == 'poor' && $arg2 > 1) {
            $this->foo = 'poor';
            return 2;
        } else {
            return false;
        }
    }

    // }}}
}

// }}}

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * c-hanging-comment-ender-p: nil
 * End:
 */

?>

(Quelle: PEAR Coding Standard, 05.02.2008)

geändert in:
 
 
08.03.2008 16:27 Uhr von chueser -
Zeile 9 hinzugefügt:
 
 
08.03.2008 15:23 Uhr von chueser -
Zeilen 32-35 gelöscht:

––

(deprecated)

 
 
08.03.2008 15:13 Uhr von chueser - + new one + software engineering
Zeilen 1-36 hinzugefügt:
 
 
06.03.2008 23:04 Uhr von nstolle -
Zeile 0 gelöscht:

G7vqcp <a href="http://zuhuhsozniys.com/">zuhuhsozniys</a>, [url=http://kspcpylceilq.com/]kspcpylceilq[/url], [link=http://ydbnntzoezxj.com/]ydbnntzoezxj[/link], http://hjewbgauswor.com/

 
 
06.03.2008 20:24 Uhr von 195.225.178.31 - HwnjixmbBFstwh
Zeilen 1-1203 bearbeitet:

Vorschlag für einen StudIP Coding Standard: PEAR Coding Standard

Diskussion über den PEAR Coding Standard

Einleitung
Zusammenfassung
Änderungswünsche & mehr

Inhaltsverzeichnis: PEAR Coding Standard

Einrückungen und Zeilenlänge
Kontrollstrukturen
Funktionsaufrufe
Klassen-Definition
Funktionsdefinitionen
Kommentare
Code einbinden
PHP-Code-Tags
Kopf-Kommentare
CVS-Nutzung
Beispiel-URLs
Namens-Konventionen
Dateiformate
E_STRICT-kompatibler Code
Richtlinen zur Fehlerbehandlung
Best practices
Beispieldatei inklusive Docblock-Kommentaren

Diskussion über den PEAR Coding Standard

Einleitung

Die Einhaltung eines Coding Standards ist ein wichtiger Bestandteil guter Projektarbeit. Gerade in Open Source Projekten mit vielen Entwicklern wird damit gewährleistet, dass Source Code eine hohe Qualität erhält/behält, weniger Bugs enthält, und einfacher zu warten ist.

Darüber hinaus gibt es jedoch auch andere wichtige Faktoren:

  • Kommunikation
  • funktionierender Code
  • übersichtlicher Code
  • Module und Modultests
  • Wiederverwendbarkeit des Codes
  • einfache Wartung des Codes
  • Code, der leicht zu erweitern ist
  • Unterstützung von Refactoring

um nur einige zu nennen. Ein Coding Standard unterstützt alle genannten Punkte. Neue Entwickler können sich schnell einarbeiten, denn wenn jeder den Code des anderen versteht, kann man auch schnell Bug-Fixes vornehmen oder Module des anderen verwenden ohne das Rad neu zu erfinden.

Um diese Ziele zu erreichen, muss eine PHP-Applikation:

  • leicht zu lesen sein
  • leicht verständlich sein
  • gut dokumentiert sein
  • durch verschiedene Programmierer wartbar
  • frei von typischen Fehlern

sein. Im besten Falle kann sogar der Anwender die Module der PHP-Applikation verstehen und weiter verwenden.

Das Ziel von leicht verständlichem Source-Code ist erreicht, wenn jedes Mitglied des Teams, jedes Modul aus dem Stehgreif erklären kann. Nicht zuletzt soll jede Arbeit am Projekt, dem Code und der Dokumentation Spaß machen. Je höher der Frustfaktor ist, je unübersichtlicher Strukturen und Code sind, desto höher ist die Wahrscheinlichkeit, das die Arbeit keinen Spaß mehr macht. Das gilt es auf jeden Fall zu verhindern.

Wenn sich ein Projekt an Coding Standards hält, dann sind einige gute Effekte zu beobachten:

  • Entwickler können in jeden Code hineienschauen und sofort heraus finden was dort vor sich geht.
  • Die Lebenszeit eines Softwareprojektes wird verlängert und überlebt die Lebenszeit der erfahrenen Entwickler.
  • Neue Leute können sich schnell einarbeiten.
  • PHP Einsteiger brauchen keinen persönlichen Style enwickeln und diesen bis zum bitteren Ende verteidigen.
  • PHP Einsteiger werden davor bewahrt die gleichen Fehler wieder und wieder zu machen.
  • In konsistenten Umgebungen werden weniger Fehler gemacht.

Ich freue mich auf eine früchtetragende Diskussion mit guten Ergebnissen hinsichtlich der Verwirklichung des StudIP Coding Standards.

PEAR Coding Standard
Note: Sehr zu empfehlen!

Zusammenfassung

(:table border=1 width=100% align=center cellspacing=0 :)

(:cellnr width=20% align=center bgcolor=#CCCCCC :) Feature (:cell width=50% align=center bgcolor=#CCCCCC :) Ausprägung (:cell width=30% align=center bgcolor=#CCCCCC :) Euer Kommentar (mit Namen bitte)

(:cellnr align=left bgcolor=#EEEEEE :) Einrückungen (:cell align=left bgcolor=#EEEEEE :)

  • 4 Leerzeichen, keine Tabulatoren

(:cell align=left bgcolor=#EEEEEE :)

  • find ich gut so (chueser)
  • find ich nicht gut so (ssuchi)
  • warum nicht? (chueser)

(:cellnr align=left bgcolor=#EEEEEE :) Zeilenlänge (:cell align=left bgcolor=#EEEEEE :)

  • ca. 75 - 85 Zeichen

(:cell align=left bgcolor=#EEEEEE :)

  • kollidiert schnell mit den Vorschriften zur Lokalisierung (ssuchi)
  • wieso gibt es diese vorschriften? (mlunzena)

(:cellnr align=left bgcolor=#EEEEEE :) Kontrollstrukturen (:cell align=left bgcolor=#EEEEEE :)

  • Leerzeichen zwischen den Schlüsselwörtern und der öffnenden Klammer
  • immer geschweifte Klammern verwenden
  • öffnende geschweifte Klammer in gleicher Zeile

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Funktionsaufrufe (:cell align=left bgcolor=#EEEEEE :)

  • kein Leerzeichen zwischen dem Funktionsnamen, der öffnenden Klammer und dem ersten Parameter

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Klassen-Definition (:cell align=left bgcolor=#EEEEEE :)

  • öffnende Klammer einer Klassen-Deklaration beginnt auf einer neuen Zeile

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Funktionsdefinitionen (:cell align=left bgcolor=#EEEEEE :)

  • öffnende Klammer einer Funktionsdefinition beginnt auf einer neuen Zeile
  • Argumente mit Standardwerten werden am Ende der Argumentenliste platziert
  • wenn möglich, immer einen aussagekräftigen Wert zurückliefern

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Kommentare (:cell align=left bgcolor=#EEEEEE :)

  • vollständige Inline-Dokumentation (Docblocks): File, Includes, Konstanten, Variablen, Methoden, Klasse
  • unbedingt (!) auch abseits der offziellen API-Dokumentation Kommentare im Quellcode einsetzen
  • Als Daumenregel gilt, wenn Sie auf einen Code-Abschnitt schauen und denken: „Wow, Ich würde nicht versuchen herauszufinden, wie es funktioniert“, sollten Sie auf jeden Fall einen Kommentar ergänzen, bevor Sie vergessen, wie es funktioniert.

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Code einbinden (:cell align=left bgcolor=#EEEEEE :) (:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) PHP-Code-Tags (:cell align=left bgcolor=#EEEEEE :)

  • immer die Langform <?php ?> benutzen

(:cell align=left bgcolor=#EEEEEE :)

  • während deiner Präsentation hatten wir schon angemerkt, dass das natürlich nicht für die Templates gilt.. (mlunzena)
  • sehe ich keinen Sinn drin, bisher wird fast immer die Kurzform benutzt (ssuchi)
  • funktioniert unabhängig vom Betriebssystem und PHP-Konfiguration (s.u.) (chueser)

(:cellnr align=left bgcolor=#EEEEEE :) Kopf-Kommentare (:cell align=left bgcolor=#EEEEEE :)

  • Alle Quellcode-Dateien sollen einen „Page-level“ Docblock am Datei-Anfang besitzen und einen „Class-level“ Docblock unmittelbar vor jeder Klasse.
  • Docblock = short decription + long description + tag list

(:cell align=left bgcolor=#EEEEEE :)

  • Finde ich sehr gut. Bitte auch einheitlich wie weiter unten beschrieben. Momentan ist „Page-level“ Docblock in vielen Dateien sehr unterschiedlich. (mriehe)

(:cellnr align=left bgcolor=#EEEEEE :) CVS-Nutzung (:cell align=left bgcolor=#EEEEEE :)

  • $Id$-CVS-Schlüsselwort in jede Datei.

(:cell align=left bgcolor=#EEEEEE :)

  • in diesem Fall ist wohl das SVN- Schlüsselwort gemient. (mriehe)

(:cellnr align=left bgcolor=#EEEEEE :) Beispiel-URLs (:cell align=left bgcolor=#EEEEEE :) (:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Namens-Konventionen (:cell align=left bgcolor=#EEEEEE :)

  • beschreibende Klassennamen und Abkürzungen vermeiden
  • Klassennamen beginnen immer mit einen Großbuchstaben
  • Klassenhierarchie spiegelt sich im Klassennamen wieder, jede Ebene der Hierarchie wird durch einen einzelnen Unterstrich getrennt
  • Funktionen und Methoden im „Camel Caps“
  • Funktionsnamen sollte der Package-Name vorangestellt werden
  • erster Buchstabe nach Prefix wird klein geschrieben, und jeder Buchstabe eines neuen „Wortes“ wird großgeschrieben
  • privaten Klassenelemente wird ein Unterstrich vorangestellt

(:cell align=left bgcolor=#EEEEEE :)

  • private Klassenelemente sollten keinen Unterstrich vorangestellt bekommen; das ist doch PHP5! (mlunzena)

(:cellnr align=left bgcolor=#EEEEEE :) Dateiformate (:cell align=left bgcolor=#EEEEEE :) (:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) E_STRICT-kompatibler Code (:cell align=left bgcolor=#EEEEEE :)

  • Der Code darf keine Fehler oder Warnungen erzeugen, wenn das Fehler-Reporting von PHP auf E_STRICT eingestellt ist.

(:cell align=left bgcolor=#EEEEEE :)

  • das dürfte kaum durchsetzbar sein.. (mlunzena)
  • vielleicht nicht für den alten code, aber auf jeden fall für alle neuen änderungen und plugins. würde das debuggen sehr vereinfachen… (mriehe)

(:cellnr align=left bgcolor=#EEEEEE :) Richtlinen zur Fehlerbehandlung (:cell align=left bgcolor=#EEEEEE :) (:cell align=left bgcolor=#EEEEEE :)

(:tableend:)

Änderungswünsche & mehr

(:table border=1 width=100% align=center cellspacing=0 :)

(:cellnr width=20% align=center bgcolor=#CCCCCC :) Feature (Name) (:cell width=50% align=center bgcolor=#CCCCCC :) Ausprägung (:cell width=30% align=center bgcolor=#CCCCCC :) Euer Kommentar (Namen)

(:cellnr align=left bgcolor=#EEEEEE :) Namenskonvention für Accessor-Methoden (chueser) (:cell align=left bgcolor=#EEEEEE :)

  • getter Methoden: get+Variablenname
  • setter Methoden: set+Variablenname
  • erster Buchstabe des Variablennamens groß schreiben

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Anzahl Klassen in einem File (chueser) (:cell align=left bgcolor=#EEEEEE :)

  • nur eine Klasse pro File (wegen Eindeutigkeit der Packages)

(:cell align=left bgcolor=#EEEEEE :)

  • Da seh ich nicht den Sinn, in Java ok, aber das ist PHP, warum sollte man das machen? Es gibt doch gar keine "import" Anweisung? (mlunzena)
  • Ich finde das sehr sinnvoll, so findet man dann auch leichter, wo die Klassen sind. (tgloeggl)
  • Ich stimme da tgloeggl vollkommen zu. (mriehe)

(:cellnr align=left bgcolor=#EEEEEE :) File-Name bei Files die eine Klasse enthalten (chueser) (:cell align=left bgcolor=#EEEEEE :)

  • Name des Files gleich dem Klassen-Namen

(:cell align=left bgcolor=#EEEEEE :)

  • In PHP gibt's doch aber auch Dateien, die keine Klassen enthalten.. Wie sollte das denn funktionieren? Grundsätzlich macht es keinen Sinn, einfach nur alles so zu machen wie in Java. Java ist nicht unbedingt immer ein Vorbild. Ansonsten sollte man eben Java nehmen. (mlunzena)
  • Hä? Alles Dateien mit der Endung .class.php enthalten genau eine Klasse, alle anderen Dateien sind normale Skripte wie bisher. (tgloeggl)
  • Ich stimme da tgloeggl vollkommen zu. (mriehe)

(:cellnr align=left bgcolor=#EEEEEE :) Regeln zur Lokalisierung (ssuchi) (:cell align=left bgcolor=#EEEEEE :)

  • sollten aus dem alten Code Style übernommen werden
  • müssen Vorrang vor Formatierungsregeln haben (z.B. Zeilenlänge), sonst kommt nur Murks bei der Übersetzung raus

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) phpDocumentor (chueser) (:cell align=left bgcolor=#EEEEEE :)

  • Dokumentation einheitlich mit phpDocumentor-Style & -Tags. (chueser)

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Sichtbarkeitsschlüsselwörter (chueser) (:cell align=left bgcolor=#EEEEEE :)

  • public, protected, private für Klassenvariablen und -methoden einsetzen.

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Paketstruktur (chueser) (:cell align=left bgcolor=#EEEEEE :)

  • Hier geht es um die Paketzugehörigkeit durch @package / @subpackage.
    • Funktionen, Konstanten and globale Variablen sind vom Filesystem in Files gruppiert, die wiederum mit @package-Tag innerhalb eines Page-Level DocBlocks in Pakete gruppiert werden.
    • Methoden und Klassenvariablen sind von PHP in Klassen gruppiert, die wiederum mit @package-Tag innerhalb eines Class-Level DocBlocks in Pakete gruppiert werden.
phpDocumentor parst die Struktur andernfalls nicht.

(:cell align=left bgcolor=#EEEEEE :)

(:tableend:)

PEAR Coding Standard

Einrückungen und Zeilenlänge

Benutzen Sie Einrückungen mit 4 Leerzeichen, keine Tabulatoren. Damit helfen Sie, Probleme zu vermeiden, die mit Diffs, Patches und anderen CVS-Funktionen entstehen.

Wir empfehlen einen Zeilenumbruch bei ca. 75 - 85 Zeichen durchzuführen, um die Lesbarkeit zu erhöhen.

Kontrollstrukturen (if, for, while, switch usw.)

Bsp für if-Kosntruktionen:

<?php
if ((condition1) || (condition2)) {
    action1;
} elseif ((condition3) && (condition4)) {
    action2;
} else {
    defaultaction;
}
?>

Kontroll-Ausdrücke sollten ein Leerzeichen zwischen den Schlüsselwörtern und der öffnenden Klammer haben, um sie von Funktionsaufrufen unterscheiden zu können.

Sie sollten unbedingt geschweifte Klammern verwenden, auch wenn sie technisch nur optional sind. Damit verbessern Sie die Lesbarkeit und vermeiden logische Fehler, wenn neue Zeilen hinzugefügt werden.

Bsp für switch-Ausdrücke:

<?php
switch (condition) {
case 1:
    action1;
    break;

case 2:
    action2;
    break;

default:
    defaultaction;
    break;
}
?>

Funktionsaufrufe

Funktionen sollten ohne Leerzeichen zwischen dem Funktionsnamen, der öffnenden Klammer und dem ersten Parameter aufgerufen werden. Leerzeichen sollten gesetzt werden zwischen Komma und jedem Parameter. Zwischen dem letzten Parameter, der schliessenden Klammer und Semikolon sollten keine Leerzeichen gesetzt werden.

Beispiel:

<?php
$var = foo($bar, $baz, $quux);
?>

Wie oben gezeigt, sollte ein Leerzeichen vor und hinter das Gleichheitszeichen gesetzt werden, wenn der Rückgabewert der Funktion einer Variable zugewiesen wird. Wenn ein Block zusammenhängender Zuweisungen durchgeführt wird, empfehlen wir mehrere Leerzeichen einzufügen, um die Lesbarkeit zu verbessern:

<?php
$short         = foo($bar);
$long_variable = foo($baz);
?>

Klassen-Definition

Die öffnende Klammer einer Klassen-Deklaration beginnt auf einer neuen Zeile:

<?php
class FooBar
{

    //... ihr Code

}
?>

Funktionsdefinitionen

Funktionsdeklarationen folgen dem „K&R-Stil“ (Programmierstil der C-Erfindern Brian W. Kernighan und Dennis Ritchie):

<?php
function fooFunction($arg1, $arg2 = '')
{
    if (condition) {
        statement;
    }
    return $val;
}
?>

Argumente mit Standardwerten werden am Ende der Argumentenliste platziert. Eine Funktion sollte immer einen aussagekräftigen Wert zurückliefern, soweit wie es möglich ist.

Beispiel:

<?php
function connect(&$dsn, $persistent = false)
{
    if (is_array($dsn)) {
        $dsninfo = &$dsn;
    } else {
        $dsninfo = DB::parseDSN($dsn);
    }

    if (!$dsninfo || !$dsninfo['phptype']) {
        return $this->raiseError();
    }

    return true;
}
?>

Kommentare

Sie müssen vollständige Inline-Dokumentation bereitstellen (Docblocks).

Sie sollten auch abseits der offziellen API-Dokumentation Kommentare im Quellcode einsetzen. Als Daumenregel gilt, wenn Sie auf einen Code-Abschnitt schauen und denken: „Wow, Ich würde nicht versuchen herauszufinden, wie es funktioniert“, sollten Sie auf jeden Fall einen Kommentar ergänzen, bevor Sie vergessen, wie es funktioniert.

Kommentare im C-Stil (/* */) und von Standard-C++ (//) sollten verwendet werden. Kommentare im Perl/shell-Stil (#) sollten Sie vermeiden.

Code einbinden

Immer wenn Sie eine Klassendatei unbedingt inkludieren müssen, dann benutzen Sie require_once. Benötigen Sie hingegen eine Datei nur bedingt, z.B. in Factory-Methoden, verwenden Sie include_once. Beide stellen sicher, dass die Datei nur einmal eingebunden wird. Beide Funktionen benutzen die gleiche Liste zur Verwaltung der bereits eingebundenen Dateien. Sie müssen sich über eine Mischung aus beiden Funktionsaufrufen keine Gedanken machen - eine Datei, die per require_once eingebunden wurde, wird nicht erneut eingebunden mit include_once.

Anmerkung: include_once und require_once sind Anweisungen, nicht Funktionen. Deshalb sollten die Dateinamen nicht in Klammern eingeschlossen werden.

PHP-Code-Tags

Benutzen Sie immer <?php ?> um Ihren PHP-Code zu markieren, niemale die Kurzform <? ?>. Die erste Variante funktioniert unabhängig vom Betriebssystem und der PHP-Konfiguration.

Kopf-Kommentare

Alle Quellcode-Dateien sollen einen „Page-level“ Docblock am Datei-Anfang besitzen und einen „Class-level“ Docblock unmittelbar vor jeder Klasse.

Beispiele:

<?php

/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */

/**
 * Short description for file
 *
 * Long description for file (if any)...
 *
 * PHP versions 4 and 5
 *
 * LICENSE: This source file is subject to version 3.0 of the PHP license
 * that is available through the world-wide-web at the following URI:
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
 * the PHP License and are unable to obtain it through the web, please
 * send a note to license@php.net so we can mail you a copy immediately.
 *
 * @category   CategoryName
 * @package    PackageName
 * @author     Original Author <author@example.com>
 * @author     Another Author <another@example.com>
 * @copyright  1997-2005 The PHP Group
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
 * @version    CVS: $Id:$
 * @link       http://pear.php.net/package/PackageName
 * @see        NetOther, Net_Sample::Net_Sample()
 * @since      File available since Release 1.2.0
 * @deprecated File deprecated in Release 2.0.0
 */ 

/*
 * Place includes, constant defines and $_GLOBAL settings here.
 * Make sure they have appropriate docblocks to avoid phpDocumentor
 * construing they are documented by the page-level docblock.
 */

/**
 * Short description for class
 *
 * Long description for class (if any)...
 *
 * @category   CategoryName
 * @package    PackageName
 * @author     Original Author <author@example.com>
 * @author     Another Author <another@example.com>
 * @copyright  1997-2005 The PHP Group
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
 * @version    Release: @package_version@
 * @link       http://pear.php.net/package/PackageName
 * @see        NetOther, Net_Sample::Net_Sample()
 * @since      Class available since Release 1.2.0
 * @deprecated Class deprecated in Release 2.0.0
 */
class Foo_Bar
{
}

?>

Erforderliche Tags

Kurzbeschriebung

Die Kurzbeschreibung muss in allen Docblocks existieren. Sie umfasst einen Satz, und sollten keinesfalls nur aus dem Namen des beschreibenden Objektes stehen.

PHP Version

Folgende Zeile muss in den Page-level-Docblock eingefügt werden. Sie beschreibt, unter welcher PHP-Version der Quellcode läuft:

  • PHP version 4
  • PHP version 5
  • PHP versions 4 and 5

@license

Sie können verschiedene Lizenzen für ihr Package verwenden. Sie müssen eine auswählen und diese sowohl im Page-level-, wie auch dem Class-level-Docblock einfügen:

  • @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
  • @license http://www.freebsd.org/copyright/freebsd-license.html BSD License (2 Clause)
  • @license http://www.debian.org/misc/bsd.license BSD License (3 Clause)
  • @license http://www.freebsd.org/copyright/license.html BSD License (4 Clause)
  • @license http://www.opensource.org/licenses/mit-license.html MIT License
  • @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
  • @license http://www.php.net/license/3_0.txt PHP License 3.0

@link

Die Link-Angabe muss im Page-level- and Class-level-Docblock erfolgen. Sie müssen den Eintrag für „PackageName“ natürlich durch den Namen Ihres Packages ersetzen. Auf diese Weise ist sicher gestellt, dass die API-Dokumentation die Links auf die Package-Homepage enthält.

  • @link http://pear.php.net/package/PackageName

@author

Es gibt keine klare Regel, wann jemand zur Liste der Quellcode-Autoren hinzugefügt werden sollte. Allgemein sollten sie substanziell beigetragen haben, ca. 10% bis 20% des Codes. Sie können Ausnahmen machen, wenn Methoden neu geschrieben wurden oder neue Logik beigesteuert wurde.

Einfache Code-Neuformatierungen oder Bug-Fixes sollten nicht zur Aufnahme in die Liste führen.

@since

Dieses Tag ist erforderlich, wenn eine Datei oder Klasse nach dem ersten Release zum Package ergänzt wurde. Verwenden Sie es nicht beim ersten Release.

@deprecated

Dieses Tag ist erforderlich, wenn eine Datei oder Klasse nicht mehr benutzt wird, aber für die Rückwärtskompatibilität noch verfügbar ist.

Optionale Tags

@copyright

Sie können dieses Tag setzen, wenn Sie Copyright-Anmerkungen ergänzen wollen. Das Format des Tags: Die vierstellige Jahreszahl bzw. bei mehreren Jahren, nur das erste und letzte Jahr getrennt mit einem Querstrich; danach der Copyright-Inhaber, also die betreffenden Personen, Firma oder z.B. die PHP Group.

Beispiele:

  • @copyright 2003 John Doe and Jennifer Buck
  • @copyright 2001-2004 John Doe
  • @copyright 1997-2004 The PHP Group
  • @copyright 2001-2004 XYZ Corporation

License Summary

If you are using the PHP License, use the summary text provided above. If another license is being used, please remove the PHP License summary. Feel free to substitute it with text appropriate to your license, though to keep things easy to locate, please preface the text with LICENSE: .

@see

Fügen Sie ein @see-Tag hinzu, wenn Sie auf andere Abschnitte in der Package-Dokumentation verweisen. Wenn Sie mehrere Einträge hinzufügen, verwenden Sie nicht mehrere Tags, sondern trennen diese in einem Tag per Komma.

Abfolge und Leerzeichen

Um die langfristige Lesbarkeit zu gewährleisten, sollten Texte und Tags dem gegebenem Beispiel folgen. Diese Festlegungen entsprechen dem JavaDoc-Standard.

Verwendung von @package_version@

Es gibt zwei Wege @package_version@ zu ersetzen. Das ist abhängig davon, ob Sie die Package-Datei package.xml von Hand erzeugen oder das Package PackageFileManager benutzen.

Wenn Sie die Datei direkt bearbeiten, ergänzen Sie ein <replace>-Tag für jede Datei. Das XML sieht dann ähnlich wie dieses aus:

<file name="Class.php">
  <replace from="@package_version@" to="version" type="package-info" />
</file>

Wenn PackageFileManager verwenden, rufen Sie addReplacement() für jede Datei auf:

<?php
$pkg->addReplacement('filename.php', 'package-info',
                     '@package_version@', 'version');
?>

Übergangsregeln

Für existierende kleine Packages

Existierende Packages mit nur wenigen Dateien sollten die DocBlöcke im nächst möglichen Release enthalten.

Für existierende große Packages

Existierende Packages mit vielen Dateien sollten die neuen DocBlöcke sobald wie möglich integrieren. Auf jeden Fall aber mit den nächsten Major-Release.

Neue und unveröffentliche Packages

Neue Packages und existierende Package, für welche noch kein Release existiert, müssen über die DocBlöcke verfügen, wenn ihr erstes Release erscheint.

CVS-Nutzung

Ergänzen Sie das $Id$-CVS-Schlüsselwort in jeder Datei.

Beispiel-URLs

Benutzen Sie example.com, example.org und example.net für alle Beispiel-URLs und Email-Adressen entsprechend RFC 2606.

Namens-Konventionen

Klassen

Verwenden Sie beschreibende Klassennamen und vermeiden Sie Abkürzungen. Klassennamen beginnen immer mit einen Großbuchstaben. Die Klassenhierarchie in PEAR spiegelt sich auch im Klassennamen wieder, jede Ebene der Hierarchie wird durch einen einzelnen Unterstrich getrennt.

Beispiele für Klassennamen:

  • Log
  • Net_Finger
  • HTML_Upload_Error

Funktionen und Methoden

Funktionen und Methoden sollten dem „Studly Caps“-Stil folgen (auch bekannt als „Bumpy Base“ oder „Camel Caps“). Funktionsnamen sollte der Package-Name vorangestellt werden, um Kollisionen mit anderen Funktionsnamen zu vermeiden. Der erste Buchstabe nach dem Prefix wird klein geschrieben, und jeder Buchstabe eines neuen „Wortes“ im Namen wird großgeschrieben.

Beispiele:

  • connect()
  • getData()
  • buildSomeWidget()
  • XML_RPC_serializeData()

Privaten Klassenelemente wird ein Unterstrich vorangestellt.

Zum Beispiel:

  • _sort()
  • _initTree()

$this->_status

Anmerkung: Unter PHP 5 gilt: Klassenelemente, welche protected sind, werden nicht mit einem Unterstrich versehen:

  • protected $somevar
  • protected function initTree()

Konstanten

Konstanten werden immer vollständig groß geschrieben, mit Unterstrichen zwischen den Worten. Ihre Namen müssen mit dem Klassen- bzw. Package-Namen beginnen. Zum Beispiel beginnen alle Konstanten des DB::-Packages mit DB_.

Anmerkung: Die Konstanten true, false und null werden als einzige Ausnahme immer klein geschrieben.

Globale Variablen

Wenn Ihr Package globale Variablen benötigt, sollte deren Name mit einem Unterstrich beginnen, gefolgt vom Package-Namen und einem weiteren Unterstrich. Zum Beispiel benutzt das PEAR-Package die globale Variable $_PEAR_destructor_object_list.

Dateiformate

Alle Skripte in PEAR müssen:

  • als ASCII gespeichert werden.
  • mit dem Zeichensatz ISO-8859-1 kodiert werden.
  • den UNIX-Konventionen folgen. „Unix-Konventionen“ bedeutet:
    • Zeilen dürfen nur mit dem Line-Feed-Zeichen (LF) enden. Das Zeichen entspricht dem Ordinal-Wert 10, Octal 012 und hexadezimal 0A. Benutzen Sie kein Carriage-Return-Zeichen (CR) wie unter Apple Macintosh-Computern oder die CRLF-Kombination unter Windows.
    • Fügen Sie ein Zeilenende-Zeichen nach dem schliessendem PHP-Tag (?>) ein. Das bedeutet, der Cursor im Editor steht eine Zeile nach dem schliessendem Tag.

E_STRICT-kompatibler Code

Jeder Code muss E_STRICT-kompatibel sein. Das heisst, er darf keine Fehler oder Warnungen erzeugen, wenn das Fehler-Reporting von PHP auf E_STRICT eingestellt ist.

Die Entwicklung existierender Packages, die dieser Konvention noch nicht entsprechen, müssen dies auch noch nicht. Erst wenn eine neue major-Version eines Packages erscheint, dann muss diese Version der E_STRICT-Konvention entsprechen.

Richtlinen zur Fehlerbehandlung

Richtlinen zur Fehlerbehandlung

Dieser Abschnitt beschreibt wie Fehler in PEAR-Packages behandelt werden sollen, die für PHP 5 und 6 entwickelt werden. Fehler werden über Exceptions abgewickelt, sie wurden mit PHP 5.0 und der Zend Engine 2 eingeführt.

Was ist ein Fehler?

Ein Fehler ist definiert als ein unerwartet, nicht korrekter Programmzustande, der nicht wieder behoben werden kann. Zur Vereinfachung dieser Definition gilt, dass die Behebung des Fehlers nicht innerhalb einer Methode möglich ist. Eine unvollständige Behebung gilt trotzdem als Behebung.

Beispiel 4-1. Eine typische Fehlersituation

<?php
/**
 * Verbinde zur angegebenen Datenbank
 *
 * @throws Example_Datasource_Exception wenn der Verbindungsaufbau fehlschlägt
 */
function connectDB($dsn) {
    $this->db =& DB::connect($dsn);
    if (DB::isError($this->db)) 
    {
        throw new Example_Datasource_Exception(
                "Unable to connect to $dsn:" . $this->db->getMessage()
        );
    }
}
?>

In diesem Beispiel soll die Methode die Verbindung mit der Datenbank mit dem gegegebenem DSN herstellen. Die Methode ruft ihrerseits nur PEAR::DB, wenn dieses Package einen Fehler wirft, kann nur eine Exception erzeugt und geworfen werden, ohne weiter Einfluß nehmen zu können.

Beispiel 4-2. Fehlerbehandlung mit Behebung

<?php
/*
 * Verbinde mit einer der möglichen Datenbanken
 *
 * @throws Example_Datasource_Exception wenn keine der gewählten
 *         Datenbank angesprochen werden konnte.
 *
 * @throws Example_Config_Exception wenn keine Datenbanken
 *         konfiguriert wurden
 */

function connect(Config $conf) 
{
    $dsns =& $conf->searchPath(array('config', 'db'));
    if ($dsns === FALSE) throw new Example_Config_Exception(
        'Unable to find config/db section in configuration.'
    );

    $dsns =& $dsns->toArray();

    foreach($dsns as $dsn) {
        try {
            $this->connectDB($dsn);
            return;
        } catch (Example_Datasource_Exception e) {
            // Warn-/Logging-Code um den Verbindungsfehler
            // aufzuzeichnen
        }
    }
    throw new Example_Datasource_Exception(
        'Unable to connect to any of the configured databases'
    );
}
?>

Das zweite Beispiel zeigt, wie eine Exception empfangen und behandelt wird. Die verwendete connectDB()-Methode kann nur einen Fehler melden, wenn die Verbindung fehlschlägt. Die übergeordnete Methode connect() hingegen weiss, dass das Objekt auch mit einer der anderen Datenbank-Verbindungen lauffähig ist. Deshalb kann der Fehler als behoben angesehen werden und die Exception wird nicht weitergeleitet.

Beispiel 4-3. Unvollständige Behebung

<?php
/**
 * loadConfig wertet die angegebene Konfiguration aus. Wenn die
 * Konfiguration unkorrekt ist, dann wird auf die Standard-
 * zurückgegriffen
 *
 */
function loadConfig(Config $conf) 
{
    try {
        $this->config = $conf->parse();
    } catch (Config_Parse_Exception e) {
        // Warn-/Logging-Code
        // Unvollständige Fehlerbehebung
        $this->config = $this->defaultConfig;
    }
}
?>

Die Fehlerbehebung führt zu Seiteneffekten, deshalb ist sie nicht vollständig. Das Programm kann weiterlaufen, die Exception gilt als behandelt und muss nicht weitergeleitet werden. Wie im vorherigen Beispiel sollte die aufgetretene Exception aber trotzdem geloggt werden oder eine andere Form der Warnung stattfinden.

Fehler-Benachrichtigung PHP 5 PEAR-Packages

Fehlerhafte Zustände in PEAR-Packages für PHP 5 müssen über Exceptions gemeldet werden. Nicht mehr verwendet werden sollten Fehlercodes oder ein PEAR_Error-Objekt. Diese Regel gilt natürlich nicht, wenn das Package kompatibel mit PHP 4 bleiben muss. In diesem Fall gelten die Konvention der PEAR Coding Standards unter PHP 4 weiter.

Eine Exception sollte immer geworfen werden, wenn ein fehlerhafter Zustand auftritt, entsprechend der Definition im vorherigen Abschnitt. Die geworfene Exception sollte genügend Informationen enthalten, um den Fehler debuggen zu können und schnell dessen Grund herauszufinden. Bedenken Sie, dass in Produktionsumgebungen keine Exception an den Endanwender durchdringen sollten. Deshalb muss man sich keine Gedanken machen über die Komplexität der Fehlermeldung.

Die Basis-Klasse PEAR_Exception enthält eine wörtliche Beschreibung des Fehlers, womit der Programmzustand beschrieben wird, der zum Fehler führte, und - optional - Execptions, die durch untergeordnete Programmaufrufe herbei geführten wurden und die ursprüngliche Ursache des Fehlers darstellen können.

Die Arten von Informationen die in einer Exception enthalten sein müssen, hängt von der Art des Fehlers ab. Es gibt drei Varianten von Exceptions:

  1. Fehler, die während der Vorabprüfung auftreten können.
  2. Fehler, die durch untergeordneten Bibliotheksaufrufe auftreten und durch Fehlercodes oder -Objekte signalisiert werden
  3. Nicht-korrigierbare Exceptions von untergeordneten Bibliotheken.

Fehler, die während der Vorabprüfung auftreten können, sollten eine Beschreibung der fehlgeschlagenen Prüfung enthalten. Wenn möglich sollte der fehlerhafte Wert mit angegeben werden.

Beispiel 4-4.

<?php
function divide($x, $y)
{
    if ($y == 0) {
        throw new Example_Aritmetic_Exception('Division by zero');
    }
}
?>

Fehler, die durch untergeordneten Bibliotheksaufrufe auftreten und durch Fehlercodes oder -Objekte signalisiert werden, sollten in Exceptions umgewandelt werden, wenn diese nicht behoben werden können. Die Fehlerbeschreibung sollte die originale Fehlerinformationen enthalten bzw. entsprechend konvertiert werden. Am Beispiel der obigen connect()-Methode:

Beispiel 4-5.

<?php
/**
 * Verbinde zur angegebenen Datenbank
 *
 * @throws Example_Datasource_Exception wenn der Verbindungsaufbau fehlschlägt
 */
function connectDB($dsn) {
    $this->db =& DB::connect($dsn);
    if (DB::isError($this->db)) {
        throw new Example_Datasource_Exception(
                "Unable to connect to $dsn:" . $this->db->getMessage()
        );
    }
}
?>

Nicht-korrigierbare Exceptions von untergeordneten Bibliotheken sollten weitergeleitet oder erneut geworfen werden. Wenn sie weitergeleitet werden soll, dann behandeln Sie die Exception nicht weiter. Wenn Sie die Exception erneut werfen, dann müssen Sie die originale Exception in der neuen Exception verpacken.

Beispiel 4-6. Eine Exception neu verpacken

<?php
function preTaxPrice($retailPrice, $taxRate) 
{
    try {
        return $this->divide($retailPrice, 1 + $taxRate);
    } catch (Example_Aritmetic_Exception e) {
        throw new Example_Tax_Exception('Invalid tax rate.', e);
    }
}
?>

Beispiel 4-7. Eine Exception weiterleiten

<?php
function preTaxPrice($retailPrice, $taxRate) 
{
    return $this->divide($retailPrice, 1 + $taxRate);
}
?>

Die Entscheidung, ob eine Exception neu verpackt oder weitergeleitet werden soll, ist eine Frage der Software-Architektur. Exceptions sollten weitergeleitet werden, ausser in zwei Fällen:

  1. Die originale Excpetion ist von einem anderen Package. Wenn diese weitergeleitet wird, dann würden Details der Implementierung nach aussen dringen.
  2. Die Methode kann nützliche Debug-Informationen ergänzen.

Exceptions und der normale Programmfluß

Exceptions sollten niemals als Bestandteil des normalen Programmflußes benutzt werden. Wenn alle Logik zur Behandlung von Exceptions entfernt würde (try-catch-Statements), dann sollte der verbliebende Code den "wahren Pfad" repräsentieren – dem Programmfluß, wenn keinerlei Fehler auftreten würden.

Diese Forderung entspricht der Erwartung, dass Exceptions nur bei fehlerhaften Zuständen geworfen werden sollten und niemals bei regulären Zuständen.

Ein Beispiel für die falsche Benutzung der Exception-Weiterleitung ist die Rückgabe eines Wertes eines rekursiven Aufrufs:

Beispiel 4-8.

<?php
/**
 * Rekursive Suche in einem Baum nach einem String
 * @throws ResultException
 */
public function search(TreeNode $node, $data)  
{
    if ($node->data === $data) {
         throw new ResultException( $node );
    } else {
         search( $node->leftChild, $data );
         search( $node->rightChild, $data );
    }
}
?>

Im Beispiel wird die ResultException benutzt, um "schnell" wieder aus der Rekursion heraus zu kommen. Das ist im Fehlerfall tatsächlich praktisch, in diesem Fall, aber nur ein Beispiel für einen faulen Programmierer. Die Klassen-Hierarchie von Exceptions

Alle Exceptions, die von Packages geworfen werden, müssen von PEAR_Exception abstammen. PEAR_Exception bietet zusätzliche Fähigkeiten, um andere Exceptions zu verpacken. Sie finden diese nicht in der obersten PHP Exception-Klasse, sind aber notwendig, um die oben gestellten Anforderungen zu erfüllen.

Zusätzlich sollte jedes PEAR-Package seine eigene Exception-Klasse definieren; der Name der Klasse entspricht dem Muster: <Package_Name>_Exception. Jede Exception sollte von dieser Klasse abgeleitet werden. Exceptions dokumentieren

Da PHP, im Gegensatz zu Java, es nicht erfordert, mögliche Exceptions in der Funktionssignatur aufzunehmen, ist deren sorgfältige Dokumentation im Methodenkopf wichtig.

Beispiel 4-9. Exceptions werden dokumentiert mit dem @throws-Schlüsselwort

<?php
/**
 * Diese Methode sucht nach Aliens.
 *
 * @return array Array von Alien-Objekten.
 * @throws AntennaBrokenException wenn die Impedanz-Leser anzeigt, dass die
 *         Antenne nicht funktioniert
 *
 * @throws AntennaInUseException wenn ein anderer Prozess die Antenne
 *         bereits benutzt
 */
public function findAliens($color = 'green');
?>

In vielen Fällen wandelt die mittlere Schicht einer Anwendung Exceptions von untergeordneten Methoden in aussagekräftiger, anwendungsspezifische Exceptions. Das sollte ebenfalls angesprochen werden:

Beispiel 4-10.

<?php
/**
 * Lade Session-Objekte in den Shared-Memory
 *
 * @throws LoadingException Jede untergeordnete IOException wird als
 *         LoadingException neu verpackt.
 */
public function loadSessionObjects();
?>

In anderen Fällen kann ihre Methode als Filter fungieren, der nur bestimmte Exceptions weiterleitet. Dann sollten Sie dokumentieren, welche Exceptions nicht von Ihrer Methode abgefangen werden.

Beispiel 4-11.

<?php
/**
 * Führt eine Reihe von Datenbankanfragen aus (atomar, nicht innerhalb einer Transaktion).
 * @throws SQLException Low-level SQL-Fehler werden direkt weitergeleitet.
 */
public function batchExecute();
?>

Exceptions als Teil der API

Exceptions spielen eine kritische Rolle in der API ihrer Bibliothek. Entwickler, die Ihre Bibliothek verwenden, sind abhängig von der angemessenen Beschreibung wo und warum Exceptions auftreten in Ihrem Package. Auch die sorgfältige Planung der Fehlermeldungen ist ein wichtiger Faktor für die Erhaltung der Rückwärts-Kompatibilität.

Da Exceptions ein integraler Bestandteil der API ihres Packages sind, darf bei Änderungen daran die Rückwärts-Kompatibilität (BC) nicht grundlos gebrochen werden.

Dinge, die zum Bruch führen:

  • Jede Änderung an Methoden, die Exceptions werfen.
  • Wenn eine Exception-Klasse verwendet wird, die höher in der Vererbungskette liegt, als die ursprüngliche. Zum Beispiel, wenn Sie in einer neueren Version eine PEAR_Exception werfen würden, in der alten aber z.B. PEAR_IOException verwendet haben.

Dinge, die nicht zum Bruch führen:

  • Wenn eine abgeleitete Klasse der originalen Exception verwendet wird. Zum Beispiel, wenn Sie in der aktuellen Version eine PEAR_IOException werfen, und in älteren Versionen PEAR_Exception. Natürlich nur unter der Voraussetzung, dass PEAR_IOException von PEAR_Exception) abgeleitet ist.

Best practices

Es gibt einige andere Dinge, die nicht vom PEAR Coding Standard betroffen sind, sondern von den persönlichen Gewohnheiten abhängen und nicht die Lesbarkeit unmittelbar berühren. Das betrifft z.B. die Frage 'Einfache oder doppelte Anführungszeichen'. Es handelt sich um Konstrukte, welche die Programmierung vereinfachen ohne konkrete Probleme zu verursachsen. Welche dieser 'üblichen' Praktiken genutzt wird, diese Entscheidung ist dem Programmierer überlassen. Wichtiger ist die konsequente Anwendung der eigenen Entscheidung in einem Package. Respektieren Sie die Entscheidung des verantwortlichen Programmierers, wenn Sie fremde Packages verändern.

Beispieldatei inklusive Docblock-Kommentaren

Der Quellcode von PEAR-Packages wird von tausenden von Menschen gelesen. Genauso kann es passieren, dass andere einmal an Ihrem Package entwicklen werden. Um es ihnen leichter zu machen, ist die Formatierung des Quellcode und der Docblöcke standarisiert. Damit können Andere Informationen einfacher finden, das sie wissen, wo sie suchen müssen.

Jeder Docblock im Beispiel enthält viele Details wie Sie die Kommentare schreiben sollten. Diese Instruktionen sind aus zwei Gründen wichtig. Erstens können Benutzer und Entwickler schneller verstehen, was Ihr Code tut. Zweitens wird auf der PEAR-Webseite die Quellcode-Dokumentation für jedes Release von jedem Package bereitgestellt und Sie sollten auch dafür sorgen, dass diese Möglichkeit sinnvoll genutzt werden kann.

Bitte achten Sie auch auf den Einsatz von vertikalen und horizontalen Leerräumen. Sie sind Bestandteil der Standards.

Die „Fold Markers“ (// {{{ und // }}}) sind optional. Wenn Sie nicht benötigt werden, entfernen Sie die Einstellung foldmethod=marker aus dem Block mit Vim-Einstellungen.

<?php

/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */

/**
 * Kurze Beschreibung des Datei-Inhalts
 *
 * Lange Beschreibung des Datei-Inhaltes, wenn erforderlich.
 *
 * PHP versions 4 and 5
 *
 * LICENSE: This source file is subject to version 3.0 of the PHP license
 * that is available through the world-wide-web at the following URI:
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
 * the PHP License and are unable to obtain it through the web, please
 * send a note to license@php.net so we can mail you a copy immediately.
 *
 * @category   CategoryName
 * @package    PackageName
 * @author     Original Author <author@example.com>
 * @author     Another Author <another@example.com>
 * @copyright  1997-2005 The PHP Group
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
 * @version    CVS: $Id:$
 * @link       http://pear.php.net/package/PackageName
 * @see        NetOther, Net_Sample::Net_Sample()
 * @since      File available since Release 1.2.0
 * @deprecated File deprecated in Release 2.0.0
 */

/**
 * Das ist ein "Docblock-Kommentar", auch bekannt als "docblock"/"Docblock"
 * Der Klassen-Docblock weiter unten enthält eine Beschreibung wie sie
 * geschrieben werden.
 */
require_once 'PEAR.php';

// {{{ constants

/**
 * Methoden geben diesen Wert im Erfolgsfall zurück.
 */
define('_NET_SAMPLE_OK', 1);

// }}}
// {{{ GLOBALS

/**
 * Die Anzahl der erzeugten Objekte
 * @global int $GLOBALS['NET_SAMPLE_Count']
 */
$GLOBALS['_NET_SAMPLE_Count'] = 0;

// }}}
// {{{ Net_Sample

/**
 * Ein Beispiel wird Code entsprechend der PEAR-Standards aussieht
 *
 * Anmerkung des Übersetzers: Quelltext-Kommentare sollten natürlich
 * durchgängig in Englisch erfolgen!
 *
 * Ein Docblock-Kommentar beginnt mit "/**" am Anfang.  Beachten Sie, das "/"
 * beginnt mit der normalen Einrückung und die Sterne darunter stehen in der
 * selben Textspalte wie der erste Stern. Der letzte Zeile des Kommentar-Blocks
 * sollte unmittelbar das zu dokumentierende Element folgen,
 * Vermeiden Sie zusätzliche Leerzeilen. Ergänzen Sie eine Leerzeile
 * zwischen Absätzen im Kommentartext, genauso zwischen Kommentartext und dem
 * ersten @-Tag. Ein Zeilenumbruch im Kommentartext sollte nach 80 Zeichen
 * erfolgen.
 *
 * Docblöcke können nur für eine begrenzte Anzahl an Elementen verwendet
 * werden (Klassen, Eigenschaften, Methoden, Konstanten, Include und
 * globale Variablen. In der Dokumentation zu phpDocumentor finden Sie mehr
 * Informationen dazu:
 * http://phpdoc.org/docs/HTMLSmartyConverter/default/phpDocumentor/tutorial_phpDocumentor.howto.pkg.html
 *
 * Der Javadoc Style Guide ist eine exzellente Quelle wie man Kommentare
 * formulieren sollte. Letztlich sind diese Informationen eine Zusammenfassung
 * davon, andererseits gibt es aber auch einige Abweichungen davon.
 * http://java.sun.com/j2se/javadoc/writingdoccomments/index.html#styleguide
 *
 * Diese erste Zeile jedes Docblocks ist eine Zusammenfassung. Sie sollte
 * genau einen Satz umfassen, ohne Punkt am Ende. Zusammenfassungen für
 * Klassen, Eigenschaften und Konstanten sollten nicht deren Namen enthalten
 *
 * Die unten aufgeführten Tag werden üblicherweise für Klassen benutzt.
 * Die Tags @category bis @version sind erforderlich. Die Übrigen
 * sollten ergänzt werden, wenn erforderlich. Verwenden Sie die Tags
 * in der Reihenfolge, wie hier aufgeführt. phpDocumentor bietet
 * weitere Tags, verwenden Sie diese, wenn erforderlich.
 *
 * @category   CategoryName
 * @package    PackageName
 * @author     Original Author <author@example.com>
 * @author     Another Author <another@example.com>
 * @copyright  1997-2005 The PHP Group
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
 * @version    Release: @package_version@
 * @link       http://pear.php.net/package/PackageName
 * @see        NetOther, Net_Sample::Net_Sample()
 * @since      Class available since Release 1.2.0
 * @deprecated Class deprecated in Release 2.0.0
 */
class Net_Sample
{
    // {{{ properties

    /**
     * Der Zustand von foo's universe
     *
     * Potentielle Werte sind 'good', 'fair', 'poor' und 'unknown'.
     *
     * @var string
     */
    var $foo = 'unknown';

    /**
     * The status of life
     *
     * Vergessen Sie nicht, dass private Elemente mit einem
     * Unterstrich beginnen müssen.
     *
     * @var bool
     * @access private
     */
    var $_good = true;

    // }}}
    // {{{ setFoo()

    /**
     * Registriert den Zustand des Foo-Universums
     *
     * Die Zusammenfassung für eine Methode sollte besser in der 3. Person 
     * Einzahl statt in der 2. Person formuliert werden.
     * Das Verb sollte am Anfang stehen.
     *
     * Die Zusammenfassung sollte mehr Informationen liefern, die über den
     * Methodennamen hinaus gehen. Die besten Methodennamen sind
     * selbst beschreibend, sie sagen was die Methode im Grunde macht.
     * Wenn die Zusammenfassung den Methodennamen nur in Form eines
     * Satzes wiederholt, liefert sie keine zusätzlichen Informationen.
     *
     * Beispiele für die Zusammenfassung:
     *   + Sets the label              (empfohlen)
     *   + Set the label               (vermeiden)
     *   + This method sets the label  (vermeiden)
     *
     * Als nächstes werden die üblichen Tags für Methoden angeführt.
     * Ein @param-Tag muss für jeden Parameter angegeben werden.
     * Die Tags @return und @access sind wahlfrei. Das @throw-Tag
     * muss angegeben werden, wenn die Methode Exceptions wirft.
     * Das Tag @static ist erforderlich, wenn die Methode statisch
     * aufgerufen werden kann. Die übrigen Tags brauchen Sie nur
     * angeben, wenn diese benötigt werden. Bitte geben Sie die
     * Tags in der Reihenfolge an, wie sie hier aufgeführt sind.
     * phpDocumentor bietet weitere Tags, benutze Sie diese, wenn
     * es sinnvoll ist.
     *
     * Das @param-Tag umfasst den Datentypen, den Parameter-Namen, gefolgt
     * von einer Beschreibung. Per Konvention sollte die Beschreibung beginnen
     * mit dem Datentyp, dem ein Artikel ("a", "an" oder "the") vorangestellt
     * werden kann. Setzen Sie zwei Leerzeichen zwischen dem Namen
     * des Parameters und seiner Beschreibung für eine bessere Lesbarkeit.
     *
     * Wenn Sie einen Satz schreiben, starten Sie nicht mit einem
     * Großbuchstaben und beenden Sie ihn nicht mit einem Punkt:
     *   + the string to be tested
     *
     * Wenn Sie mehr als einen Satz schreiben, setzen Sie einen Punkt und
     * beginnen Sie den zweiten Satz mit einem Großbuchstaben:
     *   + the string to be tested. Must use UTF-8 encoding.
     *
     * Das @return-Tag sollte den Datentyp und eine Beschreibung des
     * zurückgegebenen Wertes enthalten. Der Datentyp kann einer von PHP's
     * Datentyp sein (int, float, bool, string, array, object, resource, mixed)
     * und sollte den primär zurückgegebenen Wert enthalten. Z.B.
     * eine Methode gibt korrekterweise ein Objekt zurück und nur im
     * Fehlerfall 'false', dann sollten Sie 'object' angeben statt
     * 'mixed'. Verwenden Sie 'void' wenn nicht zurückgegeben wird.
     *
     * Hier ein Beispiel für Quellcode-Texte:
     * <code>
     * require_once 'Net/Sample.php';
     *
     * $s = new Net_Sample();
     * if (PEAR::isError($s)) {
     *     echo $s->getMessage() . "\n";
     * }
     * </code>
     *
     * Hier ein Beispiel für Nicht-PHP-Code:
     * <samp>
     * pear install net_sample
     * </samp>
     *
     * @param string $arg1  the string to quote
     * @param int    $arg2  an integer of how many problems happened.
     *                       Rücken Sie nachfolgende Zeilen in der Beschreibung
     *                       entsprechend ein.
     *
     * @return int  the integer of the set mode used. FALSE if foo
     *               foo could not be set.
     * @throws exceptionclass  [description]
     *
     * @access public
     * @static
     * @see Net_Sample::$foo, Net_Other::someMethod()
     * @since Method available since Release 1.2.0
     * @deprecated Method deprecated in Release 2.0.0
     */
    function setFoo($arg1, $arg2 = 0)
    {
        /*
         * Das ist ein "Block Kommentar". Das Format entspricht
         * den obigen Kommentaren, mit der Ausnahme, das der Kommentarbeginn
         * nur einen Stern enthält.
         * phpDocumentor wertet diese nicht aus.
         */
        if ($arg1 == 'good' || $arg1 == 'fair') {
            $this->foo = $arg1;
            return 1;
        } elseif ($arg1 == 'poor' && $arg2 > 1) {
            $this->foo = 'poor';
            return 2;
        } else {
            return false;
        }
    }

    // }}}
}

// }}}

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * c-hanging-comment-ender-p: nil
 * End:
 */

?>

(Quelle: PEAR Coding Standard, 05.02.2008)

geändert in:

G7vqcp <a href="http://zuhuhsozniys.com/">zuhuhsozniys</a>, [url=http://kspcpylceilq.com/]kspcpylceilq[/url], [link=http://ydbnntzoezxj.com/]ydbnntzoezxj[/link], http://hjewbgauswor.com/

 
 
21.02.2008 09:50 Uhr von mlunzena -
Zeile 102 hinzugefügt:
  • wieso gibt es diese vorschriften? (mlunzena)
 
 
21.02.2008 09:50 Uhr von 131.173.75.110 -
Zeile 102 hinzugefügt:
  • wieso gibt es diese vorschriften? (mlunzena)
 
 
13.02.2008 20:55 Uhr von chueser - + description E_STRICT
Zeile 185 hinzugefügt:
Zeile 186 gelöscht:
Zeile 194 hinzugefügt:
  • Der Code darf keine Fehler oder Warnungen erzeugen, wenn das Fehler-Reporting von PHP auf E_STRICT eingestellt ist.
 
 
13.02.2008 20:49 Uhr von chueser - + file name
Zeile 235 bearbeitet:

File-Name (chueser)

geändert in:

File-Name bei Files die eine Klasse enthalten (chueser)

 
 
13.02.2008 20:41 Uhr von chueser - + name
Zeile 251 bearbeitet:

phpDocumentor

geändert in:

phpDocumentor (chueser)

Zeile 257 bearbeitet:

Sichtbarkeitsschlüsselwörter

geändert in:

Sichtbarkeitsschlüsselwörter (chueser)

 
 
13.02.2008 20:40 Uhr von chueser - + name
Zeile 263 bearbeitet:

Paketstruktur

geändert in:

Paketstruktur (chueser)

 
 
13.02.2008 20:39 Uhr von chueser - + paketstruktur
Zeile 253 bearbeitet:
  • Dokumentation einheitlich mit phpDocumentor-Style & -Tags.
geändert in:
  • Dokumentation einheitlich mit phpDocumentor-Style & -Tags. (chueser)
Zeile 259 bearbeitet:

public, protected, private für Klassenvariablen und -methoden einsetzen.

geändert in:
  • public, protected, private für Klassenvariablen und -methoden einsetzen.
Zeile 263 hinzugefügt:

Paketstruktur

Zeilen 265-268 hinzugefügt:
  • Hier geht es um die Paketzugehörigkeit durch @package / @subpackage.
    • Funktionen, Konstanten and globale Variablen sind vom Filesystem in Files gruppiert, die wiederum mit @package-Tag innerhalb eines Page-Level DocBlocks in Pakete gruppiert werden.
    • Methoden und Klassenvariablen sind von PHP in Klassen gruppiert, die wiederum mit @package-Tag innerhalb eines Class-Level DocBlocks in Pakete gruppiert werden.
phpDocumentor parst die Struktur andernfalls nicht.
 
 
13.02.2008 20:22 Uhr von chueser - + new item
Zeile 253 bearbeitet:

Dokumentation einheitlich mit phpDocumentor-Style & -Tags.

geändert in:
  • Dokumentation einheitlich mit phpDocumentor-Style & -Tags.
Zeile 257 hinzugefügt:

Sichtbarkeitsschlüsselwörter

Zeile 259 hinzugefügt:

public, protected, private für Klassenvariablen und -methoden einsetzen.

Zeilen 262-264 hinzugefügt:

(:cellnr align=left bgcolor=#EEEEEE :) (:cell align=left bgcolor=#EEEEEE :) (:cell align=left bgcolor=#EEEEEE :)

 
 
13.02.2008 20:06 Uhr von chueser - + documentation
Zeilen 248-253 hinzugefügt:

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) phpDocumentor (:cell align=left bgcolor=#EEEEEE :) Dokumentation einheitlich mit phpDocumentor-Style & -Tags.

 
 
13.02.2008 19:58 Uhr von chueser - + argument
Zeilen 94-95 bearbeitet:
geändert in:
  • warum nicht? (chueser)
Zeilen 151-152 bearbeitet:
geändert in:
  • funktioniert unabhängig vom Betriebssystem und PHP-Konfiguration (s.u.) (chueser)
Zeilen 186-187 bearbeitet:
geändert in:
Zeile 192 bearbeitet:
geändert in:
Zeile 199 bearbeitet:
geändert in:
 
 
13.02.2008 19:45 Uhr von chueser - link correction
Zeilen 184-185 bearbeitet:
geändert in:
Zeile 190 bearbeitet:
geändert in:
Zeile 197 bearbeitet:
geändert in:
 
 
13.02.2008 17:56 Uhr von ssuchi -
Zeile 230 hinzugefügt:
Zeile 239 hinzugefügt:
Zeile 241 hinzugefügt:

Regeln zur Lokalisierung (ssuchi)

Zeilen 243-244 hinzugefügt:
  • sollten aus dem alten Code Style übernommen werden
  • müssen Vorrang vor Formatierungsregeln haben (z.B. Zeilenlänge), sonst kommt nur Murks bei der Übersetzung raus
Zeile 247 gelöscht:

Regeln zur Lokalisierung (ssuchi)

Zeilen 248-249 gelöscht:
  • sollten aus dem alten Code Style übernommen werden
  • müssen Vorrang vor Formatierungsregeln haben (z.B. Zeilenlänge), sonst kommt nur Murks bei der Übersetzung raus
 
 
13.02.2008 17:53 Uhr von ssuchi -
Zeile 74 gelöscht:

ile (chueser) nur eine Klasse pro File (wegen Eindeutigkeit der Packages)

Zeilen 93-94 bearbeitet:
geändert in:
  • find ich nicht gut so (ssuchi)
Zeilen 100-101 bearbeitet:
geändert in:
  • kollidiert schnell mit den Vorschriften zur Lokalisierung (ssuchi)
Zeilen 149-150 bearbeitet:
geändert in:
  • sehe ich keinen Sinn drin, bisher wird fast immer die Kurzform benutzt (ssuchi)
Zeilen 241-248 hinzugefügt:

(:cellnr align=left bgcolor=#EEEEEE :) Regeln zur Lokalisierung (ssuchi) (:cell align=left bgcolor=#EEEEEE :)

  • sollten aus dem alten Code Style übernommen werden
  • müssen Vorrang vor Formatierungsregeln haben (z.B. Zeilenlänge), sonst kommt nur Murks bei der Übersetzung raus

(:cell align=left bgcolor=#EEEEEE :)

 
 
13.02.2008 17:41 Uhr von ssuchi -
Zeilen 147-148 bearbeitet:
  • während deiner Präsentation hatten wir schon angemerkt, dass das natürlich nicht für die Templates gilt.. (mlunzena)
geändert in:
  • während deiner Präsentation hatten wir schon angemerkt, dass das natürlich nicht für die Templates gilt.. (mlunzena)
Zeilen 155-156 bearbeitet:
geändert in:
  • Finde ich sehr gut. Bitte auch einheitlich wie weiter unten beschrieben. Momentan ist „Page-level“ Docblock in vielen Dateien sehr unterschiedlich. (mriehe)
Zeilen 162-163 bearbeitet:
geändert in:
  • in diesem Fall ist wohl das SVN- Schlüsselwort gemient. (mriehe)
Zeilen 191-192 bearbeitet:
geändert in:
  • vielleicht nicht für den alten code, aber auf jeden fall für alle neuen änderungen und plugins. würde das debuggen sehr vereinfachen… (mriehe)
Zeile 227 hinzugefügt:
  • Ich stimme da tgloeggl vollkommen zu. (mriehe)
Zeile 235 hinzugefügt:
  • Ich stimme da tgloeggl vollkommen zu. (mriehe)
 
 
13.02.2008 16:16 Uhr von 134.106.67.70 -
Zeilen 155-156 bearbeitet:
geändert in:
  • Finde ich sehr gut. Bitte auch einheitlich wie weiter unten beschrieben. Momentan ist „Page-level“ Docblock in vielen Dateien sehr unterschiedlich. (mriehe)
Zeile 162 hinzugefügt:
  • in diesem Fall ist wohl das SVN- Schlüsselwort gemient. (mriehe)
 
 
13.02.2008 16:11 Uhr von 134.106.67.70 -
Zeile 225 hinzugefügt:
  • Ich stimme da tgloeggl vollkommen zu. (mriehe)
Zeile 233 hinzugefügt:
  • Ich stimme da tgloeggl vollkommen zu. (mriehe)
 
 
13.02.2008 16:09 Uhr von 134.106.67.70 -
Zeile 189 bearbeitet:

vielleicht nicht für den alten code, aber auf jeden fall für alle neuen änderungen und plugins. würde das debuggen sehr vereinfachen… (mriehe)

geändert in:
  • vielleicht nicht für den alten code, aber auf jeden fall für alle neuen änderungen und plugins. würde das debuggen sehr vereinfachen… (mriehe)
 
 
13.02.2008 16:08 Uhr von 134.106.67.70 -
Zeilen 147-148 bearbeitet:
  • während deiner Präsentation hatten wir schon angemerkt, dass das natürlich nicht für die Templates gilt.. (mlunzena)
geändert in:
  • während deiner Präsentation hatten wir schon angemerkt, dass das natürlich nicht für die Templates gilt.. (mlunzena)
Zeile 189 hinzugefügt:

vielleicht nicht für den alten code, aber auf jeden fall für alle neuen änderungen und plugins. würde das debuggen sehr vereinfachen… (mriehe)

 
 
13.02.2008 15:32 Uhr von tgloeggl -
Zeile 75 bearbeitet:
geändert in:

ile (chueser) nur eine Klasse pro File (wegen Eindeutigkeit der Packages)

Zeile 223 hinzugefügt:
  • Ich finde das sehr sinnvoll, so findet man dann auch leichter, wo die Klassen sind. (tgloeggl)
Zeile 230 hinzugefügt:
  • Hä? Alles Dateien mit der Endung .class.php enthalten genau eine Klasse, alle anderen Dateien sind normale Skripte wie bisher. (tgloeggl)
 
 
13.02.2008 15:32 Uhr von 131.173.75.18 -
Zeile 75 bearbeitet:
geändert in:

ile (chueser) nur eine Klasse pro File (wegen Eindeutigkeit der Packages)

Zeile 223 hinzugefügt:
  • Ich finde das sehr sinnvoll, so findet man dann auch leichter, wo die Klassen sind. (tgloeggl)
Zeile 230 hinzugefügt:
  • Hä? Alles Dateien mit der Endung .class.php enthalten genau eine Klasse, alle anderen Dateien sind normale Skripte wie bisher. (tgloeggl)
 
 
13.02.2008 14:30 Uhr von mlunzena -
Zeile 134 bearbeitet:
  • Als Daumenregel gilt, wenn Sie auf einen Code-Abschnitt schauen und denken: „Wow, Ich würde nicht versuchen herauszufinden, wie es funktioniert“, sollten Sie auf jeden Fall einen Kommentar ergänzen, bevor Sie vergessen, wie es funktioniert.
geändert in:
  • Als Daumenregel gilt, wenn Sie auf einen Code-Abschnitt schauen und denken: „Wow, Ich würde nicht versuchen herauszufinden, wie es funktioniert“, sollten Sie auf jeden Fall einen Kommentar ergänzen, bevor Sie vergessen, wie es funktioniert.
Zeilen 147-148 bearbeitet:
geändert in:
  • während deiner Präsentation hatten wir schon angemerkt, dass das natürlich nicht für die Templates gilt.. (mlunzena)
Zeile 152 bearbeitet:
  • Alle Quellcode-Dateien sollen einen „Page-level“ Docblock am Datei-Anfang besitzen und einen „Class-level“ Docblock unmittelbar vor jeder Klasse.
geändert in:
  • Alle Quellcode-Dateien sollen einen „Page-level“ Docblock am Datei-Anfang besitzen und einen „Class-level“ Docblock unmittelbar vor jeder Klasse.
Zeile 173 bearbeitet:
  • Funktionen und Methoden im „Camel Caps“
geändert in:
  • Funktionen und Methoden im „Camel Caps“
Zeile 175 bearbeitet:
  • erster Buchstabe nach Prefix wird klein geschrieben, und jeder Buchstabe eines neuen „Wortes“ wird großgeschrieben
geändert in:
  • erster Buchstabe nach Prefix wird klein geschrieben, und jeder Buchstabe eines neuen „Wortes“ wird großgeschrieben
Zeile 178 bearbeitet:
geändert in:
  • private Klassenelemente sollten keinen Unterstrich vorangestellt bekommen; das ist doch PHP5! (mlunzena)
Zeilen 188-189 bearbeitet:
geändert in:
  • das dürfte kaum durchsetzbar sein.. (mlunzena)
Zeile 222 bearbeitet:
geändert in:
  • Da seh ich nicht den Sinn, in Java ok, aber das ist PHP, warum sollte man das machen? Es gibt doch gar keine "import" Anweisung? (mlunzena)
Zeile 228 bearbeitet:
geändert in:
  • In PHP gibt's doch aber auch Dateien, die keine Klassen enthalten.. Wie sollte das denn funktionieren? Grundsätzlich macht es keinen Sinn, einfach nur alles so zu machen wie in Java. Java ist nicht unbedingt immer ein Vorbild. Ansonsten sollte man eben Java nehmen. (mlunzena)
Zeilen 322-323 bearbeitet:

Funktionsdeklarationen folgen dem „K&R-Stil“ (Programmierstil der C-Erfindern Brian W. Kernighan und Dennis Ritchie):

geändert in:

Funktionsdeklarationen folgen dem „K&R-Stil“ (Programmierstil der C-Erfindern Brian W. Kernighan und Dennis Ritchie):

Zeilen 361-362 bearbeitet:

Sie sollten auch abseits der offziellen API-Dokumentation Kommentare im Quellcode einsetzen. Als Daumenregel gilt, wenn Sie auf einen Code-Abschnitt schauen und denken: „Wow, Ich würde nicht versuchen herauszufinden, wie es funktioniert“, sollten Sie auf jeden Fall einen Kommentar ergänzen, bevor Sie vergessen, wie es funktioniert.

geändert in:

Sie sollten auch abseits der offziellen API-Dokumentation Kommentare im Quellcode einsetzen. Als Daumenregel gilt, wenn Sie auf einen Code-Abschnitt schauen und denken: „Wow, Ich würde nicht versuchen herauszufinden, wie es funktioniert“, sollten Sie auf jeden Fall einen Kommentar ergänzen, bevor Sie vergessen, wie es funktioniert.

Zeilen 383-384 bearbeitet:

Alle Quellcode-Dateien sollen einen „Page-level“ Docblock am Datei-Anfang besitzen und einen „Class-level“ Docblock unmittelbar vor jeder Klasse.

geändert in:

Alle Quellcode-Dateien sollen einen „Page-level“ Docblock am Datei-Anfang besitzen und einen „Class-level“ Docblock unmittelbar vor jeder Klasse.

Zeilen 474-475 bearbeitet:

Die Link-Angabe muss im Page-level- and Class-level-Docblock erfolgen. Sie müssen den Eintrag für „PackageName“ natürlich durch den Namen Ihres Packages ersetzen. Auf diese Weise ist sicher gestellt, dass die API-Dokumentation die Links auf die Package-Homepage enthält.

geändert in:

Die Link-Angabe muss im Page-level- and Class-level-Docblock erfolgen. Sie müssen den Eintrag für „PackageName“ natürlich durch den Namen Ihres Packages ersetzen. Auf diese Weise ist sicher gestellt, dass die API-Dokumentation die Links auf die Package-Homepage enthält.

Zeilen 577-578 bearbeitet:

Funktionen und Methoden sollten dem „Studly Caps“-Stil folgen (auch bekannt als „Bumpy Base“ oder „Camel Caps“). Funktionsnamen sollte der Package-Name vorangestellt werden, um Kollisionen mit anderen Funktionsnamen zu vermeiden. Der erste Buchstabe nach dem Prefix wird klein geschrieben, und jeder Buchstabe eines neuen „Wortes“ im Namen wird großgeschrieben.

geändert in:

Funktionen und Methoden sollten dem „Studly Caps“-Stil folgen (auch bekannt als „Bumpy Base“ oder „Camel Caps“). Funktionsnamen sollte der Package-Name vorangestellt werden, um Kollisionen mit anderen Funktionsnamen zu vermeiden. Der erste Buchstabe nach dem Prefix wird klein geschrieben, und jeder Buchstabe eines neuen „Wortes“ im Namen wird großgeschrieben.

Zeile 620 bearbeitet:
  • den UNIX-Konventionen folgen. „Unix-Konventionen“ bedeutet:
geändert in:
  • den UNIX-Konventionen folgen. „Unix-Konventionen“ bedeutet:
Zeile 913 bearbeitet:

Die „Fold Markers“ (// {{{ und // }}}) sind optional. Wenn Sie nicht benötigt werden, entfernen Sie die Einstellung foldmethod=marker aus dem Block mit Vim-Einstellungen.

geändert in:

Die „Fold Markers“ (// {{{ und // }}}) sind optional. Wenn Sie nicht benötigt werden, entfernen Sie die Einstellung foldmethod=marker aus dem Block mit Vim-Einstellungen.

 
 
13.02.2008 14:29 Uhr von 84.61.137.105 -
Zeile 134 bearbeitet:
  • Als Daumenregel gilt, wenn Sie auf einen Code-Abschnitt schauen und denken: „Wow, Ich würde nicht versuchen herauszufinden, wie es funktioniert“, sollten Sie auf jeden Fall einen Kommentar ergänzen, bevor Sie vergessen, wie es funktioniert.
geändert in:
  • Als Daumenregel gilt, wenn Sie auf einen Code-Abschnitt schauen und denken: „Wow, Ich würde nicht versuchen herauszufinden, wie es funktioniert“, sollten Sie auf jeden Fall einen Kommentar ergänzen, bevor Sie vergessen, wie es funktioniert.
Zeilen 147-148 bearbeitet:
geändert in:
  • während deiner Präsentation hatten wir schon angemerkt, dass das natürlich nicht für die Templates gilt.. (mlunzena)
Zeile 152 bearbeitet:
  • Alle Quellcode-Dateien sollen einen „Page-level“ Docblock am Datei-Anfang besitzen und einen „Class-level“ Docblock unmittelbar vor jeder Klasse.
geändert in:
  • Alle Quellcode-Dateien sollen einen „Page-level“ Docblock am Datei-Anfang besitzen und einen „Class-level“ Docblock unmittelbar vor jeder Klasse.
Zeile 173 bearbeitet:
  • Funktionen und Methoden im „Camel Caps“
geändert in:
  • Funktionen und Methoden im „Camel Caps“
Zeile 175 bearbeitet:
  • erster Buchstabe nach Prefix wird klein geschrieben, und jeder Buchstabe eines neuen „Wortes“ wird großgeschrieben
geändert in:
  • erster Buchstabe nach Prefix wird klein geschrieben, und jeder Buchstabe eines neuen „Wortes“ wird großgeschrieben
Zeile 178 bearbeitet:
geändert in:
  • private Klassenelemente sollten keinen Unterstrich vorangestellt bekommen; das ist doch PHP5! (mlunzena)
Zeilen 188-189 bearbeitet:
geändert in:
  • das dürfte kaum durchsetzbar sein.. (mlunzena)
Zeile 222 bearbeitet:
geändert in:
  • Da seh ich nicht den Sinn, in Java ok, aber das ist PHP, warum sollte man das machen? Es gibt doch gar keine "import" Anweisung? (mlunzena)
Zeile 228 bearbeitet:
geändert in:
  • In PHP gibt's doch aber auch Dateien, die keine Klassen enthalten.. Wie sollte das denn funktionieren? Grundsätzlich macht es keinen Sinn, einfach nur alles so zu machen wie in Java. Java ist nicht unbedingt immer ein Vorbild. Ansonsten sollte man eben Java nehmen. (mlunzena)
Zeilen 322-323 bearbeitet:

Funktionsdeklarationen folgen dem „K&R-Stil“ (Programmierstil der C-Erfindern Brian W. Kernighan und Dennis Ritchie):

geändert in:

Funktionsdeklarationen folgen dem „K&R-Stil“ (Programmierstil der C-Erfindern Brian W. Kernighan und Dennis Ritchie):

Zeilen 361-362 bearbeitet:

Sie sollten auch abseits der offziellen API-Dokumentation Kommentare im Quellcode einsetzen. Als Daumenregel gilt, wenn Sie auf einen Code-Abschnitt schauen und denken: „Wow, Ich würde nicht versuchen herauszufinden, wie es funktioniert“, sollten Sie auf jeden Fall einen Kommentar ergänzen, bevor Sie vergessen, wie es funktioniert.

geändert in:

Sie sollten auch abseits der offziellen API-Dokumentation Kommentare im Quellcode einsetzen. Als Daumenregel gilt, wenn Sie auf einen Code-Abschnitt schauen und denken: „Wow, Ich würde nicht versuchen herauszufinden, wie es funktioniert“, sollten Sie auf jeden Fall einen Kommentar ergänzen, bevor Sie vergessen, wie es funktioniert.

Zeilen 383-384 bearbeitet:

Alle Quellcode-Dateien sollen einen „Page-level“ Docblock am Datei-Anfang besitzen und einen „Class-level“ Docblock unmittelbar vor jeder Klasse.

geändert in:

Alle Quellcode-Dateien sollen einen „Page-level“ Docblock am Datei-Anfang besitzen und einen „Class-level“ Docblock unmittelbar vor jeder Klasse.

Zeilen 474-475 bearbeitet:

Die Link-Angabe muss im Page-level- and Class-level-Docblock erfolgen. Sie müssen den Eintrag für „PackageName“ natürlich durch den Namen Ihres Packages ersetzen. Auf diese Weise ist sicher gestellt, dass die API-Dokumentation die Links auf die Package-Homepage enthält.

geändert in:

Die Link-Angabe muss im Page-level- and Class-level-Docblock erfolgen. Sie müssen den Eintrag für „PackageName“ natürlich durch den Namen Ihres Packages ersetzen. Auf diese Weise ist sicher gestellt, dass die API-Dokumentation die Links auf die Package-Homepage enthält.

Zeilen 577-578 bearbeitet:

Funktionen und Methoden sollten dem „Studly Caps“-Stil folgen (auch bekannt als „Bumpy Base“ oder „Camel Caps“). Funktionsnamen sollte der Package-Name vorangestellt werden, um Kollisionen mit anderen Funktionsnamen zu vermeiden. Der erste Buchstabe nach dem Prefix wird klein geschrieben, und jeder Buchstabe eines neuen „Wortes“ im Namen wird großgeschrieben.

geändert in:

Funktionen und Methoden sollten dem „Studly Caps“-Stil folgen (auch bekannt als „Bumpy Base“ oder „Camel Caps“). Funktionsnamen sollte der Package-Name vorangestellt werden, um Kollisionen mit anderen Funktionsnamen zu vermeiden. Der erste Buchstabe nach dem Prefix wird klein geschrieben, und jeder Buchstabe eines neuen „Wortes“ im Namen wird großgeschrieben.

Zeile 620 bearbeitet:
  • den UNIX-Konventionen folgen. „Unix-Konventionen“ bedeutet:
geändert in:
  • den UNIX-Konventionen folgen. „Unix-Konventionen“ bedeutet:
Zeile 913 bearbeitet:

Die „Fold Markers“ (// {{{ und // }}}) sind optional. Wenn Sie nicht benötigt werden, entfernen Sie die Einstellung foldmethod=marker aus dem Block mit Vim-Einstellungen.

geändert in:

Die „Fold Markers“ (// {{{ und // }}}) sind optional. Wenn Sie nicht benötigt werden, entfernen Sie die Einstellung foldmethod=marker aus dem Block mit Vim-Einstellungen.

 
 
08.02.2008 14:53 Uhr von chueser -
Zeilen 4-7 bearbeitet:
geändert in:
Zeilen 27-28 gelöscht:
Zeilen 31-76 hinzugefügt:

Einleitung

Die Einhaltung eines Coding Standards ist ein wichtiger Bestandteil guter Projektarbeit. Gerade in Open Source Projekten mit vielen Entwicklern wird damit gewährleistet, dass Source Code eine hohe Qualität erhält/behält, weniger Bugs enthält, und einfacher zu warten ist.

Darüber hinaus gibt es jedoch auch andere wichtige Faktoren:

  • Kommunikation
  • funktionierender Code
  • übersichtlicher Code
  • Module und Modultests
  • Wiederverwendbarkeit des Codes
  • einfache Wartung des Codes
  • Code, der leicht zu erweitern ist
  • Unterstützung von Refactoring

um nur einige zu nennen. Ein Coding Standard unterstützt alle genannten Punkte. Neue Entwickler können sich schnell einarbeiten, denn wenn jeder den Code des anderen versteht, kann man auch schnell Bug-Fixes vornehmen oder Module des anderen verwenden ohne das Rad neu zu erfinden.

Um diese Ziele zu erreichen, muss eine PHP-Applikation:

  • leicht zu lesen sein
  • leicht verständlich sein
  • gut dokumentiert sein
  • durch verschiedene Programmierer wartbar
  • frei von typischen Fehlern

sein. Im besten Falle kann sogar der Anwender die Module der PHP-Applikation verstehen und weiter verwenden.

Das Ziel von leicht verständlichem Source-Code ist erreicht, wenn jedes Mitglied des Teams, jedes Modul aus dem Stehgreif erklären kann. Nicht zuletzt soll jede Arbeit am Projekt, dem Code und der Dokumentation Spaß machen. Je höher der Frustfaktor ist, je unübersichtlicher Strukturen und Code sind, desto höher ist die Wahrscheinlichkeit, das die Arbeit keinen Spaß mehr macht. Das gilt es auf jeden Fall zu verhindern.

Wenn sich ein Projekt an Coding Standards hält, dann sind einige gute Effekte zu beobachten:

  • Entwickler können in jeden Code hineienschauen und sofort heraus finden was dort vor sich geht.
  • Die Lebenszeit eines Softwareprojektes wird verlängert und überlebt die Lebenszeit der erfahrenen Entwickler.
  • Neue Leute können sich schnell einarbeiten.
  • PHP Einsteiger brauchen keinen persönlichen Style enwickeln und diesen bis zum bitteren Ende verteidigen.
  • PHP Einsteiger werden davor bewahrt die gleichen Fehler wieder und wieder zu machen.
  • In konsistenten Umgebungen werden weniger Fehler gemacht.

Ich freue mich auf eine früchtetragende Diskussion mit guten Ergebnissen hinsichtlich der Verwirklichung des StudIP Coding Standards.

PEAR Coding Standard
Note: Sehr zu empfehlen!

Zeile 195 bearbeitet:

geändert in:

 
 
08.02.2008 14:51 Uhr von chueser - Einleitung ergänzt
Zeilen 4-7 bearbeitet:
geändert in:
Zeilen 27-28 gelöscht:
Zeilen 31-76 hinzugefügt:

Einleitung

Die Einhaltung eines Coding Standards ist ein wichtiger Bestandteil guter Projektarbeit. Gerade in Open Source Projekten mit vielen Entwicklern wird damit gewährleistet, dass Source Code eine hohe Qualität erhält/behält, weniger Bugs enthält, und einfacher zu warten ist.

Darüber hinaus gibt es jedoch auch andere wichtige Faktoren:

  • Kommunikation
  • funktionierender Code
  • übersichtlicher Code
  • Module und Modultests
  • Wiederverwendbarkeit des Codes
  • einfache Wartung des Codes
  • Code, der leicht zu erweitern ist
  • Unterstützung von Refactoring

um nur einige zu nennen. Ein Coding Standard unterstützt alle genannten Punkte. Neue Entwickler können sich schnell einarbeiten, denn wenn jeder den Code des anderen versteht, kann man auch schnell Bug-Fixes vornehmen oder Module des anderen verwenden ohne das Rad neu zu erfinden.

Um diese Ziele zu erreichen, muss eine PHP-Applikation:

  • leicht zu lesen sein
  • leicht verständlich sein
  • gut dokumentiert sein
  • durch verschiedene Programmierer wartbar
  • frei von typischen Fehlern

sein. Im besten Falle kann sogar der Anwender die Module der PHP-Applikation verstehen und weiter verwenden.

Das Ziel von leicht verständlichem Source-Code ist erreicht, wenn jedes Mitglied des Teams, jedes Modul aus dem Stehgreif erklären kann. Nicht zuletzt soll jede Arbeit am Projekt, dem Code und der Dokumentation Spaß machen. Je höher der Frustfaktor ist, je unübersichtlicher Strukturen und Code sind, desto höher ist die Wahrscheinlichkeit, das die Arbeit keinen Spaß mehr macht. Das gilt es auf jeden Fall zu verhindern.

Wenn sich ein Projekt an Coding Standards hält, dann sind einige gute Effekte zu beobachten:

  • Entwickler können in jeden Code hineienschauen und sofort heraus finden was dort vor sich geht.
  • Die Lebenszeit eines Softwareprojektes wird verlängert und überlebt die Lebenszeit der erfahrenen Entwickler.
  • Neue Leute können sich schnell einarbeiten.
  • PHP Einsteiger brauchen keinen persönlichen Style enwickeln und diesen bis zum bitteren Ende verteidigen.
  • PHP Einsteiger werden davor bewahrt die gleichen Fehler wieder und wieder zu machen.
  • In konsistenten Umgebungen werden weniger Fehler gemacht.

Ich freue mich auf eine früchtetragende Diskussion mit guten Ergebnissen hinsichtlich der Verwirklichung des StudIP Coding Standards.

PEAR Coding Standard
Note: Sehr zu empfehlen!

Zeile 195 bearbeitet:

geändert in:

 
 
08.02.2008 13:41 Uhr von chueser -
Zeilen 1-1116 hinzugefügt:

Vorschlag für einen StudIP Coding Standard: PEAR Coding Standard

Diskussion über den PEAR Coding Standard

Zusammenfassung
Änderungswünsche & mehr

Inhaltsverzeichnis: PEAR Coding Standard

Einrückungen und Zeilenlänge
Kontrollstrukturen
Funktionsaufrufe
Klassen-Definition
Funktionsdefinitionen
Kommentare
Code einbinden
PHP-Code-Tags
Kopf-Kommentare
CVS-Nutzung
Beispiel-URLs
Namens-Konventionen
Dateiformate
E_STRICT-kompatibler Code
Richtlinen zur Fehlerbehandlung
Best practices
Beispieldatei inklusive Docblock-Kommentaren

Diskussion über den PEAR Coding Standard

Zusammenfassung

(:table border=1 width=100% align=center cellspacing=0 :)

(:cellnr width=20% align=center bgcolor=#CCCCCC :) Feature (:cell width=50% align=center bgcolor=#CCCCCC :) Ausprägung (:cell width=30% align=center bgcolor=#CCCCCC :) Euer Kommentar (mit Namen bitte)

(:cellnr align=left bgcolor=#EEEEEE :) Einrückungen (:cell align=left bgcolor=#EEEEEE :)

  • 4 Leerzeichen, keine Tabulatoren

(:cell align=left bgcolor=#EEEEEE :)

  • find ich gut so (chueser)

(:cellnr align=left bgcolor=#EEEEEE :) Zeilenlänge (:cell align=left bgcolor=#EEEEEE :)

  • ca. 75 - 85 Zeichen

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Kontrollstrukturen (:cell align=left bgcolor=#EEEEEE :)

  • Leerzeichen zwischen den Schlüsselwörtern und der öffnenden Klammer
  • immer geschweifte Klammern verwenden
  • öffnende geschweifte Klammer in gleicher Zeile

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Funktionsaufrufe (:cell align=left bgcolor=#EEEEEE :)

  • kein Leerzeichen zwischen dem Funktionsnamen, der öffnenden Klammer und dem ersten Parameter

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Klassen-Definition (:cell align=left bgcolor=#EEEEEE :)

  • öffnende Klammer einer Klassen-Deklaration beginnt auf einer neuen Zeile

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Funktionsdefinitionen (:cell align=left bgcolor=#EEEEEE :)

  • öffnende Klammer einer Funktionsdefinition beginnt auf einer neuen Zeile
  • Argumente mit Standardwerten werden am Ende der Argumentenliste platziert
  • wenn möglich, immer einen aussagekräftigen Wert zurückliefern

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Kommentare (:cell align=left bgcolor=#EEEEEE :)

  • vollständige Inline-Dokumentation (Docblocks): File, Includes, Konstanten, Variablen, Methoden, Klasse
  • unbedingt (!) auch abseits der offziellen API-Dokumentation Kommentare im Quellcode einsetzen
  • Als Daumenregel gilt, wenn Sie auf einen Code-Abschnitt schauen und denken: „Wow, Ich würde nicht versuchen herauszufinden, wie es funktioniert“, sollten Sie auf jeden Fall einen Kommentar ergänzen, bevor Sie vergessen, wie es funktioniert.

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Code einbinden (:cell align=left bgcolor=#EEEEEE :) (:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) PHP-Code-Tags (:cell align=left bgcolor=#EEEEEE :)

  • immer die Langform <?php ?> benutzen

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Kopf-Kommentare (:cell align=left bgcolor=#EEEEEE :)

  • Alle Quellcode-Dateien sollen einen „Page-level“ Docblock am Datei-Anfang besitzen und einen „Class-level“ Docblock unmittelbar vor jeder Klasse.
  • Docblock = short decription + long description + tag list

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) CVS-Nutzung (:cell align=left bgcolor=#EEEEEE :)

  • $Id$-CVS-Schlüsselwort in jede Datei.

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Beispiel-URLs (:cell align=left bgcolor=#EEEEEE :) (:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Namens-Konventionen (:cell align=left bgcolor=#EEEEEE :)

  • beschreibende Klassennamen und Abkürzungen vermeiden
  • Klassennamen beginnen immer mit einen Großbuchstaben
  • Klassenhierarchie spiegelt sich im Klassennamen wieder, jede Ebene der Hierarchie wird durch einen einzelnen Unterstrich getrennt
  • Funktionen und Methoden im „Camel Caps“
  • Funktionsnamen sollte der Package-Name vorangestellt werden
  • erster Buchstabe nach Prefix wird klein geschrieben, und jeder Buchstabe eines neuen „Wortes“ wird großgeschrieben
  • privaten Klassenelemente wird ein Unterstrich vorangestellt

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Dateiformate (:cell align=left bgcolor=#EEEEEE :) (:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) E_STRICT-kompatibler Code (:cell align=left bgcolor=#EEEEEE :) (:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Richtlinen zur Fehlerbehandlung (:cell align=left bgcolor=#EEEEEE :) (:cell align=left bgcolor=#EEEEEE :)

(:tableend:)

Änderungswünsche & mehr

(:table border=1 width=100% align=center cellspacing=0 :)

(:cellnr width=20% align=center bgcolor=#CCCCCC :) Feature (Name) (:cell width=50% align=center bgcolor=#CCCCCC :) Ausprägung (:cell width=30% align=center bgcolor=#CCCCCC :) Euer Kommentar (Namen)

(:cellnr align=left bgcolor=#EEEEEE :) Namenskonvention für Accessor-Methoden (chueser) (:cell align=left bgcolor=#EEEEEE :)

  • getter Methoden: get+Variablenname
  • setter Methoden: set+Variablenname
  • erster Buchstabe des Variablennamens groß schreiben

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Anzahl Klassen in einem File (chueser) (:cell align=left bgcolor=#EEEEEE :)

  • nur eine Klasse pro File (wegen Eindeutigkeit der Packages)

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) File-Name (chueser) (:cell align=left bgcolor=#EEEEEE :)

  • Name des Files gleich dem Klassen-Namen

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) (:cell align=left bgcolor=#EEEEEE :) (:cell align=left bgcolor=#EEEEEE :)

(:tableend:)

PEAR Coding Standard

Einrückungen und Zeilenlänge

Benutzen Sie Einrückungen mit 4 Leerzeichen, keine Tabulatoren. Damit helfen Sie, Probleme zu vermeiden, die mit Diffs, Patches und anderen CVS-Funktionen entstehen.

Wir empfehlen einen Zeilenumbruch bei ca. 75 - 85 Zeichen durchzuführen, um die Lesbarkeit zu erhöhen.

Kontrollstrukturen (if, for, while, switch usw.)

Bsp für if-Kosntruktionen:

<?php
if ((condition1) || (condition2)) {
    action1;
} elseif ((condition3) && (condition4)) {
    action2;
} else {
    defaultaction;
}
?>

Kontroll-Ausdrücke sollten ein Leerzeichen zwischen den Schlüsselwörtern und der öffnenden Klammer haben, um sie von Funktionsaufrufen unterscheiden zu können.

Sie sollten unbedingt geschweifte Klammern verwenden, auch wenn sie technisch nur optional sind. Damit verbessern Sie die Lesbarkeit und vermeiden logische Fehler, wenn neue Zeilen hinzugefügt werden.

Bsp für switch-Ausdrücke:

<?php
switch (condition) {
case 1:
    action1;
    break;

case 2:
    action2;
    break;

default:
    defaultaction;
    break;
}
?>

Funktionsaufrufe

Funktionen sollten ohne Leerzeichen zwischen dem Funktionsnamen, der öffnenden Klammer und dem ersten Parameter aufgerufen werden. Leerzeichen sollten gesetzt werden zwischen Komma und jedem Parameter. Zwischen dem letzten Parameter, der schliessenden Klammer und Semikolon sollten keine Leerzeichen gesetzt werden.

Beispiel:

<?php
$var = foo($bar, $baz, $quux);
?>

Wie oben gezeigt, sollte ein Leerzeichen vor und hinter das Gleichheitszeichen gesetzt werden, wenn der Rückgabewert der Funktion einer Variable zugewiesen wird. Wenn ein Block zusammenhängender Zuweisungen durchgeführt wird, empfehlen wir mehrere Leerzeichen einzufügen, um die Lesbarkeit zu verbessern:

<?php
$short         = foo($bar);
$long_variable = foo($baz);
?>

Klassen-Definition

Die öffnende Klammer einer Klassen-Deklaration beginnt auf einer neuen Zeile:

<?php
class FooBar
{

    //... ihr Code

}
?>

Funktionsdefinitionen

Funktionsdeklarationen folgen dem „K&R-Stil“ (Programmierstil der C-Erfindern Brian W. Kernighan und Dennis Ritchie):

<?php
function fooFunction($arg1, $arg2 = '')
{
    if (condition) {
        statement;
    }
    return $val;
}
?>

Argumente mit Standardwerten werden am Ende der Argumentenliste platziert. Eine Funktion sollte immer einen aussagekräftigen Wert zurückliefern, soweit wie es möglich ist.

Beispiel:

<?php
function connect(&$dsn, $persistent = false)
{
    if (is_array($dsn)) {
        $dsninfo = &$dsn;
    } else {
        $dsninfo = DB::parseDSN($dsn);
    }

    if (!$dsninfo || !$dsninfo['phptype']) {
        return $this->raiseError();
    }

    return true;
}
?>

Kommentare

Sie müssen vollständige Inline-Dokumentation bereitstellen (Docblocks).

Sie sollten auch abseits der offziellen API-Dokumentation Kommentare im Quellcode einsetzen. Als Daumenregel gilt, wenn Sie auf einen Code-Abschnitt schauen und denken: „Wow, Ich würde nicht versuchen herauszufinden, wie es funktioniert“, sollten Sie auf jeden Fall einen Kommentar ergänzen, bevor Sie vergessen, wie es funktioniert.

Kommentare im C-Stil (/* */) und von Standard-C++ (//) sollten verwendet werden. Kommentare im Perl/shell-Stil (#) sollten Sie vermeiden.

Code einbinden

Immer wenn Sie eine Klassendatei unbedingt inkludieren müssen, dann benutzen Sie require_once. Benötigen Sie hingegen eine Datei nur bedingt, z.B. in Factory-Methoden, verwenden Sie include_once. Beide stellen sicher, dass die Datei nur einmal eingebunden wird. Beide Funktionen benutzen die gleiche Liste zur Verwaltung der bereits eingebundenen Dateien. Sie müssen sich über eine Mischung aus beiden Funktionsaufrufen keine Gedanken machen - eine Datei, die per require_once eingebunden wurde, wird nicht erneut eingebunden mit include_once.

Anmerkung: include_once und require_once sind Anweisungen, nicht Funktionen. Deshalb sollten die Dateinamen nicht in Klammern eingeschlossen werden.

PHP-Code-Tags

Benutzen Sie immer <?php ?> um Ihren PHP-Code zu markieren, niemale die Kurzform <? ?>. Die erste Variante funktioniert unabhängig vom Betriebssystem und der PHP-Konfiguration.

Kopf-Kommentare

Alle Quellcode-Dateien sollen einen „Page-level“ Docblock am Datei-Anfang besitzen und einen „Class-level“ Docblock unmittelbar vor jeder Klasse.

Beispiele:

<?php

/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */

/**
 * Short description for file
 *
 * Long description for file (if any)...
 *
 * PHP versions 4 and 5
 *
 * LICENSE: This source file is subject to version 3.0 of the PHP license
 * that is available through the world-wide-web at the following URI:
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
 * the PHP License and are unable to obtain it through the web, please
 * send a note to license@php.net so we can mail you a copy immediately.
 *
 * @category   CategoryName
 * @package    PackageName
 * @author     Original Author <author@example.com>
 * @author     Another Author <another@example.com>
 * @copyright  1997-2005 The PHP Group
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
 * @version    CVS: $Id:$
 * @link       http://pear.php.net/package/PackageName
 * @see        NetOther, Net_Sample::Net_Sample()
 * @since      File available since Release 1.2.0
 * @deprecated File deprecated in Release 2.0.0
 */ 

/*
 * Place includes, constant defines and $_GLOBAL settings here.
 * Make sure they have appropriate docblocks to avoid phpDocumentor
 * construing they are documented by the page-level docblock.
 */

/**
 * Short description for class
 *
 * Long description for class (if any)...
 *
 * @category   CategoryName
 * @package    PackageName
 * @author     Original Author <author@example.com>
 * @author     Another Author <another@example.com>
 * @copyright  1997-2005 The PHP Group
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
 * @version    Release: @package_version@
 * @link       http://pear.php.net/package/PackageName
 * @see        NetOther, Net_Sample::Net_Sample()
 * @since      Class available since Release 1.2.0
 * @deprecated Class deprecated in Release 2.0.0
 */
class Foo_Bar
{
}

?>

Erforderliche Tags

Kurzbeschriebung

Die Kurzbeschreibung muss in allen Docblocks existieren. Sie umfasst einen Satz, und sollten keinesfalls nur aus dem Namen des beschreibenden Objektes stehen.

PHP Version

Folgende Zeile muss in den Page-level-Docblock eingefügt werden. Sie beschreibt, unter welcher PHP-Version der Quellcode läuft:

  • PHP version 4
  • PHP version 5
  • PHP versions 4 and 5

@license

Sie können verschiedene Lizenzen für ihr Package verwenden. Sie müssen eine auswählen und diese sowohl im Page-level-, wie auch dem Class-level-Docblock einfügen:

  • @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
  • @license http://www.freebsd.org/copyright/freebsd-license.html BSD License (2 Clause)
  • @license http://www.debian.org/misc/bsd.license BSD License (3 Clause)
  • @license http://www.freebsd.org/copyright/license.html BSD License (4 Clause)
  • @license http://www.opensource.org/licenses/mit-license.html MIT License
  • @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
  • @license http://www.php.net/license/3_0.txt PHP License 3.0

@link

Die Link-Angabe muss im Page-level- and Class-level-Docblock erfolgen. Sie müssen den Eintrag für „PackageName“ natürlich durch den Namen Ihres Packages ersetzen. Auf diese Weise ist sicher gestellt, dass die API-Dokumentation die Links auf die Package-Homepage enthält.

  • @link http://pear.php.net/package/PackageName

@author

Es gibt keine klare Regel, wann jemand zur Liste der Quellcode-Autoren hinzugefügt werden sollte. Allgemein sollten sie substanziell beigetragen haben, ca. 10% bis 20% des Codes. Sie können Ausnahmen machen, wenn Methoden neu geschrieben wurden oder neue Logik beigesteuert wurde.

Einfache Code-Neuformatierungen oder Bug-Fixes sollten nicht zur Aufnahme in die Liste führen.

@since

Dieses Tag ist erforderlich, wenn eine Datei oder Klasse nach dem ersten Release zum Package ergänzt wurde. Verwenden Sie es nicht beim ersten Release.

@deprecated

Dieses Tag ist erforderlich, wenn eine Datei oder Klasse nicht mehr benutzt wird, aber für die Rückwärtskompatibilität noch verfügbar ist.

Optionale Tags

@copyright

Sie können dieses Tag setzen, wenn Sie Copyright-Anmerkungen ergänzen wollen. Das Format des Tags: Die vierstellige Jahreszahl bzw. bei mehreren Jahren, nur das erste und letzte Jahr getrennt mit einem Querstrich; danach der Copyright-Inhaber, also die betreffenden Personen, Firma oder z.B. die PHP Group.

Beispiele:

  • @copyright 2003 John Doe and Jennifer Buck
  • @copyright 2001-2004 John Doe
  • @copyright 1997-2004 The PHP Group
  • @copyright 2001-2004 XYZ Corporation

License Summary

If you are using the PHP License, use the summary text provided above. If another license is being used, please remove the PHP License summary. Feel free to substitute it with text appropriate to your license, though to keep things easy to locate, please preface the text with LICENSE: .

@see

Fügen Sie ein @see-Tag hinzu, wenn Sie auf andere Abschnitte in der Package-Dokumentation verweisen. Wenn Sie mehrere Einträge hinzufügen, verwenden Sie nicht mehrere Tags, sondern trennen diese in einem Tag per Komma.

Abfolge und Leerzeichen

Um die langfristige Lesbarkeit zu gewährleisten, sollten Texte und Tags dem gegebenem Beispiel folgen. Diese Festlegungen entsprechen dem JavaDoc-Standard.

Verwendung von @package_version@

Es gibt zwei Wege @package_version@ zu ersetzen. Das ist abhängig davon, ob Sie die Package-Datei package.xml von Hand erzeugen oder das Package PackageFileManager benutzen.

Wenn Sie die Datei direkt bearbeiten, ergänzen Sie ein <replace>-Tag für jede Datei. Das XML sieht dann ähnlich wie dieses aus:

<file name="Class.php">
  <replace from="@package_version@" to="version" type="package-info" />
</file>

Wenn PackageFileManager verwenden, rufen Sie addReplacement() für jede Datei auf:

<?php
$pkg->addReplacement('filename.php', 'package-info',
                     '@package_version@', 'version');
?>

Übergangsregeln

Für existierende kleine Packages

Existierende Packages mit nur wenigen Dateien sollten die DocBlöcke im nächst möglichen Release enthalten.

Für existierende große Packages

Existierende Packages mit vielen Dateien sollten die neuen DocBlöcke sobald wie möglich integrieren. Auf jeden Fall aber mit den nächsten Major-Release.

Neue und unveröffentliche Packages

Neue Packages und existierende Package, für welche noch kein Release existiert, müssen über die DocBlöcke verfügen, wenn ihr erstes Release erscheint.

CVS-Nutzung

Ergänzen Sie das $Id$-CVS-Schlüsselwort in jeder Datei.

Beispiel-URLs

Benutzen Sie example.com, example.org und example.net für alle Beispiel-URLs und Email-Adressen entsprechend RFC 2606.

Namens-Konventionen

Klassen

Verwenden Sie beschreibende Klassennamen und vermeiden Sie Abkürzungen. Klassennamen beginnen immer mit einen Großbuchstaben. Die Klassenhierarchie in PEAR spiegelt sich auch im Klassennamen wieder, jede Ebene der Hierarchie wird durch einen einzelnen Unterstrich getrennt.

Beispiele für Klassennamen:

  • Log
  • Net_Finger
  • HTML_Upload_Error

Funktionen und Methoden

Funktionen und Methoden sollten dem „Studly Caps“-Stil folgen (auch bekannt als „Bumpy Base“ oder „Camel Caps“). Funktionsnamen sollte der Package-Name vorangestellt werden, um Kollisionen mit anderen Funktionsnamen zu vermeiden. Der erste Buchstabe nach dem Prefix wird klein geschrieben, und jeder Buchstabe eines neuen „Wortes“ im Namen wird großgeschrieben.

Beispiele:

  • connect()
  • getData()
  • buildSomeWidget()
  • XML_RPC_serializeData()

Privaten Klassenelemente wird ein Unterstrich vorangestellt.

Zum Beispiel:

  • _sort()
  • _initTree()

$this->_status

Anmerkung: Unter PHP 5 gilt: Klassenelemente, welche protected sind, werden nicht mit einem Unterstrich versehen:

  • protected $somevar
  • protected function initTree()

Konstanten

Konstanten werden immer vollständig groß geschrieben, mit Unterstrichen zwischen den Worten. Ihre Namen müssen mit dem Klassen- bzw. Package-Namen beginnen. Zum Beispiel beginnen alle Konstanten des DB::-Packages mit DB_.

Anmerkung: Die Konstanten true, false und null werden als einzige Ausnahme immer klein geschrieben.

Globale Variablen

Wenn Ihr Package globale Variablen benötigt, sollte deren Name mit einem Unterstrich beginnen, gefolgt vom Package-Namen und einem weiteren Unterstrich. Zum Beispiel benutzt das PEAR-Package die globale Variable $_PEAR_destructor_object_list.

Dateiformate

Alle Skripte in PEAR müssen:

  • als ASCII gespeichert werden.
  • mit dem Zeichensatz ISO-8859-1 kodiert werden.
  • den UNIX-Konventionen folgen. „Unix-Konventionen“ bedeutet:
    • Zeilen dürfen nur mit dem Line-Feed-Zeichen (LF) enden. Das Zeichen entspricht dem Ordinal-Wert 10, Octal 012 und hexadezimal 0A. Benutzen Sie kein Carriage-Return-Zeichen (CR) wie unter Apple Macintosh-Computern oder die CRLF-Kombination unter Windows.
    • Fügen Sie ein Zeilenende-Zeichen nach dem schliessendem PHP-Tag (?>) ein. Das bedeutet, der Cursor im Editor steht eine Zeile nach dem schliessendem Tag.

E_STRICT-kompatibler Code

Jeder Code muss E_STRICT-kompatibel sein. Das heisst, er darf keine Fehler oder Warnungen erzeugen, wenn das Fehler-Reporting von PHP auf E_STRICT eingestellt ist.

Die Entwicklung existierender Packages, die dieser Konvention noch nicht entsprechen, müssen dies auch noch nicht. Erst wenn eine neue major-Version eines Packages erscheint, dann muss diese Version der E_STRICT-Konvention entsprechen.

Richtlinen zur Fehlerbehandlung

Richtlinen zur Fehlerbehandlung

Dieser Abschnitt beschreibt wie Fehler in PEAR-Packages behandelt werden sollen, die für PHP 5 und 6 entwickelt werden. Fehler werden über Exceptions abgewickelt, sie wurden mit PHP 5.0 und der Zend Engine 2 eingeführt.

Was ist ein Fehler?

Ein Fehler ist definiert als ein unerwartet, nicht korrekter Programmzustande, der nicht wieder behoben werden kann. Zur Vereinfachung dieser Definition gilt, dass die Behebung des Fehlers nicht innerhalb einer Methode möglich ist. Eine unvollständige Behebung gilt trotzdem als Behebung.

Beispiel 4-1. Eine typische Fehlersituation

<?php
/**
 * Verbinde zur angegebenen Datenbank
 *
 * @throws Example_Datasource_Exception wenn der Verbindungsaufbau fehlschlägt
 */
function connectDB($dsn) {
    $this->db =& DB::connect($dsn);
    if (DB::isError($this->db)) 
    {
        throw new Example_Datasource_Exception(
                "Unable to connect to $dsn:" . $this->db->getMessage()
        );
    }
}
?>

In diesem Beispiel soll die Methode die Verbindung mit der Datenbank mit dem gegegebenem DSN herstellen. Die Methode ruft ihrerseits nur PEAR::DB, wenn dieses Package einen Fehler wirft, kann nur eine Exception erzeugt und geworfen werden, ohne weiter Einfluß nehmen zu können.

Beispiel 4-2. Fehlerbehandlung mit Behebung

<?php
/*
 * Verbinde mit einer der möglichen Datenbanken
 *
 * @throws Example_Datasource_Exception wenn keine der gewählten
 *         Datenbank angesprochen werden konnte.
 *
 * @throws Example_Config_Exception wenn keine Datenbanken
 *         konfiguriert wurden
 */

function connect(Config $conf) 
{
    $dsns =& $conf->searchPath(array('config', 'db'));
    if ($dsns === FALSE) throw new Example_Config_Exception(
        'Unable to find config/db section in configuration.'
    );

    $dsns =& $dsns->toArray();

    foreach($dsns as $dsn) {
        try {
            $this->connectDB($dsn);
            return;
        } catch (Example_Datasource_Exception e) {
            // Warn-/Logging-Code um den Verbindungsfehler
            // aufzuzeichnen
        }
    }
    throw new Example_Datasource_Exception(
        'Unable to connect to any of the configured databases'
    );
}
?>

Das zweite Beispiel zeigt, wie eine Exception empfangen und behandelt wird. Die verwendete connectDB()-Methode kann nur einen Fehler melden, wenn die Verbindung fehlschlägt. Die übergeordnete Methode connect() hingegen weiss, dass das Objekt auch mit einer der anderen Datenbank-Verbindungen lauffähig ist. Deshalb kann der Fehler als behoben angesehen werden und die Exception wird nicht weitergeleitet.

Beispiel 4-3. Unvollständige Behebung

<?php
/**
 * loadConfig wertet die angegebene Konfiguration aus. Wenn die
 * Konfiguration unkorrekt ist, dann wird auf die Standard-
 * zurückgegriffen
 *
 */
function loadConfig(Config $conf) 
{
    try {
        $this->config = $conf->parse();
    } catch (Config_Parse_Exception e) {
        // Warn-/Logging-Code
        // Unvollständige Fehlerbehebung
        $this->config = $this->defaultConfig;
    }
}
?>

Die Fehlerbehebung führt zu Seiteneffekten, deshalb ist sie nicht vollständig. Das Programm kann weiterlaufen, die Exception gilt als behandelt und muss nicht weitergeleitet werden. Wie im vorherigen Beispiel sollte die aufgetretene Exception aber trotzdem geloggt werden oder eine andere Form der Warnung stattfinden.

Fehler-Benachrichtigung PHP 5 PEAR-Packages

Fehlerhafte Zustände in PEAR-Packages für PHP 5 müssen über Exceptions gemeldet werden. Nicht mehr verwendet werden sollten Fehlercodes oder ein PEAR_Error-Objekt. Diese Regel gilt natürlich nicht, wenn das Package kompatibel mit PHP 4 bleiben muss. In diesem Fall gelten die Konvention der PEAR Coding Standards unter PHP 4 weiter.

Eine Exception sollte immer geworfen werden, wenn ein fehlerhafter Zustand auftritt, entsprechend der Definition im vorherigen Abschnitt. Die geworfene Exception sollte genügend Informationen enthalten, um den Fehler debuggen zu können und schnell dessen Grund herauszufinden. Bedenken Sie, dass in Produktionsumgebungen keine Exception an den Endanwender durchdringen sollten. Deshalb muss man sich keine Gedanken machen über die Komplexität der Fehlermeldung.

Die Basis-Klasse PEAR_Exception enthält eine wörtliche Beschreibung des Fehlers, womit der Programmzustand beschrieben wird, der zum Fehler führte, und - optional - Execptions, die durch untergeordnete Programmaufrufe herbei geführten wurden und die ursprüngliche Ursache des Fehlers darstellen können.

Die Arten von Informationen die in einer Exception enthalten sein müssen, hängt von der Art des Fehlers ab. Es gibt drei Varianten von Exceptions:

  1. Fehler, die während der Vorabprüfung auftreten können.
  2. Fehler, die durch untergeordneten Bibliotheksaufrufe auftreten und durch Fehlercodes oder -Objekte signalisiert werden
  3. Nicht-korrigierbare Exceptions von untergeordneten Bibliotheken.

Fehler, die während der Vorabprüfung auftreten können, sollten eine Beschreibung der fehlgeschlagenen Prüfung enthalten. Wenn möglich sollte der fehlerhafte Wert mit angegeben werden.

Beispiel 4-4.

<?php
function divide($x, $y)
{
    if ($y == 0) {
        throw new Example_Aritmetic_Exception('Division by zero');
    }
}
?>

Fehler, die durch untergeordneten Bibliotheksaufrufe auftreten und durch Fehlercodes oder -Objekte signalisiert werden, sollten in Exceptions umgewandelt werden, wenn diese nicht behoben werden können. Die Fehlerbeschreibung sollte die originale Fehlerinformationen enthalten bzw. entsprechend konvertiert werden. Am Beispiel der obigen connect()-Methode:

Beispiel 4-5.

<?php
/**
 * Verbinde zur angegebenen Datenbank
 *
 * @throws Example_Datasource_Exception wenn der Verbindungsaufbau fehlschlägt
 */
function connectDB($dsn) {
    $this->db =& DB::connect($dsn);
    if (DB::isError($this->db)) {
        throw new Example_Datasource_Exception(
                "Unable to connect to $dsn:" . $this->db->getMessage()
        );
    }
}
?>

Nicht-korrigierbare Exceptions von untergeordneten Bibliotheken sollten weitergeleitet oder erneut geworfen werden. Wenn sie weitergeleitet werden soll, dann behandeln Sie die Exception nicht weiter. Wenn Sie die Exception erneut werfen, dann müssen Sie die originale Exception in der neuen Exception verpacken.

Beispiel 4-6. Eine Exception neu verpacken

<?php
function preTaxPrice($retailPrice, $taxRate) 
{
    try {
        return $this->divide($retailPrice, 1 + $taxRate);
    } catch (Example_Aritmetic_Exception e) {
        throw new Example_Tax_Exception('Invalid tax rate.', e);
    }
}
?>

Beispiel 4-7. Eine Exception weiterleiten

<?php
function preTaxPrice($retailPrice, $taxRate) 
{
    return $this->divide($retailPrice, 1 + $taxRate);
}
?>

Die Entscheidung, ob eine Exception neu verpackt oder weitergeleitet werden soll, ist eine Frage der Software-Architektur. Exceptions sollten weitergeleitet werden, ausser in zwei Fällen:

  1. Die originale Excpetion ist von einem anderen Package. Wenn diese weitergeleitet wird, dann würden Details der Implementierung nach aussen dringen.
  2. Die Methode kann nützliche Debug-Informationen ergänzen.

Exceptions und der normale Programmfluß

Exceptions sollten niemals als Bestandteil des normalen Programmflußes benutzt werden. Wenn alle Logik zur Behandlung von Exceptions entfernt würde (try-catch-Statements), dann sollte der verbliebende Code den "wahren Pfad" repräsentieren – dem Programmfluß, wenn keinerlei Fehler auftreten würden.

Diese Forderung entspricht der Erwartung, dass Exceptions nur bei fehlerhaften Zuständen geworfen werden sollten und niemals bei regulären Zuständen.

Ein Beispiel für die falsche Benutzung der Exception-Weiterleitung ist die Rückgabe eines Wertes eines rekursiven Aufrufs:

Beispiel 4-8.

<?php
/**
 * Rekursive Suche in einem Baum nach einem String
 * @throws ResultException
 */
public function search(TreeNode $node, $data)  
{
    if ($node->data === $data) {
         throw new ResultException( $node );
    } else {
         search( $node->leftChild, $data );
         search( $node->rightChild, $data );
    }
}
?>

Im Beispiel wird die ResultException benutzt, um "schnell" wieder aus der Rekursion heraus zu kommen. Das ist im Fehlerfall tatsächlich praktisch, in diesem Fall, aber nur ein Beispiel für einen faulen Programmierer. Die Klassen-Hierarchie von Exceptions

Alle Exceptions, die von Packages geworfen werden, müssen von PEAR_Exception abstammen. PEAR_Exception bietet zusätzliche Fähigkeiten, um andere Exceptions zu verpacken. Sie finden diese nicht in der obersten PHP Exception-Klasse, sind aber notwendig, um die oben gestellten Anforderungen zu erfüllen.

Zusätzlich sollte jedes PEAR-Package seine eigene Exception-Klasse definieren; der Name der Klasse entspricht dem Muster: <Package_Name>_Exception. Jede Exception sollte von dieser Klasse abgeleitet werden. Exceptions dokumentieren

Da PHP, im Gegensatz zu Java, es nicht erfordert, mögliche Exceptions in der Funktionssignatur aufzunehmen, ist deren sorgfältige Dokumentation im Methodenkopf wichtig.

Beispiel 4-9. Exceptions werden dokumentiert mit dem @throws-Schlüsselwort

<?php
/**
 * Diese Methode sucht nach Aliens.
 *
 * @return array Array von Alien-Objekten.
 * @throws AntennaBrokenException wenn die Impedanz-Leser anzeigt, dass die
 *         Antenne nicht funktioniert
 *
 * @throws AntennaInUseException wenn ein anderer Prozess die Antenne
 *         bereits benutzt
 */
public function findAliens($color = 'green');
?>

In vielen Fällen wandelt die mittlere Schicht einer Anwendung Exceptions von untergeordneten Methoden in aussagekräftiger, anwendungsspezifische Exceptions. Das sollte ebenfalls angesprochen werden:

Beispiel 4-10.

<?php
/**
 * Lade Session-Objekte in den Shared-Memory
 *
 * @throws LoadingException Jede untergeordnete IOException wird als
 *         LoadingException neu verpackt.
 */
public function loadSessionObjects();
?>

In anderen Fällen kann ihre Methode als Filter fungieren, der nur bestimmte Exceptions weiterleitet. Dann sollten Sie dokumentieren, welche Exceptions nicht von Ihrer Methode abgefangen werden.

Beispiel 4-11.

<?php
/**
 * Führt eine Reihe von Datenbankanfragen aus (atomar, nicht innerhalb einer Transaktion).
 * @throws SQLException Low-level SQL-Fehler werden direkt weitergeleitet.
 */
public function batchExecute();
?>

Exceptions als Teil der API

Exceptions spielen eine kritische Rolle in der API ihrer Bibliothek. Entwickler, die Ihre Bibliothek verwenden, sind abhängig von der angemessenen Beschreibung wo und warum Exceptions auftreten in Ihrem Package. Auch die sorgfältige Planung der Fehlermeldungen ist ein wichtiger Faktor für die Erhaltung der Rückwärts-Kompatibilität.

Da Exceptions ein integraler Bestandteil der API ihres Packages sind, darf bei Änderungen daran die Rückwärts-Kompatibilität (BC) nicht grundlos gebrochen werden.

Dinge, die zum Bruch führen:

  • Jede Änderung an Methoden, die Exceptions werfen.
  • Wenn eine Exception-Klasse verwendet wird, die höher in der Vererbungskette liegt, als die ursprüngliche. Zum Beispiel, wenn Sie in einer neueren Version eine PEAR_Exception werfen würden, in der alten aber z.B. PEAR_IOException verwendet haben.

Dinge, die nicht zum Bruch führen:

  • Wenn eine abgeleitete Klasse der originalen Exception verwendet wird. Zum Beispiel, wenn Sie in der aktuellen Version eine PEAR_IOException werfen, und in älteren Versionen PEAR_Exception. Natürlich nur unter der Voraussetzung, dass PEAR_IOException von PEAR_Exception) abgeleitet ist.

Best practices

Es gibt einige andere Dinge, die nicht vom PEAR Coding Standard betroffen sind, sondern von den persönlichen Gewohnheiten abhängen und nicht die Lesbarkeit unmittelbar berühren. Das betrifft z.B. die Frage 'Einfache oder doppelte Anführungszeichen'. Es handelt sich um Konstrukte, welche die Programmierung vereinfachen ohne konkrete Probleme zu verursachsen. Welche dieser 'üblichen' Praktiken genutzt wird, diese Entscheidung ist dem Programmierer überlassen. Wichtiger ist die konsequente Anwendung der eigenen Entscheidung in einem Package. Respektieren Sie die Entscheidung des verantwortlichen Programmierers, wenn Sie fremde Packages verändern.

Beispieldatei inklusive Docblock-Kommentaren

Der Quellcode von PEAR-Packages wird von tausenden von Menschen gelesen. Genauso kann es passieren, dass andere einmal an Ihrem Package entwicklen werden. Um es ihnen leichter zu machen, ist die Formatierung des Quellcode und der Docblöcke standarisiert. Damit können Andere Informationen einfacher finden, das sie wissen, wo sie suchen müssen.

Jeder Docblock im Beispiel enthält viele Details wie Sie die Kommentare schreiben sollten. Diese Instruktionen sind aus zwei Gründen wichtig. Erstens können Benutzer und Entwickler schneller verstehen, was Ihr Code tut. Zweitens wird auf der PEAR-Webseite die Quellcode-Dokumentation für jedes Release von jedem Package bereitgestellt und Sie sollten auch dafür sorgen, dass diese Möglichkeit sinnvoll genutzt werden kann.

Bitte achten Sie auch auf den Einsatz von vertikalen und horizontalen Leerräumen. Sie sind Bestandteil der Standards.

Die „Fold Markers“ (// {{{ und // }}}) sind optional. Wenn Sie nicht benötigt werden, entfernen Sie die Einstellung foldmethod=marker aus dem Block mit Vim-Einstellungen.

<?php

/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */

/**
 * Kurze Beschreibung des Datei-Inhalts
 *
 * Lange Beschreibung des Datei-Inhaltes, wenn erforderlich.
 *
 * PHP versions 4 and 5
 *
 * LICENSE: This source file is subject to version 3.0 of the PHP license
 * that is available through the world-wide-web at the following URI:
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
 * the PHP License and are unable to obtain it through the web, please
 * send a note to license@php.net so we can mail you a copy immediately.
 *
 * @category   CategoryName
 * @package    PackageName
 * @author     Original Author <author@example.com>
 * @author     Another Author <another@example.com>
 * @copyright  1997-2005 The PHP Group
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
 * @version    CVS: $Id:$
 * @link       http://pear.php.net/package/PackageName
 * @see        NetOther, Net_Sample::Net_Sample()
 * @since      File available since Release 1.2.0
 * @deprecated File deprecated in Release 2.0.0
 */

/**
 * Das ist ein "Docblock-Kommentar", auch bekannt als "docblock"/"Docblock"
 * Der Klassen-Docblock weiter unten enthält eine Beschreibung wie sie
 * geschrieben werden.
 */
require_once 'PEAR.php';

// {{{ constants

/**
 * Methoden geben diesen Wert im Erfolgsfall zurück.
 */
define('_NET_SAMPLE_OK', 1);

// }}}
// {{{ GLOBALS

/**
 * Die Anzahl der erzeugten Objekte
 * @global int $GLOBALS['NET_SAMPLE_Count']
 */
$GLOBALS['_NET_SAMPLE_Count'] = 0;

// }}}
// {{{ Net_Sample

/**
 * Ein Beispiel wird Code entsprechend der PEAR-Standards aussieht
 *
 * Anmerkung des Übersetzers: Quelltext-Kommentare sollten natürlich
 * durchgängig in Englisch erfolgen!
 *
 * Ein Docblock-Kommentar beginnt mit "/**" am Anfang.  Beachten Sie, das "/"
 * beginnt mit der normalen Einrückung und die Sterne darunter stehen in der
 * selben Textspalte wie der erste Stern. Der letzte Zeile des Kommentar-Blocks
 * sollte unmittelbar das zu dokumentierende Element folgen,
 * Vermeiden Sie zusätzliche Leerzeilen. Ergänzen Sie eine Leerzeile
 * zwischen Absätzen im Kommentartext, genauso zwischen Kommentartext und dem
 * ersten @-Tag. Ein Zeilenumbruch im Kommentartext sollte nach 80 Zeichen
 * erfolgen.
 *
 * Docblöcke können nur für eine begrenzte Anzahl an Elementen verwendet
 * werden (Klassen, Eigenschaften, Methoden, Konstanten, Include und
 * globale Variablen. In der Dokumentation zu phpDocumentor finden Sie mehr
 * Informationen dazu:
 * http://phpdoc.org/docs/HTMLSmartyConverter/default/phpDocumentor/tutorial_phpDocumentor.howto.pkg.html
 *
 * Der Javadoc Style Guide ist eine exzellente Quelle wie man Kommentare
 * formulieren sollte. Letztlich sind diese Informationen eine Zusammenfassung
 * davon, andererseits gibt es aber auch einige Abweichungen davon.
 * http://java.sun.com/j2se/javadoc/writingdoccomments/index.html#styleguide
 *
 * Diese erste Zeile jedes Docblocks ist eine Zusammenfassung. Sie sollte
 * genau einen Satz umfassen, ohne Punkt am Ende. Zusammenfassungen für
 * Klassen, Eigenschaften und Konstanten sollten nicht deren Namen enthalten
 *
 * Die unten aufgeführten Tag werden üblicherweise für Klassen benutzt.
 * Die Tags @category bis @version sind erforderlich. Die Übrigen
 * sollten ergänzt werden, wenn erforderlich. Verwenden Sie die Tags
 * in der Reihenfolge, wie hier aufgeführt. phpDocumentor bietet
 * weitere Tags, verwenden Sie diese, wenn erforderlich.
 *
 * @category   CategoryName
 * @package    PackageName
 * @author     Original Author <author@example.com>
 * @author     Another Author <another@example.com>
 * @copyright  1997-2005 The PHP Group
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
 * @version    Release: @package_version@
 * @link       http://pear.php.net/package/PackageName
 * @see        NetOther, Net_Sample::Net_Sample()
 * @since      Class available since Release 1.2.0
 * @deprecated Class deprecated in Release 2.0.0
 */
class Net_Sample
{
    // {{{ properties

    /**
     * Der Zustand von foo's universe
     *
     * Potentielle Werte sind 'good', 'fair', 'poor' und 'unknown'.
     *
     * @var string
     */
    var $foo = 'unknown';

    /**
     * The status of life
     *
     * Vergessen Sie nicht, dass private Elemente mit einem
     * Unterstrich beginnen müssen.
     *
     * @var bool
     * @access private
     */
    var $_good = true;

    // }}}
    // {{{ setFoo()

    /**
     * Registriert den Zustand des Foo-Universums
     *
     * Die Zusammenfassung für eine Methode sollte besser in der 3. Person 
     * Einzahl statt in der 2. Person formuliert werden.
     * Das Verb sollte am Anfang stehen.
     *
     * Die Zusammenfassung sollte mehr Informationen liefern, die über den
     * Methodennamen hinaus gehen. Die besten Methodennamen sind
     * selbst beschreibend, sie sagen was die Methode im Grunde macht.
     * Wenn die Zusammenfassung den Methodennamen nur in Form eines
     * Satzes wiederholt, liefert sie keine zusätzlichen Informationen.
     *
     * Beispiele für die Zusammenfassung:
     *   + Sets the label              (empfohlen)
     *   + Set the label               (vermeiden)
     *   + This method sets the label  (vermeiden)
     *
     * Als nächstes werden die üblichen Tags für Methoden angeführt.
     * Ein @param-Tag muss für jeden Parameter angegeben werden.
     * Die Tags @return und @access sind wahlfrei. Das @throw-Tag
     * muss angegeben werden, wenn die Methode Exceptions wirft.
     * Das Tag @static ist erforderlich, wenn die Methode statisch
     * aufgerufen werden kann. Die übrigen Tags brauchen Sie nur
     * angeben, wenn diese benötigt werden. Bitte geben Sie die
     * Tags in der Reihenfolge an, wie sie hier aufgeführt sind.
     * phpDocumentor bietet weitere Tags, benutze Sie diese, wenn
     * es sinnvoll ist.
     *
     * Das @param-Tag umfasst den Datentypen, den Parameter-Namen, gefolgt
     * von einer Beschreibung. Per Konvention sollte die Beschreibung beginnen
     * mit dem Datentyp, dem ein Artikel ("a", "an" oder "the") vorangestellt
     * werden kann. Setzen Sie zwei Leerzeichen zwischen dem Namen
     * des Parameters und seiner Beschreibung für eine bessere Lesbarkeit.
     *
     * Wenn Sie einen Satz schreiben, starten Sie nicht mit einem
     * Großbuchstaben und beenden Sie ihn nicht mit einem Punkt:
     *   + the string to be tested
     *
     * Wenn Sie mehr als einen Satz schreiben, setzen Sie einen Punkt und
     * beginnen Sie den zweiten Satz mit einem Großbuchstaben:
     *   + the string to be tested. Must use UTF-8 encoding.
     *
     * Das @return-Tag sollte den Datentyp und eine Beschreibung des
     * zurückgegebenen Wertes enthalten. Der Datentyp kann einer von PHP's
     * Datentyp sein (int, float, bool, string, array, object, resource, mixed)
     * und sollte den primär zurückgegebenen Wert enthalten. Z.B.
     * eine Methode gibt korrekterweise ein Objekt zurück und nur im
     * Fehlerfall 'false', dann sollten Sie 'object' angeben statt
     * 'mixed'. Verwenden Sie 'void' wenn nicht zurückgegeben wird.
     *
     * Hier ein Beispiel für Quellcode-Texte:
     * <code>
     * require_once 'Net/Sample.php';
     *
     * $s = new Net_Sample();
     * if (PEAR::isError($s)) {
     *     echo $s->getMessage() . "\n";
     * }
     * </code>
     *
     * Hier ein Beispiel für Nicht-PHP-Code:
     * <samp>
     * pear install net_sample
     * </samp>
     *
     * @param string $arg1  the string to quote
     * @param int    $arg2  an integer of how many problems happened.
     *                       Rücken Sie nachfolgende Zeilen in der Beschreibung
     *                       entsprechend ein.
     *
     * @return int  the integer of the set mode used. FALSE if foo
     *               foo could not be set.
     * @throws exceptionclass  [description]
     *
     * @access public
     * @static
     * @see Net_Sample::$foo, Net_Other::someMethod()
     * @since Method available since Release 1.2.0
     * @deprecated Method deprecated in Release 2.0.0
     */
    function setFoo($arg1, $arg2 = 0)
    {
        /*
         * Das ist ein "Block Kommentar". Das Format entspricht
         * den obigen Kommentaren, mit der Ausnahme, das der Kommentarbeginn
         * nur einen Stern enthält.
         * phpDocumentor wertet diese nicht aus.
         */
        if ($arg1 == 'good' || $arg1 == 'fair') {
            $this->foo = $arg1;
            return 1;
        } elseif ($arg1 == 'poor' && $arg2 > 1) {
            $this->foo = 'poor';
            return 2;
        } else {
            return false;
        }
    }

    // }}}
}

// }}}

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * c-hanging-comment-ender-p: nil
 * End:
 */

?>

(Quelle: PEAR Coding Standard, 05.02.2008)

 
 
08.02.2008 00:17 Uhr von chueser -
 
 
08.02.2008 00:12 Uhr von chueser -
Zeilen 1113-1115 hinzugefügt:

(Quelle: PEAR Coding Standard, 05.02.2008)

 
 
07.02.2008 23:58 Uhr von chueser -
Zeile 190 bearbeitet:

PEAR Coding Standards

geändert in:

PEAR Coding Standard

 
 
07.02.2008 23:54 Uhr von chueser -
Zeilen 48-49 bearbeitet:
  • find ich gut so (CH)
geändert in:
  • find ich gut so (chueser)
Zeile 163 bearbeitet:

Namenskonvention für Accessor-Methoden (CH)

geändert in:

Namenskonvention für Accessor-Methoden (chueser)

Zeile 171 bearbeitet:

Anzahl Klassen in einem File (CH)

geändert in:

Anzahl Klassen in einem File (chueser)

Zeile 177 bearbeitet:

File-Name (CH)

geändert in:

File-Name (chueser)

 
 
07.02.2008 23:49 Uhr von chueser - StudIP Coding Standard
 
 
07.02.2008 23:47 Uhr von 88.70.57.232 - PEAR Coding Standard
Zeilen 1-1113 hinzugefügt:

Vorschlag für einen StudIP Coding Standard: PEAR Coding Standard

Diskussion über den PEAR Coding Standard

Zusammenfassung
Änderungswünsche & mehr

Inhaltsverzeichnis: PEAR Coding Standard

Einrückungen und Zeilenlänge
Kontrollstrukturen
Funktionsaufrufe
Klassen-Definition
Funktionsdefinitionen
Kommentare
Code einbinden
PHP-Code-Tags
Kopf-Kommentare
CVS-Nutzung
Beispiel-URLs
Namens-Konventionen
Dateiformate
E_STRICT-kompatibler Code
Richtlinen zur Fehlerbehandlung
Best practices
Beispieldatei inklusive Docblock-Kommentaren

Diskussion über den PEAR Coding Standard

Zusammenfassung

(:table border=1 width=100% align=center cellspacing=0 :)

(:cellnr width=20% align=center bgcolor=#CCCCCC :) Feature (:cell width=50% align=center bgcolor=#CCCCCC :) Ausprägung (:cell width=30% align=center bgcolor=#CCCCCC :) Euer Kommentar (mit Namen bitte)

(:cellnr align=left bgcolor=#EEEEEE :) Einrückungen (:cell align=left bgcolor=#EEEEEE :)

  • 4 Leerzeichen, keine Tabulatoren

(:cell align=left bgcolor=#EEEEEE :)

  • find ich gut so (CH)

(:cellnr align=left bgcolor=#EEEEEE :) Zeilenlänge (:cell align=left bgcolor=#EEEEEE :)

  • ca. 75 - 85 Zeichen

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Kontrollstrukturen (:cell align=left bgcolor=#EEEEEE :)

  • Leerzeichen zwischen den Schlüsselwörtern und der öffnenden Klammer
  • immer geschweifte Klammern verwenden
  • öffnende geschweifte Klammer in gleicher Zeile

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Funktionsaufrufe (:cell align=left bgcolor=#EEEEEE :)

  • kein Leerzeichen zwischen dem Funktionsnamen, der öffnenden Klammer und dem ersten Parameter

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Klassen-Definition (:cell align=left bgcolor=#EEEEEE :)

  • öffnende Klammer einer Klassen-Deklaration beginnt auf einer neuen Zeile

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Funktionsdefinitionen (:cell align=left bgcolor=#EEEEEE :)

  • öffnende Klammer einer Funktionsdefinition beginnt auf einer neuen Zeile
  • Argumente mit Standardwerten werden am Ende der Argumentenliste platziert
  • wenn möglich, immer einen aussagekräftigen Wert zurückliefern

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Kommentare (:cell align=left bgcolor=#EEEEEE :)

  • vollständige Inline-Dokumentation (Docblocks): File, Includes, Konstanten, Variablen, Methoden, Klasse
  • unbedingt (!) auch abseits der offziellen API-Dokumentation Kommentare im Quellcode einsetzen
  • Als Daumenregel gilt, wenn Sie auf einen Code-Abschnitt schauen und denken: „Wow, Ich würde nicht versuchen herauszufinden, wie es funktioniert“, sollten Sie auf jeden Fall einen Kommentar ergänzen, bevor Sie vergessen, wie es funktioniert.

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Code einbinden (:cell align=left bgcolor=#EEEEEE :) (:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) PHP-Code-Tags (:cell align=left bgcolor=#EEEEEE :)

  • immer die Langform <?php ?> benutzen

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Kopf-Kommentare (:cell align=left bgcolor=#EEEEEE :)

  • Alle Quellcode-Dateien sollen einen „Page-level“ Docblock am Datei-Anfang besitzen und einen „Class-level“ Docblock unmittelbar vor jeder Klasse.
  • Docblock = short decription + long description + tag list

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) CVS-Nutzung (:cell align=left bgcolor=#EEEEEE :)

  • $Id$-CVS-Schlüsselwort in jede Datei.

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Beispiel-URLs (:cell align=left bgcolor=#EEEEEE :) (:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Namens-Konventionen (:cell align=left bgcolor=#EEEEEE :)

  • beschreibende Klassennamen und Abkürzungen vermeiden
  • Klassennamen beginnen immer mit einen Großbuchstaben
  • Klassenhierarchie spiegelt sich im Klassennamen wieder, jede Ebene der Hierarchie wird durch einen einzelnen Unterstrich getrennt
  • Funktionen und Methoden im „Camel Caps“
  • Funktionsnamen sollte der Package-Name vorangestellt werden
  • erster Buchstabe nach Prefix wird klein geschrieben, und jeder Buchstabe eines neuen „Wortes“ wird großgeschrieben
  • privaten Klassenelemente wird ein Unterstrich vorangestellt

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Dateiformate (:cell align=left bgcolor=#EEEEEE :) (:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) E_STRICT-kompatibler Code (:cell align=left bgcolor=#EEEEEE :) (:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Richtlinen zur Fehlerbehandlung (:cell align=left bgcolor=#EEEEEE :) (:cell align=left bgcolor=#EEEEEE :)

(:tableend:)

Änderungswünsche & mehr

(:table border=1 width=100% align=center cellspacing=0 :)

(:cellnr width=20% align=center bgcolor=#CCCCCC :) Feature (Name) (:cell width=50% align=center bgcolor=#CCCCCC :) Ausprägung (:cell width=30% align=center bgcolor=#CCCCCC :) Euer Kommentar (Namen)

(:cellnr align=left bgcolor=#EEEEEE :) Namenskonvention für Accessor-Methoden (CH) (:cell align=left bgcolor=#EEEEEE :)

  • getter Methoden: get+Variablenname
  • setter Methoden: set+Variablenname
  • erster Buchstabe des Variablennamens groß schreiben

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) Anzahl Klassen in einem File (CH) (:cell align=left bgcolor=#EEEEEE :)

  • nur eine Klasse pro File (wegen Eindeutigkeit der Packages)

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) File-Name (CH) (:cell align=left bgcolor=#EEEEEE :)

  • Name des Files gleich dem Klassen-Namen

(:cell align=left bgcolor=#EEEEEE :)

(:cellnr align=left bgcolor=#EEEEEE :) (:cell align=left bgcolor=#EEEEEE :) (:cell align=left bgcolor=#EEEEEE :)

(:tableend:)

PEAR Coding Standards

Einrückungen und Zeilenlänge

Benutzen Sie Einrückungen mit 4 Leerzeichen, keine Tabulatoren. Damit helfen Sie, Probleme zu vermeiden, die mit Diffs, Patches und anderen CVS-Funktionen entstehen.

Wir empfehlen einen Zeilenumbruch bei ca. 75 - 85 Zeichen durchzuführen, um die Lesbarkeit zu erhöhen.

Kontrollstrukturen (if, for, while, switch usw.)

Bsp für if-Kosntruktionen:

<?php
if ((condition1) || (condition2)) {
    action1;
} elseif ((condition3) && (condition4)) {
    action2;
} else {
    defaultaction;
}
?>

Kontroll-Ausdrücke sollten ein Leerzeichen zwischen den Schlüsselwörtern und der öffnenden Klammer haben, um sie von Funktionsaufrufen unterscheiden zu können.

Sie sollten unbedingt geschweifte Klammern verwenden, auch wenn sie technisch nur optional sind. Damit verbessern Sie die Lesbarkeit und vermeiden logische Fehler, wenn neue Zeilen hinzugefügt werden.

Bsp für switch-Ausdrücke:

<?php
switch (condition) {
case 1:
    action1;
    break;

case 2:
    action2;
    break;

default:
    defaultaction;
    break;
}
?>

Funktionsaufrufe

Funktionen sollten ohne Leerzeichen zwischen dem Funktionsnamen, der öffnenden Klammer und dem ersten Parameter aufgerufen werden. Leerzeichen sollten gesetzt werden zwischen Komma und jedem Parameter. Zwischen dem letzten Parameter, der schliessenden Klammer und Semikolon sollten keine Leerzeichen gesetzt werden.

Beispiel:

<?php
$var = foo($bar, $baz, $quux);
?>

Wie oben gezeigt, sollte ein Leerzeichen vor und hinter das Gleichheitszeichen gesetzt werden, wenn der Rückgabewert der Funktion einer Variable zugewiesen wird. Wenn ein Block zusammenhängender Zuweisungen durchgeführt wird, empfehlen wir mehrere Leerzeichen einzufügen, um die Lesbarkeit zu verbessern:

<?php
$short         = foo($bar);
$long_variable = foo($baz);
?>

Klassen-Definition

Die öffnende Klammer einer Klassen-Deklaration beginnt auf einer neuen Zeile:

<?php
class FooBar
{

    //... ihr Code

}
?>

Funktionsdefinitionen

Funktionsdeklarationen folgen dem „K&R-Stil“ (Programmierstil der C-Erfindern Brian W. Kernighan und Dennis Ritchie):

<?php
function fooFunction($arg1, $arg2 = '')
{
    if (condition) {
        statement;
    }
    return $val;
}
?>

Argumente mit Standardwerten werden am Ende der Argumentenliste platziert. Eine Funktion sollte immer einen aussagekräftigen Wert zurückliefern, soweit wie es möglich ist.

Beispiel:

<?php
function connect(&$dsn, $persistent = false)
{
    if (is_array($dsn)) {
        $dsninfo = &$dsn;
    } else {
        $dsninfo = DB::parseDSN($dsn);
    }

    if (!$dsninfo || !$dsninfo['phptype']) {
        return $this->raiseError();
    }

    return true;
}
?>

Kommentare

Sie müssen vollständige Inline-Dokumentation bereitstellen (Docblocks).

Sie sollten auch abseits der offziellen API-Dokumentation Kommentare im Quellcode einsetzen. Als Daumenregel gilt, wenn Sie auf einen Code-Abschnitt schauen und denken: „Wow, Ich würde nicht versuchen herauszufinden, wie es funktioniert“, sollten Sie auf jeden Fall einen Kommentar ergänzen, bevor Sie vergessen, wie es funktioniert.

Kommentare im C-Stil (/* */) und von Standard-C++ (//) sollten verwendet werden. Kommentare im Perl/shell-Stil (#) sollten Sie vermeiden.

Code einbinden

Immer wenn Sie eine Klassendatei unbedingt inkludieren müssen, dann benutzen Sie require_once. Benötigen Sie hingegen eine Datei nur bedingt, z.B. in Factory-Methoden, verwenden Sie include_once. Beide stellen sicher, dass die Datei nur einmal eingebunden wird. Beide Funktionen benutzen die gleiche Liste zur Verwaltung der bereits eingebundenen Dateien. Sie müssen sich über eine Mischung aus beiden Funktionsaufrufen keine Gedanken machen - eine Datei, die per require_once eingebunden wurde, wird nicht erneut eingebunden mit include_once.

Anmerkung: include_once und require_once sind Anweisungen, nicht Funktionen. Deshalb sollten die Dateinamen nicht in Klammern eingeschlossen werden.

PHP-Code-Tags

Benutzen Sie immer <?php ?> um Ihren PHP-Code zu markieren, niemale die Kurzform <? ?>. Die erste Variante funktioniert unabhängig vom Betriebssystem und der PHP-Konfiguration.

Kopf-Kommentare

Alle Quellcode-Dateien sollen einen „Page-level“ Docblock am Datei-Anfang besitzen und einen „Class-level“ Docblock unmittelbar vor jeder Klasse.

Beispiele:

<?php

/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */

/**
 * Short description for file
 *
 * Long description for file (if any)...
 *
 * PHP versions 4 and 5
 *
 * LICENSE: This source file is subject to version 3.0 of the PHP license
 * that is available through the world-wide-web at the following URI:
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
 * the PHP License and are unable to obtain it through the web, please
 * send a note to license@php.net so we can mail you a copy immediately.
 *
 * @category   CategoryName
 * @package    PackageName
 * @author     Original Author <author@example.com>
 * @author     Another Author <another@example.com>
 * @copyright  1997-2005 The PHP Group
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
 * @version    CVS: $Id:$
 * @link       http://pear.php.net/package/PackageName
 * @see        NetOther, Net_Sample::Net_Sample()
 * @since      File available since Release 1.2.0
 * @deprecated File deprecated in Release 2.0.0
 */ 

/*
 * Place includes, constant defines and $_GLOBAL settings here.
 * Make sure they have appropriate docblocks to avoid phpDocumentor
 * construing they are documented by the page-level docblock.
 */

/**
 * Short description for class
 *
 * Long description for class (if any)...
 *
 * @category   CategoryName
 * @package    PackageName
 * @author     Original Author <author@example.com>
 * @author     Another Author <another@example.com>
 * @copyright  1997-2005 The PHP Group
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
 * @version    Release: @package_version@
 * @link       http://pear.php.net/package/PackageName
 * @see        NetOther, Net_Sample::Net_Sample()
 * @since      Class available since Release 1.2.0
 * @deprecated Class deprecated in Release 2.0.0
 */
class Foo_Bar
{
}

?>

Erforderliche Tags

Kurzbeschriebung

Die Kurzbeschreibung muss in allen Docblocks existieren. Sie umfasst einen Satz, und sollten keinesfalls nur aus dem Namen des beschreibenden Objektes stehen.

PHP Version

Folgende Zeile muss in den Page-level-Docblock eingefügt werden. Sie beschreibt, unter welcher PHP-Version der Quellcode läuft:

  • PHP version 4
  • PHP version 5
  • PHP versions 4 and 5

@license

Sie können verschiedene Lizenzen für ihr Package verwenden. Sie müssen eine auswählen und diese sowohl im Page-level-, wie auch dem Class-level-Docblock einfügen:

  • @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
  • @license http://www.freebsd.org/copyright/freebsd-license.html BSD License (2 Clause)
  • @license http://www.debian.org/misc/bsd.license BSD License (3 Clause)
  • @license http://www.freebsd.org/copyright/license.html BSD License (4 Clause)
  • @license http://www.opensource.org/licenses/mit-license.html MIT License
  • @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
  • @license http://www.php.net/license/3_0.txt PHP License 3.0

@link

Die Link-Angabe muss im Page-level- and Class-level-Docblock erfolgen. Sie müssen den Eintrag für „PackageName“ natürlich durch den Namen Ihres Packages ersetzen. Auf diese Weise ist sicher gestellt, dass die API-Dokumentation die Links auf die Package-Homepage enthält.

  • @link http://pear.php.net/package/PackageName

@author

Es gibt keine klare Regel, wann jemand zur Liste der Quellcode-Autoren hinzugefügt werden sollte. Allgemein sollten sie substanziell beigetragen haben, ca. 10% bis 20% des Codes. Sie können Ausnahmen machen, wenn Methoden neu geschrieben wurden oder neue Logik beigesteuert wurde.

Einfache Code-Neuformatierungen oder Bug-Fixes sollten nicht zur Aufnahme in die Liste führen.

@since

Dieses Tag ist erforderlich, wenn eine Datei oder Klasse nach dem ersten Release zum Package ergänzt wurde. Verwenden Sie es nicht beim ersten Release.

@deprecated

Dieses Tag ist erforderlich, wenn eine Datei oder Klasse nicht mehr benutzt wird, aber für die Rückwärtskompatibilität noch verfügbar ist.

Optionale Tags

@copyright

Sie können dieses Tag setzen, wenn Sie Copyright-Anmerkungen ergänzen wollen. Das Format des Tags: Die vierstellige Jahreszahl bzw. bei mehreren Jahren, nur das erste und letzte Jahr getrennt mit einem Querstrich; danach der Copyright-Inhaber, also die betreffenden Personen, Firma oder z.B. die PHP Group.

Beispiele:

  • @copyright 2003 John Doe and Jennifer Buck
  • @copyright 2001-2004 John Doe
  • @copyright 1997-2004 The PHP Group
  • @copyright 2001-2004 XYZ Corporation

License Summary

If you are using the PHP License, use the summary text provided above. If another license is being used, please remove the PHP License summary. Feel free to substitute it with text appropriate to your license, though to keep things easy to locate, please preface the text with LICENSE: .

@see

Fügen Sie ein @see-Tag hinzu, wenn Sie auf andere Abschnitte in der Package-Dokumentation verweisen. Wenn Sie mehrere Einträge hinzufügen, verwenden Sie nicht mehrere Tags, sondern trennen diese in einem Tag per Komma.

Abfolge und Leerzeichen

Um die langfristige Lesbarkeit zu gewährleisten, sollten Texte und Tags dem gegebenem Beispiel folgen. Diese Festlegungen entsprechen dem JavaDoc-Standard.

Verwendung von @package_version@

Es gibt zwei Wege @package_version@ zu ersetzen. Das ist abhängig davon, ob Sie die Package-Datei package.xml von Hand erzeugen oder das Package PackageFileManager benutzen.

Wenn Sie die Datei direkt bearbeiten, ergänzen Sie ein <replace>-Tag für jede Datei. Das XML sieht dann ähnlich wie dieses aus:

<file name="Class.php">
  <replace from="@package_version@" to="version" type="package-info" />
</file>

Wenn PackageFileManager verwenden, rufen Sie addReplacement() für jede Datei auf:

<?php
$pkg->addReplacement('filename.php', 'package-info',
                     '@package_version@', 'version');
?>

Übergangsregeln

Für existierende kleine Packages

Existierende Packages mit nur wenigen Dateien sollten die DocBlöcke im nächst möglichen Release enthalten.

Für existierende große Packages

Existierende Packages mit vielen Dateien sollten die neuen DocBlöcke sobald wie möglich integrieren. Auf jeden Fall aber mit den nächsten Major-Release.

Neue und unveröffentliche Packages

Neue Packages und existierende Package, für welche noch kein Release existiert, müssen über die DocBlöcke verfügen, wenn ihr erstes Release erscheint.

CVS-Nutzung

Ergänzen Sie das $Id$-CVS-Schlüsselwort in jeder Datei.

Beispiel-URLs

Benutzen Sie example.com, example.org und example.net für alle Beispiel-URLs und Email-Adressen entsprechend RFC 2606.

Namens-Konventionen

Klassen

Verwenden Sie beschreibende Klassennamen und vermeiden Sie Abkürzungen. Klassennamen beginnen immer mit einen Großbuchstaben. Die Klassenhierarchie in PEAR spiegelt sich auch im Klassennamen wieder, jede Ebene der Hierarchie wird durch einen einzelnen Unterstrich getrennt.

Beispiele für Klassennamen:

  • Log
  • Net_Finger
  • HTML_Upload_Error

Funktionen und Methoden

Funktionen und Methoden sollten dem „Studly Caps“-Stil folgen (auch bekannt als „Bumpy Base“ oder „Camel Caps“). Funktionsnamen sollte der Package-Name vorangestellt werden, um Kollisionen mit anderen Funktionsnamen zu vermeiden. Der erste Buchstabe nach dem Prefix wird klein geschrieben, und jeder Buchstabe eines neuen „Wortes“ im Namen wird großgeschrieben.

Beispiele:

  • connect()
  • getData()
  • buildSomeWidget()
  • XML_RPC_serializeData()

Privaten Klassenelemente wird ein Unterstrich vorangestellt.

Zum Beispiel:

  • _sort()
  • _initTree()

$this->_status

Anmerkung: Unter PHP 5 gilt: Klassenelemente, welche protected sind, werden nicht mit einem Unterstrich versehen:

  • protected $somevar
  • protected function initTree()

Konstanten

Konstanten werden immer vollständig groß geschrieben, mit Unterstrichen zwischen den Worten. Ihre Namen müssen mit dem Klassen- bzw. Package-Namen beginnen. Zum Beispiel beginnen alle Konstanten des DB::-Packages mit DB_.

Anmerkung: Die Konstanten true, false und null werden als einzige Ausnahme immer klein geschrieben.

Globale Variablen

Wenn Ihr Package globale Variablen benötigt, sollte deren Name mit einem Unterstrich beginnen, gefolgt vom Package-Namen und einem weiteren Unterstrich. Zum Beispiel benutzt das PEAR-Package die globale Variable $_PEAR_destructor_object_list.

Dateiformate

Alle Skripte in PEAR müssen:

  • als ASCII gespeichert werden.
  • mit dem Zeichensatz ISO-8859-1 kodiert werden.
  • den UNIX-Konventionen folgen. „Unix-Konventionen“ bedeutet:
    • Zeilen dürfen nur mit dem Line-Feed-Zeichen (LF) enden. Das Zeichen entspricht dem Ordinal-Wert 10, Octal 012 und hexadezimal 0A. Benutzen Sie kein Carriage-Return-Zeichen (CR) wie unter Apple Macintosh-Computern oder die CRLF-Kombination unter Windows.
    • Fügen Sie ein Zeilenende-Zeichen nach dem schliessendem PHP-Tag (?>) ein. Das bedeutet, der Cursor im Editor steht eine Zeile nach dem schliessendem Tag.

E_STRICT-kompatibler Code

Jeder Code muss E_STRICT-kompatibel sein. Das heisst, er darf keine Fehler oder Warnungen erzeugen, wenn das Fehler-Reporting von PHP auf E_STRICT eingestellt ist.

Die Entwicklung existierender Packages, die dieser Konvention noch nicht entsprechen, müssen dies auch noch nicht. Erst wenn eine neue major-Version eines Packages erscheint, dann muss diese Version der E_STRICT-Konvention entsprechen.

Richtlinen zur Fehlerbehandlung

Richtlinen zur Fehlerbehandlung

Dieser Abschnitt beschreibt wie Fehler in PEAR-Packages behandelt werden sollen, die für PHP 5 und 6 entwickelt werden. Fehler werden über Exceptions abgewickelt, sie wurden mit PHP 5.0 und der Zend Engine 2 eingeführt.

Was ist ein Fehler?

Ein Fehler ist definiert als ein unerwartet, nicht korrekter Programmzustande, der nicht wieder behoben werden kann. Zur Vereinfachung dieser Definition gilt, dass die Behebung des Fehlers nicht innerhalb einer Methode möglich ist. Eine unvollständige Behebung gilt trotzdem als Behebung.

Beispiel 4-1. Eine typische Fehlersituation

<?php
/**
 * Verbinde zur angegebenen Datenbank
 *
 * @throws Example_Datasource_Exception wenn der Verbindungsaufbau fehlschlägt
 */
function connectDB($dsn) {
    $this->db =& DB::connect($dsn);
    if (DB::isError($this->db)) 
    {
        throw new Example_Datasource_Exception(
                "Unable to connect to $dsn:" . $this->db->getMessage()
        );
    }
}
?>

In diesem Beispiel soll die Methode die Verbindung mit der Datenbank mit dem gegegebenem DSN herstellen. Die Methode ruft ihrerseits nur PEAR::DB, wenn dieses Package einen Fehler wirft, kann nur eine Exception erzeugt und geworfen werden, ohne weiter Einfluß nehmen zu können.

Beispiel 4-2. Fehlerbehandlung mit Behebung

<?php
/*
 * Verbinde mit einer der möglichen Datenbanken
 *
 * @throws Example_Datasource_Exception wenn keine der gewählten
 *         Datenbank angesprochen werden konnte.
 *
 * @throws Example_Config_Exception wenn keine Datenbanken
 *         konfiguriert wurden
 */

function connect(Config $conf) 
{
    $dsns =& $conf->searchPath(array('config', 'db'));
    if ($dsns === FALSE) throw new Example_Config_Exception(
        'Unable to find config/db section in configuration.'
    );

    $dsns =& $dsns->toArray();

    foreach($dsns as $dsn) {
        try {
            $this->connectDB($dsn);
            return;
        } catch (Example_Datasource_Exception e) {
            // Warn-/Logging-Code um den Verbindungsfehler
            // aufzuzeichnen
        }
    }
    throw new Example_Datasource_Exception(
        'Unable to connect to any of the configured databases'
    );
}
?>

Das zweite Beispiel zeigt, wie eine Exception empfangen und behandelt wird. Die verwendete connectDB()-Methode kann nur einen Fehler melden, wenn die Verbindung fehlschlägt. Die übergeordnete Methode connect() hingegen weiss, dass das Objekt auch mit einer der anderen Datenbank-Verbindungen lauffähig ist. Deshalb kann der Fehler als behoben angesehen werden und die Exception wird nicht weitergeleitet.

Beispiel 4-3. Unvollständige Behebung

<?php
/**
 * loadConfig wertet die angegebene Konfiguration aus. Wenn die
 * Konfiguration unkorrekt ist, dann wird auf die Standard-
 * zurückgegriffen
 *
 */
function loadConfig(Config $conf) 
{
    try {
        $this->config = $conf->parse();
    } catch (Config_Parse_Exception e) {
        // Warn-/Logging-Code
        // Unvollständige Fehlerbehebung
        $this->config = $this->defaultConfig;
    }
}
?>

Die Fehlerbehebung führt zu Seiteneffekten, deshalb ist sie nicht vollständig. Das Programm kann weiterlaufen, die Exception gilt als behandelt und muss nicht weitergeleitet werden. Wie im vorherigen Beispiel sollte die aufgetretene Exception aber trotzdem geloggt werden oder eine andere Form der Warnung stattfinden.

Fehler-Benachrichtigung PHP 5 PEAR-Packages

Fehlerhafte Zustände in PEAR-Packages für PHP 5 müssen über Exceptions gemeldet werden. Nicht mehr verwendet werden sollten Fehlercodes oder ein PEAR_Error-Objekt. Diese Regel gilt natürlich nicht, wenn das Package kompatibel mit PHP 4 bleiben muss. In diesem Fall gelten die Konvention der PEAR Coding Standards unter PHP 4 weiter.

Eine Exception sollte immer geworfen werden, wenn ein fehlerhafter Zustand auftritt, entsprechend der Definition im vorherigen Abschnitt. Die geworfene Exception sollte genügend Informationen enthalten, um den Fehler debuggen zu können und schnell dessen Grund herauszufinden. Bedenken Sie, dass in Produktionsumgebungen keine Exception an den Endanwender durchdringen sollten. Deshalb muss man sich keine Gedanken machen über die Komplexität der Fehlermeldung.

Die Basis-Klasse PEAR_Exception enthält eine wörtliche Beschreibung des Fehlers, womit der Programmzustand beschrieben wird, der zum Fehler führte, und - optional - Execptions, die durch untergeordnete Programmaufrufe herbei geführten wurden und die ursprüngliche Ursache des Fehlers darstellen können.

Die Arten von Informationen die in einer Exception enthalten sein müssen, hängt von der Art des Fehlers ab. Es gibt drei Varianten von Exceptions:

  1. Fehler, die während der Vorabprüfung auftreten können.
  2. Fehler, die durch untergeordneten Bibliotheksaufrufe auftreten und durch Fehlercodes oder -Objekte signalisiert werden
  3. Nicht-korrigierbare Exceptions von untergeordneten Bibliotheken.

Fehler, die während der Vorabprüfung auftreten können, sollten eine Beschreibung der fehlgeschlagenen Prüfung enthalten. Wenn möglich sollte der fehlerhafte Wert mit angegeben werden.

Beispiel 4-4.

<?php
function divide($x, $y)
{
    if ($y == 0) {
        throw new Example_Aritmetic_Exception('Division by zero');
    }
}
?>

Fehler, die durch untergeordneten Bibliotheksaufrufe auftreten und durch Fehlercodes oder -Objekte signalisiert werden, sollten in Exceptions umgewandelt werden, wenn diese nicht behoben werden können. Die Fehlerbeschreibung sollte die originale Fehlerinformationen enthalten bzw. entsprechend konvertiert werden. Am Beispiel der obigen connect()-Methode:

Beispiel 4-5.

<?php
/**
 * Verbinde zur angegebenen Datenbank
 *
 * @throws Example_Datasource_Exception wenn der Verbindungsaufbau fehlschlägt
 */
function connectDB($dsn) {
    $this->db =& DB::connect($dsn);
    if (DB::isError($this->db)) {
        throw new Example_Datasource_Exception(
                "Unable to connect to $dsn:" . $this->db->getMessage()
        );
    }
}
?>

Nicht-korrigierbare Exceptions von untergeordneten Bibliotheken sollten weitergeleitet oder erneut geworfen werden. Wenn sie weitergeleitet werden soll, dann behandeln Sie die Exception nicht weiter. Wenn Sie die Exception erneut werfen, dann müssen Sie die originale Exception in der neuen Exception verpacken.

Beispiel 4-6. Eine Exception neu verpacken

<?php
function preTaxPrice($retailPrice, $taxRate) 
{
    try {
        return $this->divide($retailPrice, 1 + $taxRate);
    } catch (Example_Aritmetic_Exception e) {
        throw new Example_Tax_Exception('Invalid tax rate.', e);
    }
}
?>

Beispiel 4-7. Eine Exception weiterleiten

<?php
function preTaxPrice($retailPrice, $taxRate) 
{
    return $this->divide($retailPrice, 1 + $taxRate);
}
?>

Die Entscheidung, ob eine Exception neu verpackt oder weitergeleitet werden soll, ist eine Frage der Software-Architektur. Exceptions sollten weitergeleitet werden, ausser in zwei Fällen:

  1. Die originale Excpetion ist von einem anderen Package. Wenn diese weitergeleitet wird, dann würden Details der Implementierung nach aussen dringen.
  2. Die Methode kann nützliche Debug-Informationen ergänzen.

Exceptions und der normale Programmfluß

Exceptions sollten niemals als Bestandteil des normalen Programmflußes benutzt werden. Wenn alle Logik zur Behandlung von Exceptions entfernt würde (try-catch-Statements), dann sollte der verbliebende Code den "wahren Pfad" repräsentieren – dem Programmfluß, wenn keinerlei Fehler auftreten würden.

Diese Forderung entspricht der Erwartung, dass Exceptions nur bei fehlerhaften Zuständen geworfen werden sollten und niemals bei regulären Zuständen.

Ein Beispiel für die falsche Benutzung der Exception-Weiterleitung ist die Rückgabe eines Wertes eines rekursiven Aufrufs:

Beispiel 4-8.

<?php
/**
 * Rekursive Suche in einem Baum nach einem String
 * @throws ResultException
 */
public function search(TreeNode $node, $data)  
{
    if ($node->data === $data) {
         throw new ResultException( $node );
    } else {
         search( $node->leftChild, $data );
         search( $node->rightChild, $data );
    }
}
?>

Im Beispiel wird die ResultException benutzt, um "schnell" wieder aus der Rekursion heraus zu kommen. Das ist im Fehlerfall tatsächlich praktisch, in diesem Fall, aber nur ein Beispiel für einen faulen Programmierer. Die Klassen-Hierarchie von Exceptions

Alle Exceptions, die von Packages geworfen werden, müssen von PEAR_Exception abstammen. PEAR_Exception bietet zusätzliche Fähigkeiten, um andere Exceptions zu verpacken. Sie finden diese nicht in der obersten PHP Exception-Klasse, sind aber notwendig, um die oben gestellten Anforderungen zu erfüllen.

Zusätzlich sollte jedes PEAR-Package seine eigene Exception-Klasse definieren; der Name der Klasse entspricht dem Muster: <Package_Name>_Exception. Jede Exception sollte von dieser Klasse abgeleitet werden. Exceptions dokumentieren

Da PHP, im Gegensatz zu Java, es nicht erfordert, mögliche Exceptions in der Funktionssignatur aufzunehmen, ist deren sorgfältige Dokumentation im Methodenkopf wichtig.

Beispiel 4-9. Exceptions werden dokumentiert mit dem @throws-Schlüsselwort

<?php
/**
 * Diese Methode sucht nach Aliens.
 *
 * @return array Array von Alien-Objekten.
 * @throws AntennaBrokenException wenn die Impedanz-Leser anzeigt, dass die
 *         Antenne nicht funktioniert
 *
 * @throws AntennaInUseException wenn ein anderer Prozess die Antenne
 *         bereits benutzt
 */
public function findAliens($color = 'green');
?>

In vielen Fällen wandelt die mittlere Schicht einer Anwendung Exceptions von untergeordneten Methoden in aussagekräftiger, anwendungsspezifische Exceptions. Das sollte ebenfalls angesprochen werden:

Beispiel 4-10.

<?php
/**
 * Lade Session-Objekte in den Shared-Memory
 *
 * @throws LoadingException Jede untergeordnete IOException wird als
 *         LoadingException neu verpackt.
 */
public function loadSessionObjects();
?>

In anderen Fällen kann ihre Methode als Filter fungieren, der nur bestimmte Exceptions weiterleitet. Dann sollten Sie dokumentieren, welche Exceptions nicht von Ihrer Methode abgefangen werden.

Beispiel 4-11.

<?php
/**
 * Führt eine Reihe von Datenbankanfragen aus (atomar, nicht innerhalb einer Transaktion).
 * @throws SQLException Low-level SQL-Fehler werden direkt weitergeleitet.
 */
public function batchExecute();
?>

Exceptions als Teil der API

Exceptions spielen eine kritische Rolle in der API ihrer Bibliothek. Entwickler, die Ihre Bibliothek verwenden, sind abhängig von der angemessenen Beschreibung wo und warum Exceptions auftreten in Ihrem Package. Auch die sorgfältige Planung der Fehlermeldungen ist ein wichtiger Faktor für die Erhaltung der Rückwärts-Kompatibilität.

Da Exceptions ein integraler Bestandteil der API ihres Packages sind, darf bei Änderungen daran die Rückwärts-Kompatibilität (BC) nicht grundlos gebrochen werden.

Dinge, die zum Bruch führen:

  • Jede Änderung an Methoden, die Exceptions werfen.
  • Wenn eine Exception-Klasse verwendet wird, die höher in der Vererbungskette liegt, als die ursprüngliche. Zum Beispiel, wenn Sie in einer neueren Version eine PEAR_Exception werfen würden, in der alten aber z.B. PEAR_IOException verwendet haben.

Dinge, die nicht zum Bruch führen:

  • Wenn eine abgeleitete Klasse der originalen Exception verwendet wird. Zum Beispiel, wenn Sie in der aktuellen Version eine PEAR_IOException werfen, und in älteren Versionen PEAR_Exception. Natürlich nur unter der Voraussetzung, dass PEAR_IOException von PEAR_Exception) abgeleitet ist.

Best practices

Es gibt einige andere Dinge, die nicht vom PEAR Coding Standard betroffen sind, sondern von den persönlichen Gewohnheiten abhängen und nicht die Lesbarkeit unmittelbar berühren. Das betrifft z.B. die Frage 'Einfache oder doppelte Anführungszeichen'. Es handelt sich um Konstrukte, welche die Programmierung vereinfachen ohne konkrete Probleme zu verursachsen. Welche dieser 'üblichen' Praktiken genutzt wird, diese Entscheidung ist dem Programmierer überlassen. Wichtiger ist die konsequente Anwendung der eigenen Entscheidung in einem Package. Respektieren Sie die Entscheidung des verantwortlichen Programmierers, wenn Sie fremde Packages verändern.

Beispieldatei inklusive Docblock-Kommentaren

Der Quellcode von PEAR-Packages wird von tausenden von Menschen gelesen. Genauso kann es passieren, dass andere einmal an Ihrem Package entwicklen werden. Um es ihnen leichter zu machen, ist die Formatierung des Quellcode und der Docblöcke standarisiert. Damit können Andere Informationen einfacher finden, das sie wissen, wo sie suchen müssen.

Jeder Docblock im Beispiel enthält viele Details wie Sie die Kommentare schreiben sollten. Diese Instruktionen sind aus zwei Gründen wichtig. Erstens können Benutzer und Entwickler schneller verstehen, was Ihr Code tut. Zweitens wird auf der PEAR-Webseite die Quellcode-Dokumentation für jedes Release von jedem Package bereitgestellt und Sie sollten auch dafür sorgen, dass diese Möglichkeit sinnvoll genutzt werden kann.

Bitte achten Sie auch auf den Einsatz von vertikalen und horizontalen Leerräumen. Sie sind Bestandteil der Standards.

Die „Fold Markers“ (// {{{ und // }}}) sind optional. Wenn Sie nicht benötigt werden, entfernen Sie die Einstellung foldmethod=marker aus dem Block mit Vim-Einstellungen.

<?php

/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */

/**
 * Kurze Beschreibung des Datei-Inhalts
 *
 * Lange Beschreibung des Datei-Inhaltes, wenn erforderlich.
 *
 * PHP versions 4 and 5
 *
 * LICENSE: This source file is subject to version 3.0 of the PHP license
 * that is available through the world-wide-web at the following URI:
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
 * the PHP License and are unable to obtain it through the web, please
 * send a note to license@php.net so we can mail you a copy immediately.
 *
 * @category   CategoryName
 * @package    PackageName
 * @author     Original Author <author@example.com>
 * @author     Another Author <another@example.com>
 * @copyright  1997-2005 The PHP Group
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
 * @version    CVS: $Id:$
 * @link       http://pear.php.net/package/PackageName
 * @see        NetOther, Net_Sample::Net_Sample()
 * @since      File available since Release 1.2.0
 * @deprecated File deprecated in Release 2.0.0
 */

/**
 * Das ist ein "Docblock-Kommentar", auch bekannt als "docblock"/"Docblock"
 * Der Klassen-Docblock weiter unten enthält eine Beschreibung wie sie
 * geschrieben werden.
 */
require_once 'PEAR.php';

// {{{ constants

/**
 * Methoden geben diesen Wert im Erfolgsfall zurück.
 */
define('_NET_SAMPLE_OK', 1);

// }}}
// {{{ GLOBALS

/**
 * Die Anzahl der erzeugten Objekte
 * @global int $GLOBALS['NET_SAMPLE_Count']
 */
$GLOBALS['_NET_SAMPLE_Count'] = 0;

// }}}
// {{{ Net_Sample

/**
 * Ein Beispiel wird Code entsprechend der PEAR-Standards aussieht
 *
 * Anmerkung des Übersetzers: Quelltext-Kommentare sollten natürlich
 * durchgängig in Englisch erfolgen!
 *
 * Ein Docblock-Kommentar beginnt mit "/**" am Anfang.  Beachten Sie, das "/"
 * beginnt mit der normalen Einrückung und die Sterne darunter stehen in der
 * selben Textspalte wie der erste Stern. Der letzte Zeile des Kommentar-Blocks
 * sollte unmittelbar das zu dokumentierende Element folgen,
 * Vermeiden Sie zusätzliche Leerzeilen. Ergänzen Sie eine Leerzeile
 * zwischen Absätzen im Kommentartext, genauso zwischen Kommentartext und dem
 * ersten @-Tag. Ein Zeilenumbruch im Kommentartext sollte nach 80 Zeichen
 * erfolgen.
 *
 * Docblöcke können nur für eine begrenzte Anzahl an Elementen verwendet
 * werden (Klassen, Eigenschaften, Methoden, Konstanten, Include und
 * globale Variablen. In der Dokumentation zu phpDocumentor finden Sie mehr
 * Informationen dazu:
 * http://phpdoc.org/docs/HTMLSmartyConverter/default/phpDocumentor/tutorial_phpDocumentor.howto.pkg.html
 *
 * Der Javadoc Style Guide ist eine exzellente Quelle wie man Kommentare
 * formulieren sollte. Letztlich sind diese Informationen eine Zusammenfassung
 * davon, andererseits gibt es aber auch einige Abweichungen davon.
 * http://java.sun.com/j2se/javadoc/writingdoccomments/index.html#styleguide
 *
 * Diese erste Zeile jedes Docblocks ist eine Zusammenfassung. Sie sollte
 * genau einen Satz umfassen, ohne Punkt am Ende. Zusammenfassungen für
 * Klassen, Eigenschaften und Konstanten sollten nicht deren Namen enthalten
 *
 * Die unten aufgeführten Tag werden üblicherweise für Klassen benutzt.
 * Die Tags @category bis @version sind erforderlich. Die Übrigen
 * sollten ergänzt werden, wenn erforderlich. Verwenden Sie die Tags
 * in der Reihenfolge, wie hier aufgeführt. phpDocumentor bietet
 * weitere Tags, verwenden Sie diese, wenn erforderlich.
 *
 * @category   CategoryName
 * @package    PackageName
 * @author     Original Author <author@example.com>
 * @author     Another Author <another@example.com>
 * @copyright  1997-2005 The PHP Group
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
 * @version    Release: @package_version@
 * @link       http://pear.php.net/package/PackageName
 * @see        NetOther, Net_Sample::Net_Sample()
 * @since      Class available since Release 1.2.0
 * @deprecated Class deprecated in Release 2.0.0
 */
class Net_Sample
{
    // {{{ properties

    /**
     * Der Zustand von foo's universe
     *
     * Potentielle Werte sind 'good', 'fair', 'poor' und 'unknown'.
     *
     * @var string
     */
    var $foo = 'unknown';

    /**
     * The status of life
     *
     * Vergessen Sie nicht, dass private Elemente mit einem
     * Unterstrich beginnen müssen.
     *
     * @var bool
     * @access private
     */
    var $_good = true;

    // }}}
    // {{{ setFoo()

    /**
     * Registriert den Zustand des Foo-Universums
     *
     * Die Zusammenfassung für eine Methode sollte besser in der 3. Person 
     * Einzahl statt in der 2. Person formuliert werden.
     * Das Verb sollte am Anfang stehen.
     *
     * Die Zusammenfassung sollte mehr Informationen liefern, die über den
     * Methodennamen hinaus gehen. Die besten Methodennamen sind
     * selbst beschreibend, sie sagen was die Methode im Grunde macht.
     * Wenn die Zusammenfassung den Methodennamen nur in Form eines
     * Satzes wiederholt, liefert sie keine zusätzlichen Informationen.
     *
     * Beispiele für die Zusammenfassung:
     *   + Sets the label              (empfohlen)
     *   + Set the label               (vermeiden)
     *   + This method sets the label  (vermeiden)
     *
     * Als nächstes werden die üblichen Tags für Methoden angeführt.
     * Ein @param-Tag muss für jeden Parameter angegeben werden.
     * Die Tags @return und @access sind wahlfrei. Das @throw-Tag
     * muss angegeben werden, wenn die Methode Exceptions wirft.
     * Das Tag @static ist erforderlich, wenn die Methode statisch
     * aufgerufen werden kann. Die übrigen Tags brauchen Sie nur
     * angeben, wenn diese benötigt werden. Bitte geben Sie die
     * Tags in der Reihenfolge an, wie sie hier aufgeführt sind.
     * phpDocumentor bietet weitere Tags, benutze Sie diese, wenn
     * es sinnvoll ist.
     *
     * Das @param-Tag umfasst den Datentypen, den Parameter-Namen, gefolgt
     * von einer Beschreibung. Per Konvention sollte die Beschreibung beginnen
     * mit dem Datentyp, dem ein Artikel ("a", "an" oder "the") vorangestellt
     * werden kann. Setzen Sie zwei Leerzeichen zwischen dem Namen
     * des Parameters und seiner Beschreibung für eine bessere Lesbarkeit.
     *
     * Wenn Sie einen Satz schreiben, starten Sie nicht mit einem
     * Großbuchstaben und beenden Sie ihn nicht mit einem Punkt:
     *   + the string to be tested
     *
     * Wenn Sie mehr als einen Satz schreiben, setzen Sie einen Punkt und
     * beginnen Sie den zweiten Satz mit einem Großbuchstaben:
     *   + the string to be tested. Must use UTF-8 encoding.
     *
     * Das @return-Tag sollte den Datentyp und eine Beschreibung des
     * zurückgegebenen Wertes enthalten. Der Datentyp kann einer von PHP's
     * Datentyp sein (int, float, bool, string, array, object, resource, mixed)
     * und sollte den primär zurückgegebenen Wert enthalten. Z.B.
     * eine Methode gibt korrekterweise ein Objekt zurück und nur im
     * Fehlerfall 'false', dann sollten Sie 'object' angeben statt
     * 'mixed'. Verwenden Sie 'void' wenn nicht zurückgegeben wird.
     *
     * Hier ein Beispiel für Quellcode-Texte:
     * <code>
     * require_once 'Net/Sample.php';
     *
     * $s = new Net_Sample();
     * if (PEAR::isError($s)) {
     *     echo $s->getMessage() . "\n";
     * }
     * </code>
     *
     * Hier ein Beispiel für Nicht-PHP-Code:
     * <samp>
     * pear install net_sample
     * </samp>
     *
     * @param string $arg1  the string to quote
     * @param int    $arg2  an integer of how many problems happened.
     *                       Rücken Sie nachfolgende Zeilen in der Beschreibung
     *                       entsprechend ein.
     *
     * @return int  the integer of the set mode used. FALSE if foo
     *               foo could not be set.
     * @throws exceptionclass  [description]
     *
     * @access public
     * @static
     * @see Net_Sample::$foo, Net_Other::someMethod()
     * @since Method available since Release 1.2.0
     * @deprecated Method deprecated in Release 2.0.0
     */
    function setFoo($arg1, $arg2 = 0)
    {
        /*
         * Das ist ein "Block Kommentar". Das Format entspricht
         * den obigen Kommentaren, mit der Ausnahme, das der Kommentarbeginn
         * nur einen Stern enthält.
         * phpDocumentor wertet diese nicht aus.
         */
        if ($arg1 == 'good' || $arg1 == 'fair') {
            $this->foo = $arg1;
            return 1;
        } elseif ($arg1 == 'poor' && $arg2 > 1) {
            $this->foo = 'poor';
            return 2;
        } else {
            return false;
        }
    }

    // }}}
}

// }}}

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * c-hanging-comment-ender-p: nil
 * End:
 */

?>

 

 

Quelle: Basis-Wiki-Hilfe | Letzte Änderung: 01.04.2011 23:21 Uhr, tthelen | Local view: Basis-Hilfe