Coding Guidelines¶
Globale Programmierrichtlinen¶
- Die Sprache für Bezeichner ist Englisch
- Code muss in jeder unterstützen Umgebung laufen (Min.- und Max.-PHP, -MySQL beachten)
- Alle Bezeichner werden aussagekräftig und eindeutig definiert
- Auf keinen Fall Abkürzungen verwenden, die zweideutig sein können
- Bezeichner einer Klasse werden mit Großbuchstaben voneinander getrennt (UpperCamelCase)
- Keine magischen Zahlen
- Variablen in for-Zählschleifen werden mit einem Buchstaben definiert
- Code, der nicht benutzt wird, muss gelöscht werden
- Das letzte Element eines Arrays darf nicht mit einem Komma enden
- Nutzung von Gettern und Settern:
- Getter (get<Variablenname>) sollten stets den unveränderten Inhalt der Klassenvariablen zurückgeben. Getter, die den Inhalt manipulieren, sollten namentlich nicht direkt vom Variablennamen abgeleitet sein (also z. B. getFormated<Variablenname>).
- Setter (set<Variablenname>) sollten eine Validierung des übergebenen Wertes durchführen.
- Innerhalb von Klassen sollten die Klasseneigenen Getter- und Setter-Methoden nicht genutzt werden, sondern direkt auf die Klassenvariablen zugegriffen werden. Ausnahme: Bei der Nutzung von Daten aus nicht refaktorierten Quellen (z.B. globale Variablen) darf innerhalb einer Klasse ein eigener Setter genutzt werden, um solche Variablen vor dem Setzen zu validieren.
- AJAX-Response vom Server an den Client sollte möglichst im JSON-Format sein DRAFT: { 'success': true, 'payload' => data 'message' => 'messge' }
- Dateinamen sind klein zu schreiben, es sei denn, es handelt sich um eine Klasse. Dann heißt die Datei wie die Klasse.
- Bei neu erstellten Ordnern muss eine leere index.html Datei angelegt werden, damit der Ordner nicht aufrufbar ist. Sofern möglich auch einen .htaccess-Schutz für Ordner nutzen
- Don't trust user input. Daten von außen sind zu valdieren und Fehlerfälle abzufangen.
- Kommentare müssen aussagekräftig sein. Nicht etwa //START und //END
- Alle Schlüsselwörter werden klein geschrieben, z. B. ''if, for, foreach, as, while''
- Strings werden in einfachen Anführungszeichen ' geschrieben (Außnahme JSON, dort doppeltes Anführungszeichen vorgeschrieben sind)
- ternäre Ausdrücke sind, sofern leserlich, erlaubt
- Statement-Rümpfe sind in geschweifte Klammern zu setzen (auch einzeilige!)
- Immer typsichere Vergleiche verwenden (=== oder !==). Ausnahme: Werte die unterschiedliche false-Werte enthalten können (z.B. wenn sowohl „null“ als auch „0“ als „false“ gewertet werden soll. Dann kann eine if-Bedingung wie folgt geschrieben werden: if(abc){...}
- Als Default-False-Wert bei single-select-Feldern sollte „-1“ verwendet werden, sofern dies kein valider Wert für einen Datensatz ist.
- Auf deprecated-Funktionen verzichten
Dokumentation¶
- Die Sprache für Kommentare ist Englisch
PHP Programmierrichtlinen¶
- Benennung von Variablen und Funktionen erfolgt in lowerCamelCase-Notation
- Konstanten werden in Großbuchstaben defniert
- es wird
E_NOTICE
-,E_STRICT
- undE_DEPRECATED
-sicher programmiert (während des Programmierens zu aktivieren mittelserror_reporting(E_ALL);
am Anfang des Scripts). Dabei gelten Meldungen aus der höchsten PHP-Version, die wir unterstützen - PHP-Short-Tags sind nicht erlaubt: <?php statt <?
- Keinen schließenden PHP-Tag ?> in reinen PHP-Dateien, die keine Ausgabe erzeugen.
- Globale Variablen sind verboten
- Dateien, die PHP-Code enthalten, haben die Dateiendung .php
- includete Dateien haben die Dateiendung
.inc.php
und liegen niemals im Haupt- oder admin-Verzeichnis - Funktionen gehören in den
inc
, nicht in dengm/inc
-Ordner - Klassen gehören in den passenden
system
/GXEngine
-Unterordner, nicht in dengm/classes
-Ordner - ein
xtc_db_fetch_array()
, das nicht in einer while-Schleife ist, wird erst ausgeführt, wenn sichergestellt wurde, dass das result ein Ergebnis geliefert hat (xtc_db_num_rows()
bietet sich da an). - kein
exit
oderdie()
ohne vorheriges Schließen der Datenbankverbindung (xtc_db_close()) - jede PHP-Datei hat einen Gambio-GPL-Header
- Dateien, wie z. B. Log-Dateien, die sensible Daten enthalten und von außen erreichbar sind, sind mit einem Token im Namen zu schützen (Token generieren mittels
LogControl::get_secure_token()
) - Texte gehören in die Datenbank/Sprachdateien => keine hardgecodete Texte!!!
- Leerzeichen in Datei- und Ordnernamen sind nicht erlaubt => erlaubte Zeichen sind a-Z, 0-9, -, _, .
- Dateien, die Klassen oder Funktionen enthalten, sind mittels
require_once
oderinclude_once
einzubinden =>require
undinclude
sind Tabu! - Öffnende, geschweifte Klammern gehören in eine eigene Zeile
- Beim Casten kommt zwischen Datentyp und Variable kein Leerzeichen
Dokumentation¶
- PHPDoc ist Pflicht
Legacy-Code¶
- Globale Variablen sollten in Funktionen/Methoden nicht genutzt werden, sondern stattdessen als Klassenvariable oder Parameter übergeben werden. Führt kein Weg drum herum, sollte das
$GLOBALS
-Array zum Ansprechen der Variable verwendet werden
Regeln aus "Objektorientierte Programmierung" von thePHP.cc, die wir so für neue Projekte übernehmen¶
Regel: Eine Bildschirmseite
Eine Methode darf nicht länger als eine Bildschirmseite sein. Längere Methoden müs-
sen in mehrere kleinere Methoden heruntergebrochen werden.
Regel: Kleine öffentliche APIs
Die öffentliche API einer Klasse ist immer so klein wie möglich. Methoden sind stan-
dardmäßig privat/protected und werden nur dann öffentlich gemacht, wenn ihre Funktionalität
auch tatsächlich außerhalb der Klasse benötigt wird.
Regel: Deklarierte Instanzvariablen
Alle Instanzvariablen werden am Beginn der Klasse deklariert.
Regel: Minimale Sichtbarkeit
Attribute sind immer privat/protected. Es gibt keine öffentlichen Attribute.
Regel: Keine echte Arbeit im Konstruktor
Im Konstruktor werden Objekte in einen sinnvollen Ausgangszustand versetzt. Es fin-
det keine produktive Arbeit statt, insbesondere wird nicht auf das Dateisystem oder
auf externe Prozesse oder Systeme zugegriffen.
Regel: Dokumentierte APIs
Die API jeder Klasse wird immer mit DocBlocks kommentiert, die neben einer @return-
Annotation für jeden Parameter eine @param-Annotation enthalten.
Regel: Type Hints
Für Arrays und Objekte als Methoden- und Konstruktorparameter werden immer Type
Hints verwendet.
Regel: Code-Duplikation vermeiden
Code-Duplikation wird vermieden, indem Funktionalität an ein kollaborierendes Ob-
jekt delegiert wird.
Regel: Interfaces dokumentieren
Jede in einem Interface definierte Methode wird mit DocBlocks kommentiert, die ne-
ben einer @return-Annotation für jeden Parameter eine @param-Annotation enthal-
ten.
Regel: Interfaces als Type Hints
Anstelle Klassen als Type Hints zu verwenden, definieren Sie ein Interface, das die auf-
zurufenden Methoden enthält, und verwenden dieses als Type Hint.
Regel: Durchgängig Autoload
Klassen werden immer per Autoload geladen. Ein Autoloader sucht nicht, sondern
weiß bereits, aus welchen Dateien der benötigte Code zu laden ist.
Regel: Dependency Injection
Alle Abhängigkeiten eines Objektes werden in der API explizit gemacht und mittels
Dependency Injection an die Objekte übergeben.
Regel: Pflichtabhängigkeiten als Konstruktorparameter
Diejenigen Abhängigkeiten, die ein Objekt immer benötigt, werden zu Konstruktorpa-
rametern.
Regel: Komposition statt Vererbung
Vererbung kommt zur Wiederverwendung von Code nur im Rahmen einer ”ist-ein”-
Beziehung zum Einsatz. Ansonsten ist Objektkomposition (kollaborierende Objekte)
der Vererbung vorzuziehen.
Regel: Sinnvolle Rückgabewerte oder Exception
Rückgabewerte müssen verlässlich sein. Wenn Code keinen sinnvollen Rückgabewert
liefern kann, dann muss er eine Exception werfen.
Regel: Fehlerfortpflanzung vermeiden
Rückgabewerte von Code, der keine Exceptions verwendet, müssen frühzeitig und
möglichst strikt geprüft werden, um Fehlerfortpflanzung zu vermeiden.
Regel: Spezifische Exceptions
Exceptions müssen durch Subklassenbildung oder Exception-Codes spezifisch genug
sein, dass der aufrufende Code den Fehler sinnvoll verabeiten kann.
Regel: Benachrichtigungen und Warnungen sind Fehler
Programme dürfen keinerlei Fehlermeldungen, Warnungen oder Benachrichtigungen
der Typen E_NOTICE, E_USER_NOTICE, E_WARNING, E_USER_WARNING, E_USER_ERROR,
E_STRICT, E_DEPRECATED und E_USER_DEPRECATED erzeugen.
Regel: Wertobjekte sind unveränderlich
Wertobjekte können nach Initialisierung durch den Konstruktor nicht mehr verändert
werden.
Regel: Keine Arbeit im Destruktor
In Destruktoren wird niemals produktive Arbeit erledigt.
Regel: Explizite APIs
Explizite APIs sind impliziten APIs vorzuziehen.
Regel: Keine Singletons
Es gibt in PHP keinen validen Anwendungsfall für Singletons. Ihre Verwendung ist da-
her verboten.
SQL Programmierrichtlinen¶
- SQL-Befehle werden groß geschrieben
- INSERT-Anweisungen müssen die einzelnen Spalten für die VALUES-Klausel enthalten (am besten die
SET name = value, id = zahl
Schreibweise nutzen) - SQL-Befehle werden erst in einem String gespeichert, bevor sie ausgeführt werden
- Schlüsselworte (z. B. ''SELECT, AS, FROM, JOIN, WHERE, GROUP BY, ORDER BY, HAVING, LIMIT'') oder MySQL-Funktionen (z. B. ''NOW(), SUM(), IF'') werden groß geschrieben
- Zeilenumbrüche in SQL-Befehlen nach jeder angesprochenen Spalte und jedem Schlüsselwort
- Tabellenkonstanten müssen nicht mehr verwendet werden, da dies nicht konsequent im Shop angewendet wurde und somit der Nutzen nicht mehr gegeben ist
- keine Variable kommt ungeprüft/-filtert in einem SQL-Befehl
- Die Bezeichnung des Primärschlüssels ist im Singular und heißt, falls es sich um eine ID (Integer, i.d.R. auto_increment) handelt, meist id (kein Tabellennamen-Präfix).
- Spaltenbezeichnungen sind möglichst kurz zu halten, also
date
stattmy_table_date
, Abkürzungen, wie prd, grp sind aber zu vermeiden
JavaScript Programmierrichtlinen¶
- Benennung von Variablen und Funktionen erfolgen in der lowerCamelCase-Schreibweise
- Konstanten sollten nicht verwendet werden (keine zuverlässige Browserunterstützung)
- kein SQL in JavaScript
- Wenn möglich "name" & "value" von form-Feldern keine Tabellen- oder Spaltennamen der Datenbank zuweisen
- Es dürfen, bis auf für Funktions- oder Variablen-Sammlungen, welche die komplette Seite betreffen, keine globalen Variablen verwendet werden. Im Ausnahmefall ist eine Sammlung in Form eines JSONs zu verwenden, so dass das windows-Objekt möglichst klein bleibt.
- jede JS-Datei hat einen Gambio-GPL-Header
- JavaScripte sind sowohl komprimiert, als auch unkomprimiert auszuliefern (s. Javascript-Kompression)
- AJAX-Schnittstellen müssen wie REST-konforme Webdienste implementiert werden => Daten lesen per
GET
, Daten schreiben perPOST
(Achtung: Manche IE-Versionen verwenden bei GET den Browser-Cache! JQuery "cache: false" nutzen). Das bedeutet auch, dass in einer POST-Antwort keine Daten landen, die zur Anzeige gebracht werden. Hierfür ist ein weiterer GET-Request notwendig. Rückgabewerte von POST-Requests (evtl. auch PUT, DELETE) werden über den Header übertragen, als Debug-Funktion auch als JSON - Texte gehören in die Sprachdateien => keine hardgecodete Texte!!!
- Leerzeichen in Datei- und Ordnernamen sind nicht erlaubt => erlaubte Zeichen sind a-Z, 0-9, _
- Öffnende Klammern gehören in dieselbe Zeile, wie das Statement
- Wertzuweisungen mittels || sind erlaubt
- Wenn möglich mit losen Kopplungen arbeiten. Keine Funktionen direkt aufrufen, welche nicht zur Funktionalität der eigentlichen Komponente gehören und deren Existenz nicht sichergestellt ist.
- „use strict“ ist zu verwenden
- wenn möglich in Closures arbeiten
- Zwischen Statement und Signatur, sowie Signatur und öffnender geschweiften Klammer gehört ein Leerzeichen (z. B. if (true) { ...)
Variablen: Prä- und Suffixe¶
- $-Präfix für bereits ausgeführte Selektoren (Bsp.: var $body = $(„body“);)
- Interne Methoden, die nicht direkt von außen erreichbar sind, werden mit einem "_" als Präfix versehen
Beispiel¶
<?php
/* --------------------------------------------------------------
MySampleClass.inc.php 2015-02-17 gm
Gambio GmbH
http://www.gambio.de
Copyright (c) 2015 Gambio GmbH
Released under the GNU General Public License (Version 2)
[http://www.gnu.org/licenses/gpl-2.0.html]
--------------------------------------------------------------
*/
/**
* Class MySampleClass
*/
class MySampleClass
{
/**
* @var array
*/
protected $multiselectArray = array();
/**
* @var xtcPrice
*/
protected $xtcPrice;
/**
* @var string
*/
protected $type;
/**
* @param array $multiselectArray
* @param xtcPrice $xtcPrice
*/
public function __construct(array $multiselectArray, xtcPrice $xtcPrice)
{
$this->multiselectArray = $multiselectArray;
$this->xtcPrice = $xtcPrice;
$this->type = 'test';
}
/**
* @param array $multiselectArray
*/
public function setMultiselectArray(array $multiselectArray)
{
foreach($multiselectArray as $key => $id)
{
$this->multiselectArray[$key] = (int)$id;
}
}
/**
* execute random sql query build in MySampleClass::_getSampleQuery()
*/
public function executeSampleQuery()
{
xtc_db_query($this->_getSampleQuery());
}
/**
* @return string
*/
protected function _getSampleQuery()
{
$query = 'UPDATE test
SET
text = "value",
nummer = 1
WHERE
id = 2 AND
date < NOW()';
return $query;
}
/**
* @return array
*/
public function getMultiselectArray()
{
return $this->multiselectArray;
}
/**
* @param xtcPrice $xtcPrice
*/
public function setXtcPrice(xtcPrice $xtcPrice)
{
$this->xtcPrice = $xtcPrice;
}
/**
* @return string
*/
public function getType()
{
return $this->type;
}
}
$mySampleClass = MainFactory::create_object('MySampleClass', array($_POST['multiselect'], $xtcPrice));
$type = $mySampleClass->getType();
$multiselectArray = $mySampleClass->getMultiselectArray();
$mySampleClass->executeSampleQuery();
Formatierung von Quellcode¶
Beispiel¶
so ziemlich alles falsch:
$t_flag=0;
$t_name = "Max";
$t_text = "\"".MY_TEXT."\" $t_name Mustermann";
$c_number=(double) $_POST["number"];
foreach ( $t_customer_data AS $t_value ) {
$t_status = ( $t_value=="true" ) ? true : false;
if( $t_status ) $t_flag = 1;
}
if ( !empty($t_flag) )
echo "Tada";
if($_POST['truncate'] == '1') xtc_db_query("TRUNCATE table");
korrekt:
$flag = 0;
$name = 'Max';
$text = '"' . MY_TEXT . '" ' . $name . ' Mustermann';
$number = (double)$_POST['number'];
foreach($customerDataArray as $value)
{
$status = false;
if($value === 'true')
{
$status = true;
}
if($status)
{
$flag = 1;
}
}
if(!empty($flag))
{
echo 'Tada';
}
if(isset($_POST['truncate']) && $_POST['truncate'] === '1')
{
$sql = 'TRUNCATE table';
xtc_db_query($sql);
}