Clean code et refactoring - 01 - Nommage : la competence la plus sous-estimee

Bien nommer ses variables, fonctions, classes et fichiers est la première étape vers un code lisible. Guide pratique avec exemples avant/apres.

  1. 01 Clean code et refactoring - 00 - Pourquoi le clean code est un investissement, pas un luxe
  2. 02 Clean code et refactoring - 01 - Nommage : la competence la plus sous-estimee
  3. 03 Clean code et refactoring - 02 - Fonctions : courtes, claires, responsables
  4. 04 Clean code et refactoring - 03 - Conditions et lisibilité : sortir de la pyramide
  5. 05 Clean code et refactoring - 04 - Commentaires et documentation : quand le code ne suffit pas
  6. 06 Clean code et refactoring - 05 - Immutabilite et effets de bord : moins de surprises, moins de bugs
  7. 07 Clean code et refactoring - 06 - Gestion des erreurs propre : fail fast, fail loud
  8. 08 Clean code et refactoring - 07 - Programmation defensive vs offensive : valider aux frontieres, faire confiance a l'intérieur
  9. 09 Clean code et refactoring - 08 - SOLID en pratique avec TypeScript
  10. 10 Clean code et refactoring - 09 - DRY, KISS, YAGNI
  11. 11 Clean code et refactoring - 10 - Couplage et cohesion
  12. 12 Clean code et refactoring - 11 - Complexite cyclomatique
  13. 13 Clean code et refactoring - 12 - Abstractions prematurees vs tardives
  14. 14 Clean code et refactoring - 13 - Code smells
  15. 15 Clean code et refactoring - 14 - Techniques de refactoring
  16. 16 Clean code et refactoring - 15 - Refactoring legacy sans tout casser
  17. 17 Clean code et refactoring - 16 - Tests comme filet de sécurité pour le refactoring
  18. 18 Clean code et refactoring - 17 - Structurer un projet — feature-based vs layer-based
  19. 19 Clean code et refactoring - 18 - Constantes, configuration et magic numbers
  20. 20 Clean code et refactoring - 19 - Linting et formatting — ESLint, Biome, automatiser la qualité
  21. 21 Clean code et refactoring - 20 - Conventions d'équipe et ADR
  22. 22 Clean code et refactoring - 21 - Dette technique — quand elle est acceptable, quand elle tue le projet
  23. 23 Clean code et refactoring - 22 - Code review — donner et recevoir du feedback
  24. 24 Clean code et refactoring - 23 - Glossaire — tous les termes de la serie

01 - Nommage : la competence la plus sous-estimee

Ce que tu vas apprendre

  • Pourquoi le nommage est si difficile (et si important)
  • Les conventions pour les booleens, fonctions, classes et fichiers
  • Pourquoi les abreviations sont toxiques
  • Comment le renommage est un outil de refactoring a part entière

Prerequisites

00 - Introduction


Phil Karlton, ingenieur chez Netscape, a dit un jour : "There are only two hard things in Computer Science: cache invalidation and naming things." Cette citation a 30 ans. Elle est toujours vraie.

La semaine dernière, j'ai ouvert un fichier dans un projet que j'avais écrit moi-meme il y a huit mois. J'ai trouve ca :

typescriptconst d = getD(u, p);
if (d > 0) {
  await proc(d, u);
}

Je n'avais aucune idee de ce que ce code faisait. Pas la moindre. J'ai du remonter 200 lignes pour comprendre que d etait une dette, u un utilisateur, et proc un traitement de paiement. Huit mois. Mon propre code.

Le nommage n'est pas cosmétique. C'est de la communication.

Les booleens : `is`, `has`, `can`, `should`

Un booleen represente une question oui/non. Son nom doit etre cette question.

typescript// Mauvais
const open = true;
const admin = false;
const data = true;

// Bon
const isOpen = true;
const isAdmin = false;
const hasData = true;

Les prefixes is, has, can, should rendent le code lisible comme de l'anglais :

typescriptif (user.isActive && user.hasSubscription) {
  // se lit naturellement
}

if (user.canPublish && !user.shouldModerate) {
  // on comprend immediatement
}

Pour les fonctions qui retournent un booleen, meme regle :

typescript// Mauvais
function check(email: string): boolean { ... }
function validate(user: User): boolean { ... }

// Bon
function isValidEmail(email: string): boolean { ... }
function hasPermission(user: User, action: string): boolean { ... }

Les fonctions : des verbes d'action

Une fonction fait quelque chose. Son nom doit etre un verbe.

typescript// Mauvais - noms ambigus
function userData(id: string) { ... }
function process() { ... }
function manager() { ... }

// Bon - verbes explicites
function fetchUserById(id: string) { ... }
function processPayment() { ... }
function createOrderManager() { ... }

Le verbe dit ce que la fonction fait. Quelques conventions courantes :

Prefixe Signification Exemple
get / fetch Récupérer une donnee getUserProfile()
set / update Modifier une donnee updateEmail()
create / build Creer quelque chose createInvoice()
delete / remove Supprimer removeExpiredTokens()
is / has / can Tester une condition isExpired()
parse / format Transformer formatCurrency()
validate / check Verifier validateInput()
handle / on Reagir a un événement handleSubmit()

Evite les verbes génériques comme process, handle, manage, do. Ils ne disent rien. "Process" quoi ? "Manage" comment ? Si tu ne trouves pas de verbe precis, c'est souvent un signe que ta fonction fait trop de choses. On en parle dans l'article sur les fonctions.

Les classes et les types : des noms, pas des verbes

