Annotations in PHP sind böse

Was sind Annotations?

In der Software-Entwicklung werden Annotations verwendet, um die Dokumentation und Kommentierung des Quellcodes
zu verbessern. Für das ausführbare Programm sind Annotations völlig irrelevant.

Annotations unter PHP

In PHP findet man Annotations im Zusammenhang mit phpDoc-Kommentaren. PhpDoc-Kommentare werden verwendet, um Dateien, Klassen, Funktionen, Klassen-Eigenschaften und Methoden einheitlich zu beschreiben. Dort steht z.B. welche Parameter eine Funktion erwartet, welchen Rückgabewert es gibt oder welche Variablen-Typen verwendet werden.

Hier ein kleines Beispiel:

/**
 * Beschreibung der Datei.
 *
 * @author Name XYZ
 * @pacakge Lorem ipsum
 * @copyright Urherberrechtshinweis
 * @license GNU/GPL
 * @version 1.0
 */
 
/**
 * Beschreibung der Klassse.
 *
 * @category Dolor sit
 * @subpackage Lorem ipsum dolor
 */
class MeineKlasse
{
    /**
     * Beschreibung der Eigenschaft.
     *
     * @var integer
     */
    protected $eigenschaft = 0;
 
    /**
     * Beschreibung der Methode.
     *
     * @param integer $eigenschaft
     * @return boolean
     */
    public function setEigenschaft($eigenschaft)
    {
        $this->eigenschaft = $eigenschaft;
        return true;
    }
}

Die einheitliche Syntax der Kommentare wird unter anderem von den Entwicklungsumgebungen Zend Studio, Eclipse PDT oder NetBeans verwendet, um dem Entwickler weitere Informationen zu liefern. Außerdem nutzt der phpDocumentor die Kommentarblocks zur Generierung einer technischen Dokumentation.

Das klingt doch super. Warum sollten Annotations also böse sein?

Na ja, Annotations selbst sind vielleicht nicht böse, aber in einigen Fällen können sie böse werden. Z.B. dann, wenn man in Annotations Programmlogik versteckt. Also, wenn sich Annotations direkt auf das Verhalten des Programms auswirken.

So wird es leider im neuen TYPO3 5.0 Framework Flow3 gehandhabt. In Flow3 können Annotations u.a. eingesetzt werden, um Model-Eigenschaften zu validieren und das ist meiner Meinung nach keine gute Lösung. Denn Annotations sind ja erst einmal nur Kommentare und die werden bekanntlich vom Compiler (bzw. in PHP vom Interpreter) ignoriert. Leider ist PHP trotzdem in der Lage, durch die Reflection-API die Annotations auszuwerten. Hier wird also das Verhalten des Programms durch einen Kommentar direkt beeinflusst. Kommentare haben den Nachteil, das sie gerne überlesen oder entfernt werden und dann wird es umso schwieriger, eventuell auftretende Fehler zu finden.

Also liebe Entwickler von TYPO3 5.0 und alle anderen, die in Annotations gerne Programmlogik verpacken: Bitte überdenkt diese Programmierweise nochmals. Solange Annotations in PHP noch nicht als eigenes Sprachkonstrukt existieren (anders als in Java), sollten Kommentare immer entfernt werden können, ohne dabei das Verhalten des Programms zu beeinflussen.

Getter- und Setter-Methoden generieren

Was tun, wenn man eine Klasse mit mehreren Dutzend Member-Variablen hat und keine Lust dazu, für jede einzelne Getter- und Setter-Methoden zu schreiben? Natürlich automatisieren wir das Verfahren. Ich habe dazu drei Möglichkeiten herausgesucht. Da ist bestimmt für jeden etwas dabei.

Möglichkeit 1: Zend Studio
Wer eine lizensierte Version vom Zend Studio besitzt, kann sich hier die Getter und Setter ganz einfach über den Menüpunkt Source und Generate Getters and setters… erstellen lassen.

Möglichkeit 2: Magische Methode __call()
Wem das Zend Studio (verständlicherweise) zu teuer ist, der kann Getter- und Setter-Methoden auch über __call() abfangen und bearbeiten.
Einige halten dies jedoch für unsaubere Programmierung (Ich gehöre nicht dazu).

