Perl-Programmierung: Stil und Struktur


Kommentare

Bearbeiten

Kommentare sollten gut und reichlich verwendet werden. Es ist kein Fehler, wenn das Verhältnis zwischen Kommentaren und effektivem Code bei 1:1 liegt. Da man in Perl sehr kompakten Code schreiben kann, ist bei veröffentlichtem Code vom CPAN ein Verhältnis 2:1 und darüber völlig normal.

Zu unterscheiden sind dabei die zwei verschiedenen Formen von Kommentar, die Perl erlaubt.

Die einfachste Form ist die Kommentarzeile, die alles hinter dem #-Zeichen bis zum Zeilenende beinhaltet. Daneben unterstützt Perl von Haus aus ein Werkzeug für eingebettete Dokumentation. Dieses trägt den Titel Plain Old Documentation oder kurz POD. Es erlaubt ähnlich WikiSyntax einfache Formatierungen und Verknüpfungen.

Direkt nach der Shebang-Zeile sollte der Programmname aufgeführt werden. Das ist hilfreich, weil man häufig mit less oder more sich mehrere Quelltexte in Folge zu Gemüte führt, und man sich so orientieren kann, in welchem Skript man sich gerade befindet. Das ist auch praktisch, wenn man die Möglichkeit hat, Programmlistings auf Endlospapier zu drucken.

Anschließend sollte eine ausführliche Programmbeschreibung inline in den Quelltext eingearbeitet werden. Bei Teamprojekten ist es außerdem sinnvoll, den Namen des Autors zu hinterlegen, sowie Modifikationen festzuhalten mit Beschreibung der Modifikation, Datum und Name des modifizierenden Autors.

Häufig ist es außerdem sinnvoll, Unterfunktionen, Schleifen und Verzweigungen mit beschreibenden Kommentaren zu bedenken. Meilensteine/Wendepunkte in der Programmlogik sollten mit einem markierenden/benennenden Kommentar versehen werden. Auch wichtige Variablen sollten mit einem Kommentar beschrieben werden.

Der Deklarationsteil

Bearbeiten

Die Variablendeklaration sollte der Übersichtlichkeit halber ausschließlich zu Beginn der Funktion (bei der Hauptfunktion zu Beginn des Programms) erfolgen. Die Programmlogik sollte sich klar vom Deklarationsteil abheben, und diesem nachfolgen.

Variablen sollten in erster Linie lokal innerhalb der Funktionen verwendet werden. Globale Variablen sollten auf das absolut nötige Mindestmaß beschränkt bleiben. Wenn ein Fehler auf eine Variable zurückgeführt werden kann, dann schränkt sich der zu durchsuchende Quelltextbereich auf diese Weise extrem ein.

Die Variablenbezeichnung sollte, trotz des Mehraufwandes beim Tippen, nicht kryptisch, sondern verständlich sein. $countkunden, $countmitarbeiter und $countlieferanten sagt mehr als $ck, $cm und $cl, vor allem, wenn der Chef sagt, dass man das Programm mal für vier Wochen links liegen lassen soll, weil eine wichtige Auftragsarbeit anliegt.

use strict;

Bearbeiten

Wie schon beim "Hello World!"-Programm angedeutet, sollte der Perl-Programmierer grundsätzlich die Anweisung

use strict;

verwenden. Dadurch zwingt er sich selber, nur Variablen zu verwenden, die er vorher deklariert hat. Der augenfälligste Vorteil dabei ist, daß der Programmierer eine Fehlermeldung erhält, wenn ihm bei der Verwendung einer Variablen ein Tippfehler unterläuft. Unterlässt er dies, kann sich das in sehr merkwürdigen und unvorhergesehenen Programmabläufen und stunden- bis tagelangen Fehlersuchen äußern.

use warnings;

Bearbeiten

