Conventional Comments : Une approche standardisée pour la communication en code review

28 décembre 2025

Dev en colère

Combien de temps ton équipe perd-elle à décoder l'intention derrière un commentaire de review ?

"Tu devrais refactorer ceci." Est-ce bloquant ? Une suggestion ? Une remarque en passant ? Le développeur hésite, le relecteur s'agace que son feedback soit ignoré. La MR traîne. Le problème n'est pas technique: c'est un problème de communication.

Conventional Comments propose une solution simple : rendre l'implicite explicite. Un format structuré qui clarifie l'intention, la criticité et le contexte de chaque commentaire.

Dans cet article : la méthodologie, des exemples avant/après, et les métriques que nous avons observées après l'adoption par une équipe de développement.


Comprendre le problème

Comment la Merge Request est devenue incontournable

Pour comprendre les enjeux actuels, un détour par l'histoire s'impose.

Années 80–2000 : l'ère centralisée. Avec RCS puis CVS, un fichier = un verrou. Le travail séquentiel est la norme, la relecture passe par des emails et des réunions. SVN améliore les choses avec des commits atomiques, mais les branches restent lentes et douloureuses. Résultat : pas de culture de review systématique.

2005 : la révolution Git. Branches instantanées, travail 100% local, merges intelligents. Le paradigme bascule. Les feature branches explosent, le travail parallèle devient massif. Mais avec cette liberté vient un nouveau risque : la perte de cohérence du code.

2010+ : l'essor des plateformes. GitHub, GitLab, Bitbucket introduisent la Pull/Merge Request. Discussion dans le code, historique des décisions, CI automatisée, approbations formelles. La MR devient le point de passage obligé pour tout changement.

Fil rouge : Plus les branches deviennent faciles à créer, plus la relecture structurée devient critique.

Aujourd'hui, les équipes collaborent en asynchrone. Les discussions dans les merge requests sont la documentation vivante des décisions techniques. Sans le face-à-face, le ton et l'intention sont facilement mal interprétés. Les reviews servent aussi de vecteur d'apprentissage : onboarding des juniors, challenge des approches des seniors.

Le fossé de communication

Pourtant, les commentaires de review traditionnels souffrent de patterns récurrents qui sabotent leur efficacité :

Friction émotionnelle :"Ce code ne fonctionnera pas en production" sans contexte génère de l'anxiété, pas de la collaboration. Le développeur se met sur la défensive.

Ambiguïté sur la criticité :"Considère extraire cette logique" : bloquant ou optionnel ? Le développeur perd du temps sur du non-critique, ou ignore un feedback important. Frustration des deux côtés.

Discussions sans fin :Sans framework clair, une simple question escalade en thread interminable. La MR reste bloquée plusieurs jours.

Absence de reconnaissance :12 commentaires critiques, 0 éloge. Le bon travail passe inaperçu. La motivation s'érode.

Faux consensus :Pour éviter le conflit, certains approuvent avec un "LGTM" superficiel. La dette technique s'accumule en silence.


La solution : Conventional Comments

Plus d'informations sur conventionalcomments.org.

Avant :

Tu devrais extraire cette logique

Après :

suggestion (non-blocking): Extraire la logique de validation

En un coup d'œil : c'est une suggestion, elle n'est pas bloquante. Plus d'ambiguïté.

Format

<label> (decoration): <sujet>

[discussion optionnelle]

Élément

Rôle

Exemple

label

Type de commentaire

suggestion

decoration

Modifie la criticité (optionnel)

non-blocking

sujet

Le point soulevé

Extraire la logique de validation

discussion

Contexte, raisonnement (optionnel)

Explication détaillée, liens, etc.

Labels

La spécification définit plusieurs labels. Voici ceux que nous utilisons :

Label

Usage

Bloquant

Exemple

praise

Mettre en avant des aspects positifs

Non

praise: Excellent pattern de gestion d'erreur

question

Comprendre une décision

Non (attend réponse)

question: Pourquoi async ici ?

suggestion

Proposer une amélioration

Non (auteur décide)

suggestion: Utiliser Zod pour validation

issue

Changement nécessaire

Oui (doit être résolu)

issue: Fuite mémoire dans ce listener

