Style de code¶
Ces règles ne sont pas des préférences esthétiques — elles sont appliquées en revue. Elles suivent les principes de clean code et de design architectural.
Naming¶
Utilisez des noms explicites sans être verbeux. Un nom tire son sens de son contexte — ne répétez pas le nom de la classe ou du module dans un membre.
- Dans une classe
StatusHistory, la colonne estsource, passourceStatus. - Dans une entité
Lead, le champ eststatus, pasleadStatus. - Dans un
PaymentService, la méthode estrefund(id), pasrefundPayment(paymentId).
Réservez les noms longs aux cas réellement ambigus dans leur portée.
Commentaires¶
Le code doit être auto-descriptif. Visez zéro commentaire par défaut. Un lecteur doit comprendre ce que fait le code par les identifiants et la structure.
Les commentaires sont réservés au POURQUOI — et seulement quand il est non-évident :
- une contrainte ou un invariant caché ;
- un contournement d'un bug précis ou d'une bizarrerie d'un système externe ;
- un choix délibéré non-évident qu'un futur lecteur « corrigerait » à tort.
Si un commentaire décrit ce que fait le code (// boucle sur les users), supprimez-le et renommez le code.
DRY — Don't Repeat Yourself¶
Si la même action est nécessaire à plusieurs endroits, extrayez un helper partagé :
- logique inter-services → méthode de domaine ou module partagé sous
app/<module>/; - logique inter-contrôleurs → garde, décorateur, ou fragment de schéma partagé ;
- formes de requête répétées → helper de modèle typé, jamais des blocs
findOnecopiés-collés.
Le déclencheur est deux duplications de même intention, pas une simple ressemblance. N'abstrayez pas une similitude fortuite.
KISS — Keep It Simple¶
- Écrivez de petites fonctions qui font une seule chose. Si une fonction a besoin d'un « et » dans son nom, scindez-la.
- Méthodes publiques d'abord dans les classes, puis les helpers privés en dessous. Le lecteur voit l'API avant les détails.
- Utilisez
privatepour les helpers qui découpent une méthode publique. Promouvez enpublic(et documentez) seulement si une autre classe en a réellement besoin. - Préférez du code en ligne droite à une configuration prématurée. Trois lignes similaires valent mieux qu'un objet de config utilisé une seule fois.
SOC — Separation of Concerns¶
Chaque couche porte une responsabilité. Franchir une frontière est un point bloquant en revue.
web/— HTTP uniquement. Pas de logique métier, pas d'appel Sequelize.app/<module>/— logique métier uniquement. Pas de types HTTP, pas de décorateurs Swagger.domain/— données +fromRecord+ erreurs. Pas d'I/O, pas de Sequelize, pas de Nest.database/sequelize/— formes de persistance uniquement.adapters/— I/O externe, encapsulé derrière une interface.
Si vous importez @nestjs/* dans app/ ou domain/, ou appelez un accesseur Sequelize dans web/, vous êtes dans la mauvaise couche. Voir Architecture › Vue d'ensemble.
Conventions transverses¶
| Sujet | Règle |
|---|---|
| Ensembles de valeurs | Modéliser avec un objet as const + type union dérivé, jamais un enum TS. |
| Colonnes texte optionnelles | allowNull: false, defaultValue: '' ; type de domaine string, jamais string \| null. |
| Listing | Tout endpoint de collection est paginé : page=1, pageSize=20 (max 100), réponse { items, page, pageSize, total }. |
| Routes REST | Routes plates de premier niveau (/forms, /leads) ; les FK parentes vont dans le corps ou la query, jamais dans l'URL. |
| Utilisateur courant | @CurrentUser() dans le contrôleur, passé directement au service ; pas de re-fetch. |
| Signature de service | user: User en dernier paramètre positionnel, nommé user. |
| Permissions admin | Suffixe _admin ; méthodes dans un *AdminService dédié. |
| Confirmations UX | Jamais de confirm: true dans les endpoints — préoccupation frontend. |
Voir aussi Permissions et Accès aux données.