Entwicklerrichtlinien/Styleguide

Aus Delixs
Zur Navigation springen Zur Suche springen


Diese Seite ist momentan eine Baustelle im Zustand: 1

Wird bearbeitet von: Kirmse
Hilfe zum Bearbeitungsstatus: Hilfe:Status eines Artikels


Leben mit Debian: Die Entwickler Richtlinien

Alles was programmiert wird, soll sich an diese Richtlinien halten. Einige Dinge wie die Paketerstellung & -verwaltung, sowie die Konfiguration des Installers müssen sich auch an die "Debian Policy" halten.


Styleguide

Für das einheitliche Aussehen aller delixs-Werkzeuge, folgend "Admin-Interface" genannt, wird ein Styleguide erstellt.


Warum ein Styleguide?

Es handelt sich bei Quellcodes nach heute herrschender Meinung um technische Produkte und nicht um künstlerische Artefakte. Daher sind 'abgefahrene' und individuelle Formatierungen fehl am Platze. Es ist erwünscht, dass man bei den Quelltexten von mehreren Software-Entwicklern in einem Team nicht unterscheiden kann, wer welchen Code verfasst hat.

Es gibt eine weitere Argumentation, warum man soviel Wind um einen guten Stil macht. Das Boehm's Gesetz sagt, dass die Wartungskosten im Schnitt viermal größer sind als die Erstellungskosten. Das bedeutet, dass es sehr sinnvoll ist, den Code in Hinsicht Lesbarkeit zu optimieren.

Noch besser ist es, wenn in Hinsicht Verständlichkeit optimiert wird. Bitte immer vergegenwärtigen: einfach zu lesen und einfach zu verstehen ist nicht unbedingt das Gleiche.

Deshalb wurden für alle (Perl-)Scripte, die für dieses Projekt erstellt werden, die folgenden Festlegungen getroffen. Diese orientieren sich an der "Bibel für Perlprogrammierer", dem Buch "Perl Best Practices" von Damian Conway. Es geht hier nur darum, das der Quelltext auch von verschiedenen Programmierern wie "aus einen Guss" erscheint und damit hoffentlich gleich gut zu lesen ist. Es geht hier nicht darum, bestimmte Lösungen, auch wenn sie besser sind, zu propagieren oder/und durchzusetzen. Das Anliegen dieses Styleguides ist es nicht, Kenntnisse bzw. Tipps und Tricks zu vermitteln. Es wird deshalb auch nur ein ganz kleines Subset der Regeln dieses Buches hier herangezogen und auf Änderungen im Vergleich zu den dort angegebenen Regeln wird explizit hingewiesen. (Es ist damit kaum sinnvoll möglich, das bekannte Testmodul "Perl::Critic" einzusetzen.) In Hinblick auf die Kommentierung wird davon ausgegangen, dass eine typische Perldoc-Dokumentation erstellt wird, die aber debian-typisch als Man-Page bereitgestellt wird.

Codelayout

Klammerung

wir klammern generell im K&R-Stil:

my @names = (
  'schoffer', 
  'flesch',
  'kirmse'
)


oder

foreach my $zeile (@zeilen) {
  if ($zeile ne ) {   
    print $zeile;
  } 
} 


Schlüsselwörter

Schlüsselwörter bei Kontrollstrukturen sollen klar erkennbar sein und nicht fälschlich als Funktionsaufrufe interpretiert werden können. Zwischen Schlüsselwörtern und den Klammern schreiben Sie unbedingt Leerzeichen wie in den zwei gerade angegebenen Beispielen.

Im Gegensatz dazu: bei Unterroutinen und Variablennamen schreiben Sie die Klammern direkt hinter diese Bezeichner.

my $password = &get_password($datei);

oder

my $element = $hash[2]{$nummer}; 


Operatoren

Nutzen Sie (ein) Leerzeichen, um binäre Operatoren von den Operanden abzuheben.

my $tage = time / 3600 / 24; 


Einrückung

Verwenden Sie 2 Leerzeichen für eine Einrückungsebene Anm.: Conway - 4 Leerzeichen

while ($zeile = <DATEI>) {
  if ($zeile ne ) {
    ($erstes_element) = split ',', $zeile;
    print $erstes_element, "\n";
  }
}


Blöcke

Geben Sie niemals 2 Anweisungen in der gleichen Zeile ein

if ($a > $b) {   # tauschen von $a und $b
  $c = $b;
  $b = $a;
  $a = $c;
}


Else-Konstrukte