thought

Partager une idée ou réflexion

Non

thought: Un pattern Observer serait pertinent

nitpick

Changement trivial

Non

nitpick: Retirer le console.log

todo

Petite tâche nécessaire et triviale

Oui (doit être résolu)

todo: Ajouter la validation du format email

Décorations

Les décorations ajustent la criticité d'un label :

Décoration

Signification

Exemple

(non-blocking)

Le merge peut se faire, l'auteur décide

nitpick (non-blocking): Ajouter JSDoc

(if-minor)

À corriger sauf si l'effort est disproportionné

issue (if-minor): Passer en async


Exemples concrets

Reprenons les problèmes identifiés plus haut et voyons comment Conventional Comments les résout.

Ambiguïté sur la criticité

const data = await fetchUser(userId);
if (!data) {
  throw new Error('User not found');
}

Avant

"Tu devrais utiliser un Result type au lieu de throw"

Après

suggestion (non-blocking): Considérer un Result type pour la gestion d'erreur

Avec un Result<T, E>, cela éviterait les try/catch et rendra les erreurs explicites 
au niveau des types.
Pas nécessaire pour cette MR si le reste de la codebase utilise throw.

Référence : https://swan-io.github.io/boxed/result

→ L'intention est claire : suggestion non-bloquante, le développeur décide.

Friction émotionnelle

Avant

const users = [/* ... */];
users.forEach(user => {
  sendEmail(user.email, template);
});

"Ce code va exploser en prod avec 10 000 users. C'est pas bon du tout!"

Après

issue: Risque de surcharge de l'API email avec des volumes importants

Avec 10k users, cette approche synchrone va timeout.

Suggestions :
- Utiliser `p-limit` pour limiter la concurrence (ex: 10 parallèles max)
- Déléguer à une queue (Amqp) pour un traitement async

Dispo si besoin d'un coup de main, j'ai déjà implémenté ça avec p-limit.

→ Le problème est articulé avec des solutions, pas des reproches.

Jugement déguisé en question

async function processOrders() {
  const orders = await fetchOrders();
  for (const order of orders) {
    await processPayment(order);
    await sendConfirmation(order);
  }
}

Avant

"Pourquoi tu n'utilises pas Promise.all() ? As-tu bien compris l'async en JS ?"

Après

question: Raison du traitement séquentiel plutôt que parallèle ?

Je me demande s'il y a une dépendance entre processPayment et sendConfirmation.
Si elles sont indépendantes, on pourrait améliorer la perf avec `Promise.all()`.

Si c'est intentionnel (limite de débit ?), un commentaire aiderait à documenter.

→ Curiosité plutôt que jugement, dialogue ouvert.

Absence de reconnaissance

Avant

Une MR reçoit 12 commentaires : 10 issues, 2 todos, 0 praise.

Après

praise: Excellente architecture avec le pattern Repository

La séparation domain/infrastructure rend ce code hautement testable.
Les interfaces sont claires et le typage strict prévient des erreurs runtime.

praise: Tests complets incluant les edge-cases

Les tests de timeout et retry sont particulièrement précieux.

issue: Fuite mémoire potentielle dans le listener WebSocket
[... autres commentaires ...]

→ Équilibrer critiques et reconnaissance maintient la motivation.


Implémentation et mesure

Adopter Conventional Comments ne suffit pas: il faut des règles d'équipe et un suivi pour ancrer la pratique.

Règles d'équipe

Règle

Pourquoi

Praise sincère obligatoire

Identifier les aspects positifs. Un faux praise érode la confiance.

Seul l'auteur du commentaire résout

Évite les merges prématurés. Le dev répond, le relecteur valide et résout.

Référencer le commit de correction

"Corrigé dans abc123" → le relecteur vérifie directement.

Documenter les exceptions

Merge urgent ? Créer un ticket et le mentionner dans le thread.

Exemple: notification après correction :

# Relecteur
issue: Variable userId non validée

# Développeur
Corrigé dans abc123 :ajout validation Zod avec z.string().uuid()

Exemple: exception documentée :

suggestion (non-blocking): Refactorer vers une architecture hexagonale

@dev : On merge pour débloquer la release, ticket TECH-456 créé.