Möglichkeit 3: Ein eigenes Skript schreiben
Immer wenn es eine Aufgabe gibt, die sich häufig wiederholt, ist es sinnvoll, ein Skript dafür zu schreiben, das uns die Arbeit abnimmt. Wie oft ist es mir schon passiert, dass ich gesagt habe „das mach ich kurz selbst“ und am Ende wäre es viel schneller gewesen, ein Skript für die Aufgabe zu schreiben. Für Getter- und Setter-Methoden eignet sich ebenfalls ein kleines Skript. Meins sieht in etwa so aus:

class MeineKlasse
{
	protected $foo;
	protected $bar;
	protected $fooBar;
}
 
echo '<code>';
$class = new ReflectionClass(new MeineKlasse());
$properties = $class->getProperties();
$phpCode = '';
foreach($properties as $property)
{
	$name = $property->getName();
	if(strpos($name, '_') === 0)
	{
		$name = substr($name, 1);
	}
	$func = ucfirst($name);
	$phpCode .= "\n\npublic function get{$func}()\n";
	$phpCode .= "{\n";
	$phpCode .= "\treturn \$this->{$name};\n";
	$phpCode .= "}\n\n";
	$phpCode .= "public function set{$func}(\${$name})\n";
	$phpCode .= "{\n";
	$phpCode .= "\t\$this->{$name} = \${$name};\n";
	$phpCode .= "}";
}
echo $phpCode;
echo '</code>';

Das Skript nimmt sich die Klasse und lässt sich alle Member-Variablen geben. Anschließend nehme ich den Variablennamen und lasse mir daraus PHP-Code generieren.

Zukünftige Features in PHP 5.4 / PHP 6

Heute wage ich mal einen Blick in die Zukunft von PHP. Demnächst erscheint eine erste Alpha-Version zu PHP 5.4 mit einigen neuen Features. Ein paar der wichtigsten neuen Features möchte ich nun vorstellen. Ob tatsächlich alle der hier aufgeführten Features mit dem Release von PHP 5.4 fertig werden oder ob diese nicht für PHP 6 aufgeschoben werden, steht noch in den Sternen.

Type Hinting

Type Hinting ist eines der am meisten gewünschten Features in PHP. Dabei wird in der Parameterangabe von Funktionen und Methoden auch der Variablentyp mit übergeben. Ob und in welcher Form dieses Feature in einer der zukünftigen PHP Versionen erscheinen wird, muss noch diskutiert werden. Problematisch ist dabei u.a. das Verhalten, wenn ein falscher Typ angegeben wird. Soll ein Fehler ausgegeben werden oder wird die Variable einfach umgewandelt?

function addiere(int $x, int $y)
{
	return $x + $y;
}
 
var_dump(addiere("9", "1"));

Array dereferencing

Mit dieser Funktion lassen sich Array-Angaben direkt hinter einem Funktionsaufruf ausführen.

function getAnyArray()
{
	return array("Apfel", "Birne", "Banane");
}
 
echo getAnyArray()[2]; // Ausgabe: Banane

Aus meiner Sicht ein super nützliches Feature, weil man sich dadurch das Zwischenspeichern in eine Variable und damit eine Zeile Code sparen kann.

UTF-8 / UTF-16

Hier sind sich die PHP-Entwickler noch nicht ganz einig. Man möchte, dass die interne String-Behandlung mit einer der modernen Zeichenkodieriung wie UTF-8 oder UTF-16 arbeitet, aber das bringt viele Probleme mit sich. Außerdem steht noch offen, welche Zeichenkodierung verwendet wird. UTF-8 ist zum gängigen Standard geworden, UTF-16 dagegen würde die Ausführung verlangsamen, weil der Speicherverbrauch größer wird.

Traits (Mehrfache Klassenvererbung)

Mit Traits können Klassen von mehreren Elternklassen die Funktionalitäten erben. Im Moment lässt sich über extends immer nur eine Klasse erweitern.

Hier ein Traits-Beispiel:

trait PKW
{
	public function getGeschwindigkeit()
	{
		return 'xxx';
	}
}
 
abstract class Auto
{
	public function getKmStand()
	{
		return 'xxx';
	}
}
 
class Limousine extends Auto use PKW
{
	// ...
}
 
$meinAuto = new Limousine();
echo $meinAuto-&gt;getGeschwindigkeit();
echo $meinAuto-&gt;getKmStand();