Conventions de codage
-
Introduction
Les développements dans le framework I.T. Rocks respectent les conventions de codage ci-dessous. Il est demandé aux contributeurs de les respecter scrupuleusement.
Indentation et longueur de ligne
L’indentation s’effectue avec le caractère tabulation jusqu’au début du code. Aucun caractère tabulation ne doit être utilisé après le premier caractère, ni au delà du niveau d’indentation courant.
Vous pouvez régler la taille de la tabulation librement dans votre IDE : 2, 3, 4 espaces. Le code sera ainsi affiché suivant vos préférences dans ce domaine. Partez du principe que le code devra rester proprement aligné quel que soit la taille d’indentation choisie par les autres développeurs.
Veillez à ce que la longueur des lignes ne dépasse pas 100 caractères en tabulation de 2. espaces
Structure générale du fichier php
Un fichier PHP doit contenir une et une seule classe. Le nom de fichier correspond au nom court de la classe.
Exemple de fichier PHP conforme :
<?php namespace ITRocks\Framework\Module; use Any\External\Thing; use Another\External; use The\First\Trait; use Another\Included; /** * Documentation then annotations */ class A_Name { // uses, constants, properties then methods come here }
L’ensemble des choix d’indentation et d’espacement d’éléments doit être respectés :- Le
namespace
doit être positionné au début du fichier, ligne 2 - Une ligne blanche entre le
namespace
et les clausesuse
- Les clauses
use
doivent être triées strictement dans l’ordre alphabétique - Une ligne blanche entre les clauses
use
et la documentation et les annotations de la classe
Clauses use au niveau namespace
- Ne pas utiliser les alias : en cas de conflit de nom (et seulement dans ce cas), utilisez
use
pour le namespace le plus complet qui ne fasse pas conflit et utilisez votre nom de classe en partant de ce namespace dans votre code. Par exemple :
use Any\External; // (...) $object = new External\Thing();
- Trier les clauses
use
par ordre alphabétique du premier niveau de namespace, puis du second, et ainsi de suite. - Utilisez une déclaration
use
par namespace : pas de séparation par virgules. - N’utilisez jamais l’anti-slash
\
pour débuter un nom de classe dans votre code : même pour les classes globales (sans namespace) de PHP, utilisez une clauseuse
pour les déclarer. Exemple d’utilisation correcte :
use DateTime; // (...) $date_time = new DateTime();
Conventions de nommage communes aux classes, constantes, méthodes, propriétés
- la signification doit être précise et évidente dans le cadre du métier client : toujours préférer des noms précis aux noms génériques.
Exemples : utiliser house, client, order ; n’utilisez jamais object, parent si vous n’êtes pas dans un contexte strictement générique. - Éviter toute répétition dans le namespace, entre le namespace et le nom de classe, entre le nom de classe et les noms de constantes, méthodes et propriétés : toujours considérer que les éléments sont nommés dans le cadre de leur contexte. Les noms doivent donc être clairs mais concis.
Exemples :Bappli\Time\Calendar\Output
est un nom de classe valide, alors que si on a une répétition non, commeBappli\Time\Calendar\Calendar_Output
. - L’ordre des modificateurs à respecter est le suivant :
- abstract,
- private / protected / public,
- static.
- Les déclarations doivent toujours être réalisées dans l’ordre suivant :
- clauses use dans l’ordre alphabétique,
- constantes dans l’ordre alphabétique,
- propriétés dans l’ordre alphabétique,
- méthodes dans l’ordre alphabétique,
- dans les commentaires : les annotations doivent être triées dans l’ordre alphabétique.
Généralités concernant la documentation et les commentaires
- La documentation des classes, constantes, propriétés, méthodes, doit être réalisée en phpdoc respectant l’écriture ** *.
- Elle est obligatoire pour tous ces composants, sauf les constantes où elle peut être ommise si le nom de la constante constitue une documentation suffisante.
- La documentation comporte obligatoirement :
- une courte description fonctionnelle (moins d’une ligne), qui peut être reprise dans un sommaire ou un index de documentation, exhaustif mais concis.
On n’attend pas de signe de ponctuation finale (point) dans cette description. - une ligne blanche, puis si nécessaire une documentation détaillée, dès qu’une explication fonctionnelle supplémentaire est nécessaire.
Si plusieurs phrases, on peut séparer par des points, avoir des paragraphes, listes à tirets -, etc. Une rédaction détaillée ici est possible. - Une ligne blanche, puis lorsqu’applicable (propriétés, paramètres / valeurs de retour de méthodes, annotations fonctionnelles) ajoutez la liste des annotations, obligatoirement par ordre alphabétique.
- une courte description fonctionnelle (moins d’une ligne), qui peut être reprise dans un sommaire ou un index de documentation, exhaustif mais concis.
- La documentation dans le code par double-slash doit précéder le bloc de code concerné, et n’être là que pour donner un ajout d’explication qu’on ne peut pas produire par un nommage et une organisation plus propre du code. Elle ne doit absolument pas remplacer :
- le découpage en sous-fonctions dont le nom fait office d’explication fonctionnelle concise,
- un nommage générique de variable : si votre variable avait le bon nom, vous n’auriez pas à l’expliquer en documentation,
- le sens d’un appel : si le nom d’une fonction et son contexte d’appel (classe de l’objet) n’ont pas le bon nom, il faut le corriger, pas commenter les appels.
Déclaration de classe / interface / trait
Exemple de déclaration de classe conforme :
/** * An explicit short description for the class (one line) * * A more explicit documentation for the class, if needed. * Can be on multiple-lines. * * @business * @deprecated Annotations come last, one per line, multiple lines for per annotation if needed */ class A_Name extends The_Parent implements First_Interface, Next_Interface { use First_Trait; use Next_Trait; // constants, properties then methods come here }
Les règles appliquées :- La documentation se constitue d’une ligne de description courte, suivie d’une ligne blanche et de la documentation aussi claire que possible.
- Les annotations arrivent en dernier, après une ligne blanche, en respectant scrupuleusement l’espace avant et après l’astérisque et le format de chaque annotation utilisée.
- Le prototype de la classe tiendra autant que possible sur une seule ligne.
- L’accolade ouvrante de début de classe doit être à la ligne.
- Les clauses
use
suivent directement l’accolade ouvrante, sans être précédées de ligne de séparation. Elles sont triées par ordre alphabétique, un seul trait par clauseuse
. - Une ligne blanche sépare les clauses use des déclarations suivantes.
- Une ligne blanche séparera chaque constante, chaque propriété, chaque méthode.
- L’accolade ouvrante de fin de classe doit être alignée avec l’accolade ouvrante, en fin de fichier, précédée et suivie d’une ligne blanche.
- Le nom d’une classe peut être un ou plusieurs mots
- Les mots sont séparés par le caractère underscore
_
- La première lettre de chaque mot doit être une majuscule, les lettres suivantes doivent être en minuscules
- Si le nom de la classe ou d’un chemin de
namespace
contient un acronyme, par exempleSMS
, et dans ce cas seulement à titre d’exception, on peut garder un mot entièrement en majuscules.
Déclaration de traits utilisés dans une classe (use)
Voir l’exemple et les règles de base au niveau déclaration de classe, dans le paragraphe précédent.
Déclaration de constante dans une classe
Exemple de déclaration de constante conforme :
//--------------------------------------------------------------------------- AUTHOR_DEFAULT_NAME /** * An optional documentation, if needed. */ const AUTHOR_DEFAULT_NAME = 'author';
Les règles appliquées :- Les déclarations de constantes sont toujours précédées et suivies d’une ligne blanche.
- Si plusieurs constantes, les séparer d’une ligne blanche, les trier systématiquement par ordre alphabétique.
- Chaque déclaration de constante est précédée d’une ligne de commentaire indiquant le nom de la constante à droite.
- La documentation, respectant l’indentation proposée dans cet exemple, est optionnelle, à titre de précision si la constante ne parle pas d’elle-même.
Par exception, pour améliorer la lisibilité, on peut regrouper des constantes qui représentent par exemple des valeurs possibles d’une propriété, ou du moins qui ont toutes le même champ d’application, et uniquement si elles n’ont pas besoin d’autre documentation que leur nom. L’alignement vertical est alors de rigueur. Par exemple :
//------------------------------------------------------------------------------- $status @values const ALIVE = 'alive'; const DEAD = 'dead'; const MAYBE = 'maybe';
Conventions de nommage des constantes :- Le nom d’une constante peut être un ou plusieurs mots
- Les mots sont séparés par le caractère underscore
_
- Le nom de constante doit être intégralement en majuscules
Déclaration de méthodes de classe
Exemple de déclaration de méthode conforme :
//--------------------------------------------------------------------------------- accessControl /** * This method is an AOP advice to disable access to features when no user is connected * * Abort the execution of the pointcut method if there is no connected user. * * @param $joinpoint Method_Joinpoint The joinpoint object * @param $another_parameter boolean|null Another optional parameter to make it more func * @return boolean Returns true if done well, false on error */ public function accessControl(Method_Joinpoint $joinpoint, $another_parameter = null) { // (...) }
Variante liste de paramètres en cas de dépassement à droite :
public function afterOutputControllerGetGeneralButtons( $object, array &$result, Joinpoint $joinpoint ) { // (...) }
Variante liste de paramètres sur plusieurs lignes :
public function __construct( $context_type = null, $context = null, $characteristic = null, $checked_characteristic = null, array $values = null ) {
Les règles appliquées :- Les déclarations de fonctions (prototype + implémentation) sont précédées et suivies d’une ligne blanche.
- Si plusieurs méthodes, les séparer d’une ligne blanche, les trier systématiquement par ordre alphabétique.
- Chaque déclaration de méthode est précédée d’une ligne de commentaire indiquant le nom de la méthode à droite.
- La documentation, respectant l’indentation proposée dans cet exemple, est obligatoire :
- Commence un résumé en une ligne maximum de la fonctionnalité (titre),
- Séparée par une ligne blanche, un descriptif détaillé si nécessaire,
- Précédé d’une ligne blanche, la liste des paramètres : chacun présentant d’abord le nom du paramètre, puis son type tel que reconnu par phpDocumentor / PhpStorm, puis une description détaillée du type si la description phpdoc est insuffisante (structure d’un tableau récursif par exemple), et enfin suivi d’une documentation explicite concernant l’usage de ce paramètre.
- Si la description du paramètre prend plusieurs lignes, les indenter avec des espaces après l’astérisque pour respecter l’alignement avec le type de paramètre.
- Si plusieurs paramètres d’une ligne chacun, respecter l’alignement vertical de tous les paramètres sur le type, sauf si cela nuit vraiment à la lisibilité (cas multi-lignes).
- Les annotations doivent être triées par ordre alphabétique.
- Une annotation
@example
est la bienvenue et peut être répétée pour montrer des exemples d’utilisation dans le cas où celle-ci ne tombe pas sous le sens pour le néophyte.
- Les paramètres doivent être types en compatibilité PHP 5.6 : toujours préciser le nom de la classe,
callable
,array
, pour les paramètres mono-typés concernés. - Respecter les règles d’indentation en cas de dépassement à droite, en suivant les exemples ci-dessus.
- Le nom d’une méthode peut être un ou plusieurs mots
- Les mots sont collés
- Le premier mot commence par une minuscule
- Les mots suivants commencent par une majuscule
Déclaration de propriétés de classe
Exemple de déclaration de propriété conforme :
//---------------------------------------------------------------------------------- $author_name /** @noinspection SomeInspectionRestriction With a comment for "why?" */ /** * A full documentation, multiple lines can be used. * * @max_length 50 * @var string */ private static $author_name = 'some defaults';
Les règles appliquées :- Les déclarations de propriétés sont toujours précédées et suivies d’une ligne blanche.
- Si plusieurs propriétés, les séparer d’une ligne blanche, les trier systématiquement par ordre alphabétique.
- Chaque déclaration de propriété est précédée d’une ligne de commentaire indiquant le nom de la propriété à droite.
- La documentation, respectant l’indentation proposée dans cet exemple, est obligatoire. Elle doit indiquer tout ce qu’il y a à savoir pour bien utiliser la propriété et comprendre son fonctionnement.
- La documentation doit être séparée des annotations par une ligne blanche.
- L’annotation
@var
, indiquant le type de la propriété, est obligatoire. Si plusieurs types sont possibles, mettre en premier le plus large (par exempleobject
si vous voulez déclarerobject|Another_Class
) et faire suivre les autres types possibles, séparés par une barre verticale|
sans espaces. Les classes en premier, suivent les interfaces puis les traits si utiles. - Utilisez les annotations au mieux pour déclarer les règles de gestion applicables à votre propriété le plus précisément possible.
- Si un commentaire
/** @noinspection */
doit précéder la déclaration de la propriété, mettez-le entre la ligne de commentaire et la documentation, comme dans l’exemple. Ne mettez jamais ces commentaires particuliers après la documentation, les annotations pourraient ne pas être prises en compte. Commentez toujours vos exclusions d’inspection. - Propriétés
static
: le mot cléstatic
arrive toujours après la visibilitépublic
,protected
ouprivate
. - N’utilisez jamais la visibilité
var
: précisez toujourspublic
,protected
ouprivate
.
- le nom d’une propriété peut être un ou plusieurs mots
- les mots sont séparés par le caractère underscore
_
- le nom de propriété doit être intégralement en minuscules, même s’il contient des acronymes
Structures de boucle / contrôle
Exemple d’indentation pour une condition
if
…else
:
if (!$a_boolean_variable && ($a_numeric_variable === 19)) { // (...) } else { // (...) }
On ne laisse jamais les priorités par défaut s’appliquer, sauf pour l’opérateur unaire
!
accolé à sa condition. Les conditions impliquant des opérateurs doivent être priorisés par des parenthèses(
)
pour faciliter la lecture des priorités.Exemple d’indentation pour une condition
if
qui dépasse les 100 caractères de large : les règles d’indentation sont les même après une parenthèse(
et un crochet[
que l’accolade{
pour une méthode, y compris à la fermeture, où les alignements verticaux doivent être respectés :
if ( $a_big_condition_that_takes_room || ($some && $little && $conditions) || $another_condition_again || ( $another_stack_of_a_lot_of_conditions && $more_conditions ) ) { // (...) }
L’indentation sera similaire pour un
foreach
,while
.Indentation pour un
do
…while
:
do { // (...) } while ($conditions);
Indentation pour une clause
switch
:
switch ($condition) { case 'value_1': // (...) break; case 'value_2' : // (...) break; default: // (...) }
Indentation pour opérateurs ternaires
?:
:
$a = ($condition 1 && $condition2) ? $foo : $bar;
Opérateurs ternaires sur plusieurs lignes, lorsque dépassement de la gouttière droite de 100 caractères :
$a = ($condition1 && $condition2) ? $foo : $bar;
Autres règles de retour à la ligne
Lors d’une assignation qui dépasse la largeur de ligne, on revient à la ligne et on indente, en priorité :- les arguments envoyés à un appel de fonction / méthode :
$a_variable = $this->myMethodCall( $a_huge_list, $of_parameters, $this->anotherExampleCall(), $the_last_parameter );
- l’opérateur d’assignation
=
, si toute l’opération peut tenir sur une ligne :
$a_variable = $a_big + $calculation + ($with_a / $division) - ($and_a * $multiplication);
- Un opérateur revient toujours en début de ligne suivant plutôt qu’être en fin de ligne, lorsque nécessaire. Rechercher alors un maximum la lisibilité avant tout pour choisir quels opérateurs sont ramenés à la ligne. Par exemple :
$a_variable = $a_big + $calculation + ($with_a / $division) - ($and_a * $multiplication);
Alignement vertical
L’alignement vertical par des espaces de rédactions similaires d’une ligne à l’autre doit être utilisé s’il améliore la lisibilité.
Exemple 1 : plusieurs assignations doivent être alignées (sauf si cela fait dépasser la largeur de ligne pour certaines) :
$a_variable = 'a_value'; $another_variable = 'another_value';
Exemple 2 : plusieurs appels de fonctions similaires, et leurs paramètres, peuvent être alignés pour améliorer la lisibilité :
$aop->afterMethod ([$this, 'anAdvice' ], [Third_Party::class, 'thirdPartyMethod' ]); $aop->beforeMethod([$this, 'anotherAdvice'], [Third_Party::class, 'anotherThirdPartyMethod']);
- Le