Métriques de suivi

Trois indicateurs pour évaluer l'adoption :

Métrique

Calcul

Objectif

Taux d'adoption

Commentaires conventionnels / Total

80%+ après 3 mois

Praise ratio

Praise / (Issue + Nitpick)

Min 0.2 (1 pour 5 critiques)

Temps de résolution

Date merge − Date création

Réduction de 20-30%

Évolution attendue : Praise en hausse, Issues en baisse, Questions stables.

Automatisation

Le suivi manuel est fastidieux. J'ai créé un outil CLI pour automatiser la collecte depuis l'API GitLab.

Exemple d'output :

╔════════════════════════════════════════════════╗
║             ⏱  MR Resolution Time              ║
╚════════════════════════════════════════════════╝

    12d┤
    11d┤
    10d┤
     9d┤
     9d┤━━━━━━━┓
     8d┤       ┃
     7d┤       ┃
     6d┤       ┃
d    5d┤       ┃             ┏┓
a    5d┤       ┃             ┃┃         ┏━━┓                   ┏━━━━━┓
y    4d┤       ┃         ┏━┓ ┃┃         ┃  ┃        ┏━━━━━┓    ┃     ┃
s    3d┤       ┃   ┏━━━━━┛ ┃ ┃┗━━━━━━━━━┛  ┃        ┃     ┃    ┃     ┃     ┏━━━━┓
     2d┤       ┃  ┏┛       ┃ ┃             ┃        ┃     ┃    ┃     ┃     ┃    ┃
     2d┤       ┃  ┃        ┗━┛             ┗━━━┓    ┃     ┃ ┏┓ ┃     ┃     ┃    ┃
    19h┤       ┗━━┛                            ┗━━┓ ┃     ┗━┛┗━┛     ┗━━━━━┛    ┃
     0 ┤                                          ┗━┛                           ┗━
       └┬───────┬──┬┬─────┬─┬─┬┬─┬───────┬──┬───┬──┬─┬─────┬─┬┬─┬─────┬─┬──┬┬────┬▶
          11-10     11-1711-20     11-26  12-0112-04 12-0812-11 12-1512-18 12-22
                                     date (utc)
Lissage de la courbe grâce à l'application d'un Exponentially Weighted Moving Average (EWMA)

    6d┤
    6d┤━━━━━━━┓
    5d┤       ┃
    5d┤       ┃
d   4d┤       ┗━━┓
a   4d┤          ┃
y   4d┤          ┗━━━━━━━━┓ ┏━━┓       ┏━━┓
s   3d┤                   ┗━┛  ┗━━━━━━━┛  ┗━━━┓
    3d┤                                       ┃
    2d┤                                       ┗━━┓ ┏━━━━━┓    ┏━━━━━┓
    2d┤                                          ┗━┛     ┗━━┓ ┃     ┗━┓   ┏━━━━┓
    2d┤                                                     ┗━┛       ┗━━━┛    ┗━
    1d┤
   19h┤
    9h┤
    0 ┤
      └┬───────┬──┬┬─────┬─┬─┬┬─┬───────┬──┬───┬──┬─┬─────┬─┬┬─┬─────┬─┬──┬┬────┬▶
           11-10     11-1711-20     11-26  12-0112-04 12-0812-11 12-1512-18 12-22
                                          date (utc)
╔════════════════════════════════════════════════╗
║          💬 MR Comments Distribution           ║
╚════════════════════════════════════════════════╝
Global Statistics
─────────────────
┌─────────────────────┬────────┐
│ (index)             │ Value  │
├─────────────────────┼────────┤
│ Total MRs           │ 58     │
│ Total Comments      │ 966    │
│ Average Comments/MR │ 16.7   │
│ Min Comments/MR     │ 3      │
│ Max Comments/MR     │ 80     │
│ Median Comments/MR  │ 9.5    │
└─────────────────────┴────────┘
L'évolution du nombre de commentaires par MR dans le temps (toujours en appliquant un EWMA pour lisser la courbe)

