Standard de codage

Ce document décrit les règles et les recommandations pour le développement de Nette. Quand vous contribuez du code à Nette, vous devez les respecter. Le plus simple est d'imiter le code existant. L'objectif est que tout le code paraisse écrit par une seule personne.

Le Nette Coding Standard correspond au PSR-12 Extended Coding Style avec deux exceptions majeures : il indente avec des tabulations au lieu d'espaces et emploie le PascalCase pour les constantes de classe.

Beaucoup de ces règles peuvent être vérifiées et corrigées automatiquement par l'outil Nette Coding Standard, vous n'avez donc pas à les contrôler à la main.

Règles générales

  • Chaque fichier PHP doit contenir declare(strict_types=1)
  • Deux lignes vides séparent les méthodes, pour une meilleure lisibilité
  • La raison d'employer l'opérateur de silence (@) doit être documentée : @mkdir($dir); // @ - directory may exist
  • Si un opérateur de comparaison faible est utilisé (==, !=, …), l'intention doit être documentée : // == to accept null
  • Vous pouvez écrire plusieurs classes d'exception dans un seul fichier nommé exceptions.php, et plusieurs enums dans enums.php
  • La visibilité des méthodes n'est pas précisée dans les interfaces, car elles sont toujours publiques
  • Chaque propriété, valeur de retour et paramètre doit avoir un type. À l'inverse, pour les constantes finales, nous ne précisons jamais le type, car il est évident
  • Les chaînes se délimitent par des apostrophes, sauf lorsque le littéral contient lui-même des apostrophes

Conventions de nommage

Retours à la ligne et accolades

Le Nette Coding Standard correspond au PSR-12 (ou PER Coding Style), mais le précise ou le modifie sur certains points :

  • Les fonctions fléchées s'écrivent sans espace avant la parenthèse, c'est-à-dire fn($a) => $b
  • Aucune ligne vide n'est exigée entre les différents types d'imports use
  • Le type de retour d'une fonction/méthode et l'accolade ouvrante sont toujours sur des lignes distinctes :
	public function find(
		string $dir,
		array $options,
	): array
	{
		// method body
	}

L'accolade ouvrante sur une ligne à part est importante pour séparer visuellement la signature de la fonction/méthode de son corps. Si la signature tient sur une ligne, la séparation est claire (image de gauche). Si elle s'étale sur plusieurs lignes, en PSR la signature et le corps se confondent (au milieu), tandis que dans le standard de Nette ils restent séparés (à droite) :

Blocs de documentation (phpDoc)

La règle principale : ne dupliquez jamais une information de la signature, comme le type d'un paramètre ou le type de retour, sans apporter de valeur.

Bloc de documentation d'une définition de classe :

  • Commence par une description de la classe
  • Suivie d'une ligne vide
  • Suivie des annotations @property (ou @property-read, @property-write), une par ligne. Syntaxe : annotation, espace, type, espace, $nom
  • Suivies des annotations @method, une par ligne. Syntaxe : annotation, espace, type de retour, espace, nom(type $param, ...)
  • L'annotation @author est omise. La paternité est conservée dans l'historique du code source
  • Les annotations @internal ou @deprecated peuvent être utilisées
/**
 * MIME message part.
 *
 * @property string $encoding
 * @property-read array $headers
 * @method string getSomething(string $name)
 * @method static bool isEnabled()
 */

Un bloc de documentation de propriété ne contenant que l'annotation @var doit tenir sur une seule ligne :

/** @var string[] */
private array $name;

Bloc de documentation d'une définition de méthode :

  • Commence par une courte description de la méthode
  • Pas de ligne vide
  • Les annotations @param, une par ligne
  • L'annotation @return
  • Les annotations @throws, une par ligne
  • Les annotations @internal ou @deprecated peuvent être utilisées

Chaque annotation est suivie d'une espace, sauf @param, qui est suivie de deux espaces pour une meilleure lisibilité.

/**
 * Finds a file in directory.
 * @param  string[]  $options
 * @return string[]
 * @throws DirectoryNotFoundException
 */
public function find(string $dir, array $options): array

Fonctions et constantes globales

Les fonctions et constantes globales s'écrivent sans barre oblique inverse initiale, donc count($arr) et non \count($arr). Pour les fonctions que PHP sait optimiser, ajoutez use function au début du fichier, afin que le compilateur les traduise plus efficacement. Il s'agit de fonctions comme count, strlen, is_array, is_string, is_scalar, sprintf, etc. Les fonctions sont listées sur une seule ligne pour garder le bloc d'imports compact :

use Nette;
use function count, is_array, is_scalar, sprintf;

Il nous arrive aussi d'importer des constantes dont la connaissance de la valeur peut aider le compilateur :

use const PHP_OS_FAMILY;

Tabulations au lieu d'espaces

Les tabulations ont plusieurs avantages sur les espaces :

  • La taille de l'indentation est réglable dans les éditeurs et sur le web
  • Elles n'imposent pas au code la préférence d'indentation de leur auteur, ce qui rend le code plus portable
  • Elles s'obtiennent d'une seule frappe (partout, pas seulement dans les éditeurs qui convertissent les tabulations en espaces)
  • L'indentation est leur raison d'être
  • Elles respectent les besoins des collègues malvoyants et aveugles

En utilisant des tabulations dans nos projets, nous permettons d'en régler la largeur, ce qui peut sembler superflu à la plupart des gens, mais qui est essentiel pour les personnes atteintes de déficience visuelle.

Pour les programmeurs aveugles qui utilisent un afficheur braille, chaque espace occupe une cellule braille. Si l'indentation par défaut est de 4 espaces, une indentation de 3e niveau gaspille donc 12 précieuses cellules braille avant même que le code ne commence. Sur un afficheur de 40 cellules, le plus courant pour les portables, c'est plus d'un quart des cellules disponibles gaspillé sans apporter la moindre information.