Tel. 06151 / 39 10 793

Der Drupal 7 Survival-Guide – Teil 2

03.05.2012  • Marc Sven Kleinböhl 2
Der Drupal 7 Survival-Guide – Teil 2

Wie im letzten Teil bereits angekündigt handelt dieser Teil des Guides hauptsächlich von entwicklerischen Themen.
Performance-Optimierungen, Best-Practices und Coding-Style werden in diesem Teil des Guides das Thema sein.

Coding-Style

Da Drupal von der Community und deren zahlreich beigesteuerten Modulen lebt, hat man sich in der Drupal-Community recht früh auf gemeinsame Coding-Richtlinien geeinigt, damit das mit der Inter-Community-Arbeit auch reibungslos funktionieren kann.
Es sind größtenteils Richtlinien rund um Code-Formatierung. Aber auch Vorgaben zur Kommentierung von Funktionen.

Wer irgendwann seine selbst entwickelten Module an die Community spenden möchten, oder bestehende contributed Modulen patchen möchte, kommt nicht drum herum sich an diese Richtlinien zu halten.
Gleiches gilt in Zusammenarbeit mit anderen Drupal-Entwicklern.

Formatierung des Codes

In Drupal Codes gilt allgemein folgende Faustformel zur Formatierung des Codes:

  • 2 Spaces anstatt einem Tab zur Einrückung.
  • Blöcke (die mit den geschweiften Klammern) beginnen in der Zeile des einleitenden Keywords und enden einsam (in einer eigenen Zeile).
  • Alle Identifiers (Variablen-, Klassen-, Konstanten- und Methoden-Namen) werden klein geschrieben. Besteht ein Identifier aus mehreren Worten, werden diese durch Unterstriche getrennt.
  • Es sind ausschliesslich englische Bezeichnungen für Identifiers zu verwenden.
  • Nicht-Hook-Funktionen erhalten einen anführenden Unterstrich.
  • Alle Funktionen beginnen mit dem Modul-Namen als Namespace-Präfix.
  • Keine Zeile darf länger als 80 Zeichen lang sein. Spätestens ab dem 80ten Zeichen wird versucht, die Zeile umzubrechen. Umgebrochen wird hierbei ähnlich der Block-Methode.
    Die erste Klammer vor dem Umbruch bleibt auf der Zeile vor dem Umbruch, alle weiteren enden einsam.

Beispiel:

function mymodule_menu () {
 
  return array (
    'title' => 'Mein Modul',
    'page callback' => '_mymodule_site',
    'type' => MENU_CALLBACK
  );
}

function mymodule_site () {

  return t('Hello');
}

Es gibt auch ein tolles contributed Modul, mit dessen Hilfe sich Code daraufhin überprüfen lässt, ob er gemäß der Coding-Richtlinien Drupals formatiert wurde.
Das Modul nennt sich Coder und ist unter http://www.drupal.org/project/coder zu finden.
Es kann gerade anfangs sehr helfen das Modul zu nutzen, bis man sich sicher ist, seinen Code korrekt zu formatieren.

Kommentierung des Codes

In Drupal wird per Doxygen-Style kommentiert.
Das heißt, dass allen Dateien, Funktionen, Klassen und Methoden einen Kommentar-Kopf verpasst wird, der Doxygen Kommentierungs-Attribute enthält.
Bei Methoden und Funktionen sind das Attribute, die sowohl Parameter und Rückgabe-Werte als auch deren Aufgabe beschreiben.
Bei Dateien werden in der Regel Attribute für Autor und Änderungsdatum notiert sowie eine kurze, zusammenfassende Beschreibung der Aufgabe der Datei.
Dies sieht man jedoch selten bei Drupal-Modul-Dateien.

Kommentiert wird vornehmlich auf Englisch.

Beispiel für Funktionen:

/*
* This function does some fancy stuff.
* @param $age Describes the age of a user.
* @param $hobbies An array of hobbies of the user.
* @return TRUE on success.
*/
function _useredit_setage ($age, array $hobbies) {
}