Mit dem Pragma „warnings“ werden in dem aktuellen Block Warnungen an- und abgeschaltet. Ohne dieses Pragma führt Perl stillschweigend viele Operationen durch, die der Programmierer so nicht gemeint, aber leider eingegeben hat. In folgendem Beispiel hat sich ein Tippfehler eingeschlichen:

  my $summe = "1:" + 2;

Ohne „use warnings“ wird die Operation stillschweigend durchgeführt. Mit diesem Pragma erfährt der Programmierer, dass etwas nicht stimmt:

use warnings;
my $summe = "1:" + 2;

ergibt die Warnung

 Argument "1:" isn't numeric in addition (+) at -e line 2.

Dieses Pragma ist in den manpages warnings und perllexwarn erläutert. In perldiag sind alle Warnungen aufgeführt, die Perl ausgibt.

selbstdefinierte Funktionen

Bearbeiten

Sobald sich Programmschritte wiederholen, sollten diese in eine Funktion ausgelagert werden. Damit wird der betreffende Code an einer Stelle zusammengefasst und nicht mehrfach über ein Programm verteilt. Die Fehlersuche und -behebung erleichtert dies ungemein, da dann nur in dieser einen Funktion gesucht werden muss und nicht an den vielen Stellen, die durch ein Kopieren eines Programmabschnittes entstanden sind.

Eine Funktion sollte wie ein gutes Werkzeug nur einen Zweck erfüllen, diesen aber dafür sehr gut. Dieser Zweck sollte sich in einem treffenden Namen niederschlagen.

Eine Funktion sollte wenn möglich auf keine nicht lokalen Variablen zugreifen und allein über ihre Argumente gesteuert werden.

Eine Funktion sollte mit POD dokumentiert werden. Dies ist unabhängig davon, ob sie exportiert wird oder nur zur internen Verwendung gedacht ist. Vermutlich wird der Autor der Funktion nach sechs Monaten nicht mehr wissen, warum er oder sie genau diesen Code für den Zweck gewählt hat, daher sollte dies kommentiert werden.

Querverweise: Siehe auch Perl-Programmierung: Subroutinen, Kommentar von Funktionen (in Perl-Programmierung: POD), nicht lokale Variablen (in Perl-Programmierung: Variablen)


Perl::Tidy

Bearbeiten

Um Perl-Code automatisch zu formatieren gibt es das praktische Werkzeug Perl::Tidy.

Bei wirklich umfangreichen Projekten ist ein Einsatz der Bibliotheken Log::Dispatch und Log::Log4Perl empfehlenswert, sie stellen ein ausgereiftes Logging Framework zur Verfügung. Eine kurze Einführung vom Author des letztgenannten Moduls ist hier zu finden: http://perlmeister.com/snapshots/200301/index.html .

Vorerst aber kann man es umgehen, sich dort einzuarbeiten. Völlig ausreichend bei mittelgroßen Projekten ist es, unterschiedlichste Laufzeitergebnisse in eine Log-Datei umzuleiten. Bei mir hat sich folgender, vielleicht noch ausbaufähiger Usus entwickelt:

Schritt 1:

#Deklarationsteil
my $loglevel=5;

Schritt 2:

#Anfang der Programmlogik
open (LOG, ">laufzeitausgaben.log") || die "Blabla\n";

.
.
.

#Ende der Programmlogik
close(LOG);

Schritt 3:

#Mitten in der Programmlogik
if($loglevel>4) {print LOG "VARIABLE 1: ". $variable1 . "\n";}

#oder
if($loglevel>6) {print LOG "VARIABLE 2: ". $variable2 . "\n";}

In diesem Beispiel würde die erste Logausgabe zugelassen, die zweite unterdrückt. Diese Möglichkeit ist erwünscht.

Mit dem numerischen Wert wird jeder Logausgabe eine Priorität zugewiesen, je wichtiger, desto kleiner. Mit einer kleinen Änderung im Deklarationsteil kann ab jetzt der Loglevel bestimmt werden, und damit der Detail-Grad der Logausgaben. Ohne groß zu stören, können die Ausgabezeilen jetzt im Quelltext verbleiben, bis sie gebraucht werden.