Aller au contenu

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 est source, pas sourceStatus.
  • Dans une entité Lead, le champ est status, pas leadStatus.
  • Dans un PaymentService, la méthode est refund(id), pas refundPayment(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 findOne copié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 private pour les helpers qui découpent une méthode publique. Promouvez en public (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.