Beispiel für Dateien:

/*
* @author Hroudtwolf
* @changed 12/10/2011
*
* This file contains all functions around editing users.
*/

Der große Vorteil dieser Art der Kommentierung liegt im automatisierten Erstellen von Dokumentationen.
Per Doxygen-Style dokumentierter Code liefert einer dafür geschaffenen Software genügend Informationen, API-Dokumentationen automatisiert zu generieren.
Doxygen selbst ist so eine Software.

http://sourceforge.net/project/doxygen

Es ist eine Art Code-Sniffer der einen Projekt-Ordner automatisch durchsuchen kann, um Doxygen-Kommentare zu finden und auszulesen.
Neben den Kommentaren findet Doxygen auch Funktions- und Klassen-Köpfe.

Auf diese Art sind auch die API-Dokumentationen der Drupal-Module entstanden.

Best Practices

Drupal ist eine komplexe und gleichsam mächtige Content-Management Software.
Es bietet eine Menge an API-Funktionen und Eigenheiten, auf die man als Entwickler besser eingehen sollte, um sich am Ende nicht die Performance oder gar die Integrität des eigenen Moduls oder Themes verbaut zu haben.

Ein paar der wichtigsten Best Practices bezüglich Drupal-Entwicklung möchte ich gerne nachfolgend erklären.

Die Neuerfindung des Rades

Gerade Einsteiger und Neulinge der Drupal-Entwicklung neigen dazu, viel zu viel selbst zu programmieren.
Sie erstellen Datenbank-Tabellen und Routinen, für die es in Drupal bereits Lösungen gibt, auch wenn es häufig auf den ersten Blick nicht direkt so scheint.
Das hat nicht selten zur Folge, dass diese Lösungen eher Workarounds gleichen und ähnlich robust sind.

Wer jedoch von Anfang an seine Entwicklungen mit Blick auf den Contracted Stuff (Content-Typen, Taxonomy, Ansichten, etc) konzipiert, ist letztlich auf der sicheren Seite.
Denn durch deren Einbeziehung entsteht erst die Integrität zum CMS und gegebenenfalls mit anderen Modulen.

Ich weiß das aus eigener Erfahrung. Da ich Ihnen davon berichte, müssen Sie meine vergangenen Fehler nicht wiederholen.
Daher mein Appell an Sie – Führen Sie am Anfang in den Konzeptionsphasen umfassende Researches durch, um dadurch die on-board Möglichkeiten Drupals in Ihre Entwicklungen einplanen zu können.

Hier mal das Wichtigste, das in der Planung Ihrer eigenen Module berücksichtigt werden sollte.

Inhalte

… unterschiedlicher Art werden durch sogenannte Nodes unterschiedlicher Typen repräsentiert.
Ein Node speichert einen solchen Inhalt. Drupal stellt dann jeweils eine eigene Eingabe-Maske für die Eingabe des Inhalts zur Verfügung und stellt den Inhalt bei Bedarf dar.
Die Standard-Node-Typen kommen mit 2 Inhalts-Feldern daher. Es sind ein Titel und ein Text-Körper.
Node-Typen (Content-Typen) sind frei erstellbar. Beim Erstellen eigener Node-Typen lassen sich sogar eigene Inhalts-Felder unterschiedlicher Daten-Typen (Text, Integer, …) definieren.
Nodes lassen sich zudem durch sogenannte Taxonomy-Terme taggen, worauf ich aber gleich noch eingehen werde.

Ansichten

…, sogenannte Views dienen dazu Inhalte (Nodes, Benutzer, Taxonomy-Terme) selektiv aufzulisten.
Dies kann in Tabellenform, Listenform oder einer Form geschehen, die ein Fremd-Modul erweiternd zur Verfügung stellt.
Views sind in ihren Eigenschaften frei konfigurierbar. So lassen sich zum Beispiel Anzeige-Filter (Suchbegriffe, Terme, Datenfeld-Inhalte) konfigurieren und auch definieren, welche Datenfelder aus Inhalten angezeigt werden sollen.