typescript// Mauvais
class ManageUsers { ... }
class DoPayment { ... }

// Bon
class UserRepository { ... }
class PaymentProcessor { ... }
class InvoiceGenerator { ... }

Les suffixes courants pour les classes :

  • Service : logique métier (OrderService)
  • Repository : acces aux donnees (UserRepository)
  • Controller : point d'entree HTTP (ProductController)
  • Factory : création d'objets (ConnectionFactory)
  • Validator : validation (EmailValidator)

Un type ou une interface decrit une forme. Son nom doit etre un nom commun :

typescript// Bon
type User = { id: string; email: string; name: string };
type OrderStatus = "pending" | "confirmed" | "shipped";
interface PaymentGateway { charge(amount: number): Promise<Receipt>; }

Les fichiers et dossiers : coherence avant tout

La convention la plus repandue en TypeScript/JavaScript :

  • Fichiers : kebab-case (user-repository.ts, payment-service.ts)
  • Classes : PascalCase (UserRepository, PaymentService)
  • Le fichier porte le nom de son export principal
src/
  services/
    user-service.ts        // exporte UserService
    payment-service.ts     // exporte PaymentService
  repositories/
    user-repository.ts     // exporte UserRepository
  types/
    order.ts               // exporte Order, OrderStatus
  utils/
    format-currency.ts     // exporte formatCurrency

L'important, c'est la coherence. Si ton projet utilise camelCase pour les fichiers, reste en camelCase. Un projet avec trois conventions différentes est pire qu'un projet avec une mauvaise convention.

Les abreviations : ne le fais pas

typescript// Mauvais
const usrMgr = new UserManager();
const evt = getEvent();
const btn = document.getElementById("submit");
const ctx = createContext();
const res = await fetch(url);
const err = validate(input);

// Bon
const userManager = new UserManager();
const event = getEvent();
const submitButton = document.getElementById("submit");
const context = createContext();
const response = await fetch(url);
const validationError = validate(input);

Les seules abreviations acceptables sont celles que tout le monde connaît : id, url, html, css, api, db. Si tu dois te demander ce que l'abreviation signifie, elle n'est pas assez connue.

Exception : les variables de boucle (i, j, k) et les callbacks courts (arr.map(x => x.id)). Le scope est tellement petit que le contexte suffit.

Les constantes : en majuscules si globales

typescript// Constantes de configuration
const MAX_RETRY_COUNT = 3;
const DEFAULT_PAGE_SIZE = 20;
const API_BASE_URL = "https://api.example.com";

// Constantes locales - pas besoin de majuscules
const taxRate = 0.2;
const discountThreshold = 100;

La convention SCREAMING_SNAKE_CASE est reservee aux constantes globales ou de configuration. Pour une constante locale dans une fonction, le camelCase suffit. Tout mettre en majuscules noie le signal dans le bruit.

Le renommage comme outil de refactoring

Renommer une variable ou une fonction est le refactoring le plus simple et le plus impactant. Ton IDE sait le faire en toute sécurité avec "Rename Symbol" (F2 dans VS Code). Pas besoin de chercher-remplacer a la main.

Voici un avant/apres réel tire d'un projet sur lequel j'ai travaille. C'est un service de gestion de places (des lieux a visiter) dont j'ai parle sur paltemps.fr :

typescript// Avant
async function proc(d: any, opts: any) {
  const r = await db.query("SELECT * FROM t WHERE s = $1", [d.s]);
  if (r.length === 0) return null;
  const mapped = r.map((x: any) => ({
    n: x.name,
    v: x.val,
    a: opts.a ? x.extra : undefined,
  }));
  return mapped;
}

// Apres
async function fetchActiveProducts(
  filter: ProductFilter,
  options: QueryOptions
): Promise<Product[]> {
  const products = await db.query(
    "SELECT * FROM products WHERE status = $1",
    [filter.status]
  );

  if (products.length === 0) return [];

  return products.map((row) => ({
    name: row.name,
    value: row.val,
    extraInfo: options.includeExtras ? row.extra : undefined,
  }));
}

Meme logique. Lisibilite complètement différente. Et ca m'a pris 10 minutes.

Les pièges classiques

Le nom qui ment :

typescript// La fonction s'appelle getUser mais elle cree un user si absent
function getUser(email: string): User {
  let user = db.findByEmail(email);
  if (!user) {
    user = db.create({ email }); // surprise !
  }
  return user;
}

// Mieux
function getOrCreateUser(email: string): User { ... }

Le nom trop générique :

typescript// "data", "info", "item", "result", "value" ne disent rien
const data = await fetchUsers();
const info = parseResponse(raw);

// Sois specifique
const users = await fetchUsers();
const parsedOrder = parseResponse(raw);

Le nom avec le type dedans :

typescript// Le systeme de types fait deja ce travail
const userArray: User[] = [];
const nameString: string = "Alice";
const isActiveBoolean: boolean = true;

// Laisse TypeScript parler
const users: User[] = [];
const name = "Alice";
const isActive = true;

Résumé

  • Les booleens commencent par is, has, can, should
  • Les fonctions commencent par un verbe d'action precis
  • Les classes sont des noms avec des suffixes explicites
  • Les fichiers suivent une convention unique dans tout le projet
  • Les abreviations sont interdites sauf pour id, url, html et consorts
  • Le renommage est le refactoring le plus simple et le plus rentable
  • Un bon nom elimine le besoin d'un commentaire

Article précédent : 00 - Introduction

Article suivant : 02 - Fonctions

Sources

Réservez un audit gratuit de 30 minutes. Je vous montre concrètement ce qu'on peut automatiser.