c  51 ┤
o  47 ┤
m  44 ┤━━━━━━━┓
m  41 ┤       ┃
e  37 ┤       ┃
n  34 ┤       ┗━━┓
t  30 ┤          ┃
s  27 ┤          ┗┓
/  24 ┤           ┗━━━━━━━┓
M  20 ┤                   ┗━┓
R  17 ┤                     ┗━━┓       ┏━━━━━━┓
   14 ┤                        ┗━━━━━━━┛      ┗━━┓ ┏━━━━━━━━━━━━━━━━━━━━━┓
   10 ┤                                          ┗━┛                     ┗━━━━━━━
    7 ┤
    3 ┤
    0 ┤
      └┬───────┬──┬┬─────┬─┬─┬┬─┬───────┬──┬───┬──┬─┬─────┬─┬┬─┬─────┬─┬──┬┬────┬▶
          11-10     11-1711-20     11-26  12-0112-04 12-0812-11 12-1512-18 12-22
                                date (utc)
╔════════════════════════════════════════════════╗
║       📋 Conventional Comments Analysis        ║
╚════════════════════════════════════════════════╝
Global Overview
───────────────
┌─────────────────────────┬─────────┐
│ (index)                 │ Value   │
├─────────────────────────┼─────────┤
│ Total Comments          │ 966     │
│ Conventional Comments   │ 736     │
│ Unconventional Comments │ 230     │
│ Adoption Rate           │ 76.2%   │
└─────────────────────────┴─────────┘
Label Distribution
──────────────────
┌────────────┬────────────┐
│ (index)    │ Percentage │
├────────────┼────────────┤
│ Praise     │ 1.4%       │
│ Question   │ 54.6%      │
│ Suggestion │ 14.9%      │
│ Issue      │ 21.3%      │
│ Nitpick    │ 7.9%       │
└────────────┴────────────┘
Praise Ratio
────────────
┌──────────────────────────────────┬────────┐
│ (index)                          │ Value  │
├──────────────────────────────────┼────────┤
│ Praise Count                     │ 10     │
│ Critique Count (issue + nitpick) │ 215    │
│ Ratio (praise/critique)          │ 4.7%   │
└──────────────────────────────────┴────────┘

Interprétation :

  • Adoption 76% → majorité de l'équipe utilise le format

  • Praise ratio 4.7% → 10 praises pour 215 critiques, marge de progression

  • Questions 54% → ratio élevé, peut s'expliquer par un contexte d'onboarding ou de montée en compétence

ℹ️ Tip: Filtrer les bots (dependabot, renovate, ...) pour analyser uniquement les reviews humaines.


Défis et limites

La méthode n'est pas sans écueils. Quelques pièges à éviter :

Formalisme vide

Le label ne remplace pas l'explication. issue: Variable mal nommée sans contexte reste inutile.

→ Toujours expliquer le "pourquoi" : userData serait plus explicite que data pour le contexte business.

Praise générique

praise: Joli remplit la règle mais sape son esprit. Un praise vague érode la confiance.

→ Être spécifique : praise: Excellent usage du pattern Builder pour le UserDTO

Abus de non-blocking

Si 90% des commentaires sont (non-blocking), la review n'apporte plus de valeur.

→ Oser bloquer quand c'est justifié.

Résistance initiale

Le format peut sembler bureaucratique au début.

→ Montrer par l'exemple plutôt qu'imposer. Les bénéfices visibles dans les reviews des autres encouragent l'adoption.


Conclusion

Selon moi, le problème principale n'est pas technique: c'est un problème de communication. Conventional Comments ne réinvente pas la review, il rend l'implicite explicite.

Pour les développeurs :fini de deviner si un commentaire bloque le merge. Pour les relecteurs :un cadre pour structurer le feedback sans paraître condescendant. Pour les équipes :moins de friction, plus d'apprentissage.

Ce n'est pas une solution miracle. Le format ne remplace pas l'empathie ni le jugement. Mais c'est un premier pas concret vers des reviews plus efficaces et plus humaines.

Pour commencer : essayez sur votre prochaine MR. Un suggestion (non-blocking): ou un praise: sincère. Observez la réaction.


Ressources


Cet article s'inspire d'une implémentation réelle de Conventional Comments dans une équipe de développement fullstack. Tous les exemples sont basés sur des situations réellement rencontrées, avec des détails d'identification modifiés.