Taxonomy

...-Vokabulare sind Container für Begriffe, mit denen man Inhalte taggen kann.
Diese Begriffe werden „Terme“ genannt.
In Drupal 7 sind diese Vokabulare sogar eigene kleine Inhalts-Typen, welche um neue Datenfelder erweiterbar sind.

So fügt sich in Drupal alles zusammen und auch Ihre Module werden ein Teil des Ganzen, wenn sie auf diese Dinge setzen.
Vermeiden Sie grundsätzlich jede Implementierung redundanter Technologie. Wenn Sie stets auf das bauen, was Ihnen Drupal bezüglich Datenhaltung und funktionaler API bietet, haben Sie selten Probleme mit der Integration Ihrer Module in fremde Drupal-Installationen, haben automatisch einen Wartungs-Bonus weil Sie sich nur um die Modul-Logik kümmern müssen, da Sie den Rest an Verantwortung an Drupal abgeben, und Sie ermöglichen oft eine bessere Erweiterbarkeit Ihrer Module, auch durch Dritte.

Strukturierte Modul-Architektur

Dies ist meiner Ansicht nach eine der wichtigsten Best-Practices überhaupt in der Drupal-Entwicklung.
Ein Modul sollte meiner Ansicht nach aus logisch getrennten Komponenten bestehen, die sich erstn dann zusammen fügen, wenn dies notwendig wird.
Die Laufzeit eines Moduls benötigt relativ selten den gesamten Modul-Code. Was wann gebraucht wird, hängt oft von Benutzereingaben oder anderen Steuerquellen ab.

Das Verfahren zum nachladen von Code wenn er gebraucht wird nennt sich „Lazy loading“.

Ein weiterer Faktor, der bei der Aufsplittung des Codes eine Rolle spielen muss, ist der Aspekt.
Aspekte sind zum Beispiel der Entry-Point (Die Datei im Module-Ordner mit der Endung .module) in dem alle Hooks implementiert werden sollten, die das Module braucht, Include-Dateien für Datenhaltung (wobei hier Subaspekte Model-Klassen zu berücksichtigen für eigene sind), etwaige Templates für Ausgaben, usw.

Allgemeine Best-Practices

Da Drupal in PHP programmiert ist und auch mit PHP-Scripts erweitert wird, ist es selbstverständlich, dass die meisten Best-Practices aus der normalen PHP-Programmierung auch in der Drupal-Entwicklung gelten.

Ein paar dieser Best-Practices möchte ich jedoch hier niederschreiben. Denn immer wieder entdecke ich in contributed Modulen aus der Community, dass sie nicht eingehalten werden.
Es ist mir allerdings offengesagt wichtig, ein paar Leute dahingehend zu bekehren, diese auch einzuhalten.

Der Verzicht auf Doublequotes

Wenn Sie Literale schreiben, benötigen Sie selten Doublequote (doppeltes Hochkomma). Denn dieses ist nur dann notwenig, wenn Sie PHP dazu bringen wollen, den Inhalt Ihres Literals zu parsen, um dort zum Beispiel Variablen oder Escape-Sequenzen zu ersetzen.
Andernfalls gibt es keinen Grund die Doublequotes zu verwenden. Sie belasten nur die Gesamt-Performance. Denn wie schon geschrieben, werden diese Literale von PHP im Zweifel unnötig geparsed.
Nutzen Sie Doublequotes nur, wenn Sie diese Funktionalität auch wirklich jeweilig benötigen.

Vermeidung von magischen Zeichenketten