"Herzen" Sie das else nicht. Das bedeutet, das Folgendes NICHT in einer Zeile stehen soll:

} else {

sondern schreiben Sie es wie in dem folgenden Beispiel:

if ($a > $b) {
  print "$a ist größer als $b \n";
}
else {
  print "$a ist nicht größer als $b \n";
}


Namenskonventionen

Namen für Variablen

folgende Bildungsvorschrift liefert verständliche Bezeichner:

variable -> [adjektiv_]* substantiv

Beispiele: $naechster_client, $letzter_zeitpunkt, $aktueller_aufruf

Ein besonderer Fall sind Hashs und Arrays für Lookup-Tabellen. Hier ist folgende Bildungsvorschrift zu empfehlen:

lookup_variable -> [adjektiv_]* nomen präposition

Beispiele: %titel_von, %ISBN_fuer

Das liest sich dann im Quelltext so:


foreach my $buch (@katalog) {
  print "Buch: $titel_von{$buch} - ISBN: $ISBN_fuer{$buch} \n";
}


Namen für Subroutinen und Methoden

Vorschlag für Bildungvorschrift

routine -> imperatives_verb [_adjektiv]? _nomen

Beispiele: &lies_datensatz, &generiere_profil, &schreibe_aktuellen_zaehler


Boolsche Variablen bzw. Routinen

Diese Variablen und Routinen sollten (als Sonderfall) nach ihren Test benannt werden.

Beispiele: &ist_gueltig, $hat_fehlerhaften_datensatz_gefunden

if (&ist_gueltig($naechster_datensatz)) {
  # ...
}
else {
  $hat_fehlerhaften_datensatz_gefunden = 1;
} 


Referenzvariablen

Um sofort erkennen zu können, dass eine skalare Variable eine Referenz ist, sollte das Kürzel _ref angehangen werden.

$opts_ref, $user_ref ...
sub demo {
  my $parameter_ref = shift;
  my %parameter     = %{$parameter_ref};
  # ...
}


Hashs und Arrays

Benennen Sie (normalerweise) Hashs in der Einzahl und Arrays in der Mehrzahl. Bei Hash ist es häufig noch besser lesar, wenn dem singulären Nomen eine Präposition folgt.

Beispiele: %titel, %titel_von, %option, @ereignisse, @pcs ...


Unterstriche

Im Englischen werden Namen, die aus mehreren Wörtern bestehen, durch Bindestiche oder durch Leerzeichen "verbunden". z.B. "input stream", "double-click"

Da dies in Perl keine gültigen Bezeichner ergibt, ist nächstbeste Alternative der Unterstrich, wie sie in den vorangegangenen Beispielen verwendet wurden.

Die AlternativeMitEingestreutenGrossbuchstaben ist nicht so gut lesbar.


Gross- bzw. Kleinschreibung

Verwenden Sie

  • verwenden Sie nur Kleinbuchstaben für Variablen, Subroutinen und Methoden.
  • verwenden Sie die gemischte Gross- und Kleinschreibweise für Namen von Paketen und Klassen (z.B. Delixs::LDAP)
  • Verwenden Sie Grossbuchstaben für Filehandle und Konstanten (z.B. DATEI, MAX_ANZAHL, LEERZEICHEN)


Utility-Routinen

Stellen Sie Routinen, die nur für den internen Gebrauch bestimmt sind, einen Unterstrich voran

Beispiel: &_finde_groesste_uid

Da diese Hilfsfunktion nicht exportiert wird (besser: werden sollte), fällt der Bezeichner mit den Unterstrich am Anfang im Hauptprogramm doch hoffentlich auf. ;)


Konstanten

Verwenden Sie benannte Konstanten. Schreiben Sie diese mit Großbuchstaben.


use strict;
use constant LEERSTRING => ;
 
my $string = LEERSTRING;


HERE-Dokumente

Verwenden Sie HERE-dokumente, wenn Ihre Strings länger als 2 Zeilen sind. Verwenden Sie Quotingzeichen, wenn Sie Ihre HERE-Dokumente einleiten.

my $name =<< 'ENDE';
 (c) Hans-Dietrich Kirmse <hd.kirmse@gmx.de>, 2008
 Erasmus-Reinhold-Gymnasium Saalfeld, Thüringen
ENDE
 

Kontrollstrukturen

If-Blöcke

Vermeiden Sie die Verwendung von Postfix-if. Die Lesbarkeit ist so viel besser! (Ausnahmen siehe "Perl Best Practices")

richtig:

if ($zensur == 1) {
  print "super \n";
}

falsch:

print "super \n" if $zensur == 1;


andere Postfix-Modifikationen

Verwenden Sie niemals Postfix-Varianten von unless, for, while oder until.

richtig:

my $a = 1;
while ($a < 10) {
  print $a, "\n";
  $a++;
} 

Iteratorvariablen

Verwenden Sie bei Schleifen benannte Iteratoren, nicht $_ Deklarieren Sie eine Iterator-Variable immer mit my.


do/while-Schleifen

Verwenden Sie keine do ... while-Schleife

Neben der Tatsache, dass die sich schlecht liest, ist es keine Schleife erster Klasse. Das bedeutet, in dieser Schleife können Sie nicht next, last oder redo verwenden. (jedenfalls verhalten die sich nicht so, wie Sie es erwarten!)


Kommentare

Subroutinen

Geben Sie vor jeder Subroutine mindestens den Zweck (Funktion) und den Aufruf an.

# Funktion: diese Subroutine bestimmt das Maximum zweier Zahlen
# Aufruf: $groesste_zahl = &max(100, 75);
sub max {
  my ($zahl1, $zahl2) = @_;

  if ($zahl1 > $zahl2) {
    return $zahl1;
  }
  else { 
    return $zahl2;
  }
}

Absätze

Verwenden Sie ganzzeilige Kommentare, um einen Abschnitt zu erklären. Geht ein Abschnitt nicht mit einem ganzzeiligen Kommentar zu erklären, dann ist das ein Hinweis darauf, dass in mehrere Abschnitte aufgetreilt werden sollte.

# Funktion: diese Subroutine bestimmt den größten gemeinsamen Teiler zweier Zahlen
# Aufruf: $teiler = &ggt(100, 75);
sub ggt {
  my ($zahl1, $zahl2) = @_;
  my $hilf;

  # wiederhole solange, bis die Differenz der beiden Zahlen 0 ist
  while ($zahl1 - $zahl2 == 0) { 

    # die erste zahl muss die größere sein, sonst tauschen
    if ($zahl1 < $zahl2) {
      $hilf  = $zahl1;
      $zahl1 = $zahl2;
      $zahl2 = $hilf;
    }

    # wir bilden die Differenz 
    $differenz = $zahl1 - $zahl2;

    # wir streichen die größte Zahl
    $zahl1 = $zahl2;
    $zahl2 = $differenz; 
  }

  return $zahl1
}


Erläuterungen zu einer Zeile

Kommentieren Sie alles, was Sie verwirrtt oder getäuscht hat. Erläutern sie alles, was Sie entweder im Handbuch nachschlagen müssen oder über das Sie mehr als 5 Sekunden bei lesen nachdenken mussten.

$zahl = oct $zahl;  # aus 'octal' nicht nach 'octal'

Anm.: viele gehen davon aus, dass oct eine zahl ins Oktalsystem wandelt. Es ist aber genau anders herum.


technische Dokumentation

Wenn man für das Verstehen des folgenden Codes das Konzept erklären will, dann ist es unschön, einen Block von viele Kommentarzeilen zu verwenden. Verwenden Sie stattdessen ein POD-Block für einen Formatierer, den es nicht gibt ;)

=for Konzept:
   den ggt mit Hilfe des EUKLIDschen Algorithmus zu bestimmen ist 
   algorithmisch deutlich einfacher als über die Primfaktorzerlegung. 
   Der Nachteil ist, dass er in der Schule häufig nicht erklärt wird.

=cut

Beachten Sie, dass bei dieser Art der Formatierung nur ein Absatz in dem =for .. =cut-Block sein darf!


Qualitätssicherung

Wenn sie ihr Script bzw. ihre Lösung dem delixs-Projekt zur Verfügung stellen wollen, dann muss es wegen der langfristigen Sicherung des Supports bestimmten Ansprüchen genügen. Diese Qualitätsansprüche werden im Folgenden angegeben:

  • Passworte, Hostnamen, IP-Adressen oder kurz: sämtliche variablen Daten sind nie im Script direkt anzugeben, sondern sollten immer aus der jeweiligen Datei (Beispiel: "ldap.secret") eingelesen werden.
  • da jede Schule eine andere Suchbasis (hier LDAP-Base genannt) hat, sollte das Script diese aus der /etc/ldap.conf auslesen. Das kann so geschehen:
 # wir holen uns die Such-Basis ($ldap_base) aus der ldap.conf
 open DATEI, '<', '/etc/ldap.conf'
   or die "konnte ldap.conf nicht   oeffnen, $!\n";
 while (my $zeile = <DATEI>) {
   if ($zeile =~ m/^\s*base\s+(\w.*\w)\s*$/) {
     $ldap_base = $1;
     last;
   }
 }
 close DATEI;




zurück | Hauptseite

Kirmse 2008