Magische Zeichenketten sind Zeichenketten, welche Sie zum Beispiel nicht zur Ausgabe nutzen sondern zur Programm-Flusskontrolle.
Also z.B. als Status-Strings.
Zum Einen gibt es relativ selten die Notwendigkeit Zeichenketten für so etwas einzusetzen. Denn das geht auf die Performance. Zum Anderen ist es relativ mühsam, programmweite Änderungen dieser Zeichenketten durchzuführen. Die Mühe steigt mit der Anzahl der Verwendung der Zeichenketten.
Deklarieren Sie stattdessen lieber Konstanten. Häufig können Sie dann auch komplett auf Zeichenketten verzichten und lieber die viel schneller zu verarbeitenden Integers als Werte für die Konstanten nutzen.

Ebenso sind auch magische Zahlen nicht gut für die Wartbarkeit eines Programms.
Auch für die können Sie einmal Konstanten definieren.

Wenn irgendwo in einem Switch-Case die magische Zahl 1234 vorkommt, stehen Sie eventuell wie der Ochs vorm Berg. Möglichweise benötigen Sie erstmal eine gewisse Zeit, um heraus zu finden, was die Magie hinter dieser Zahl wohl sein könnte.

Konstanten anstatt solcher magischen Werte zu verwenden ist wirklich praktisch.
Möchten Sie irgendwann die Werte ändern, können Sie das an einer einzigen Stellen anstatt an vielen durchführen.
Im Bestfall sparen Sie durch solche Vorgehensweisen also extrem viel Wartungszeit.

Fehler benötigen Aufmerksamkeit

In der Vergangenheit habe ich sehr oft erlebt, dass vor allen Programmier-Einsteiger dazu neigen, die Fehleranzeige-Einstellungen in der PHP-Ini Datei abzuschalten.
Tun Sie sich das bloß nicht an. Denn nur weil Sie keine Fehler und Warnungen sehen, sind sie nicht weg und können folgenschwere Wirkungen haben, bis hin zu Sicherheitslücken.
Fehler und Warnungen sind dazu da, auf sie einzugehen. Wenn Sie sie ignorieren, werden sie sich bei Ihnen rächen.

DRY

… damit ist „Don't repeat yourself!“ (engl.: „Wiederhole dich nicht!“) gemeint.
Vermeiden Sie es, ein und die selben Code-Passage oder gleiche Passagen mehrfach modulweit einzusetzten.
Erstellen Sie stattdessen konfigurierbare Funktionen für derartigen Code, deren Funktionsablauf Sie über Funktionsparameter steuern.

Close-Tag

Verwenden Sie in reinen PHP-Dateien am Ende der Datei niemals einen PHP-Close-Tag.
Dieser ist absolut nicht notwendig und führt häufig zu den sogenannten „White screen of death“ (engl. „Weißer Bildschirm des Todes“), wenn sich irgendwie hinter diese Close-Tags noch Zeichen geschmuggelt haben (Leerzeichen, Linebreaks, Tabulatoren...).
Das passiert recht schnell und ist je nach Software-Umfang aufwendig zu eruieren.

Atomare Funktionen

Eine PHP-Funktion sollte ihrem Schlüsselwort treu bleiben und „genau eine“ Funktion erfüllen.
Erst dann, wenn Ihre Funktionen nicht mehr in weitere Funktionen teilbar sind, haben Sie das erreicht.
Dies dient der Wiederverwendbarkeit von Funktionen, einem geringem Copy-/Paste-Faktor und der Lesbarkeit Ihres Codes.

Traue keinem Benutzer

Benutzer sind naturgemäß potentielle Sicherheitsrisiken.
Mit dieser Denkweise sollten Sie stets mit Benutzereingaben verfahren.
Drupal stellt hierfür Funktionen zur Verfügung.

Zum Beispiel die Funktionen „check_plain“ oder „filter_xss“.

Performance

Cachen, Cachen, Cachen...

Um performante Software zu erstellen, muss man an Arbeits-Belastung sparen.
Bereits akquirierte oder erstellte Daten können häufig in der selben Laufzeit oder sogar darüber hinaus wiederverwendet werden.
Das macht natürlich Sinn. Denn immer dann, wenn Daten geholt oder erstellt werden, entsteht eine Belastung für den Server.
Sehr oft verändern sich Daten einfach nicht über die Laufzeiten hinweg oder bei mehrfacher Akquirierung innerhalb derselben Laufzeit, so dass man sie natürlich wie sie sind für die Wiederverwendung wegspeichern kann.

Caching während der Laufzeit ist hier am simpelsten.
Nachdem eine Funktion Daten erstellt oder akquiriert hat, werden diese z.B. auf eine statische Variable abgelegt um sie bei erneutem Aufruf der Funktion innerhalb derselben Laufzeit wiederverwenden zu können.

Beispiel:

function getAllCustomerAddresses () {

  static $addresses = NULL;

  if ($addresses != NULL) {
    return $addresses;
  }

  // Code zum Besorgen der Adressen.

  $addresses = ….

  return $addresses;
}

Aber auch das Cachen über die Laufzeit eines Aufrufs hinaus ist nicht wesentlich komplizierter.
Drupal bieter hier aus seinem Caching-Layer Schnittstellen-Funktionen an, mit deren Hilfe das sehr einfach geht.
Das gleiche Beispiel von oben, nun mit Caching über die Laufzeiten hinweg.

function getAllCustomerAddresses () {

  $cache = cache_get ('all_customer_addresses');

  if ($cache->expire > time ()) {
    return $cache->data;
  }

  // Code zum Besorgen der Adressen.

  cache_set (
    'all_customer_addresses',
    $addresses,
    'cache',
    time () + MY_MAXIMUM_CACHE_TIME
  );

  return $addresses;
}

Konkrete Datenbank-Abfragen

Vermeiden Sie Datenbank-Abfragen mit Wildcards für die Felder.
Es wird potentiell langsamer, wenn bei jeder Datenbank-Abfrage alles von einem Datensatz geladen werden muss.
Einerseits ist dies arbeitsintensiver für die Datenbank und zudem wird das Antwort-Paket vom Datenbank-Server eventuell unnötig größer.
Konkretisieren Sie daher Ihre Datenbank-Abfragen, indem Sie ganz konkret angeben, welche Felder Sie aus dem Datensatz oder den Datensätzen benötigen.

Nächster Teil der Drupal-Survival-Guide Reihe

Im nächsten Teil der Survival-Guide Reihe gehe ich auf die Programmierung von Modulen ein unter Zurhilfenahme des Features-Moduls.
Dies ergänzt den zweiten Teil des Guides im Punkt Best-Practices, in dem wir besprochen haben, beim Programmieren eigener Module auf Drupals Fähigkeiten zu setzen.

Liebe Grüße und vielen Dank für Ihre Zeit
Marc Sven Kleinböhl

Coder seems to be outdated when it comes around coding-standart checks,
currently http://ventral.org/pareview is dominating in the project application queue

Bild von kleinboehl

Hi,

Thanks for your advice.

Best regards
Marc

Kommentar hinzufügen

Der Inhalt dieses Feldes wird nicht öffentlich zugänglich angezeigt.

Suchen


Newsletter

Melden Sie sich zu unserem kostenlosen Newsletter an. Wir informieren Sie regelmässig über unsere Leistungsangebote, Drupal Best-Practices, Mobile Apps, ERPAL Updates und Veranstaltungen.

Unsere Partner
comm-press comm-press
Drupal Spezialisten aus Hamburg
neosmart - Digital Media, Webdesign & Webentwicklung<br />
aus Darmstadt neosmart
Digital Media, Webdesign & Webentwicklung aus Darmstadt
trinomica - Software Solutions trinomica
Software Solutions
Sponsoring und Mitgliedschaften

Drupal Initiative Deutschland - Firmen-Mitglied

Wir sind Diamant Sponsors für das DrupalCamp Frankfurt 2014

So finden Sie uns