10 modèles mentaux pour du code de meilleur qualité

Albéric Trancart

Qu'est-ce qui fait l'expérience d'un dev ?

Photo d'un rookie, circa 2026

Rare photo d'un senior *avant* les 3 verres de chartreuse

Je suis un grand fan de jeux de rôles

Forcément, j'ai pris le livre de règles

Après une cinquantaine d'ouvertures...

...ma réaction

Le tabouret que j'ai pris il y a 6 mois...

💥

Soudure

qui lâche

...ma réaction

Je me suis connecté à ma banque...

Je me suis connecté à ma banque...

Déconnecté

en changeant

de page

Mauvaise font

Je me suis connecté à ma banque...

Page qui plante une fois

sur deux au refresh

...ma réaction

Quand je code...

...ma réaction

...la réaction du client

Être exposé à autant de bugs m'a donné un gout pour les choses qui marchent

Dure 30 ans

Dure depuis 160 ans

Comment faire des choses qui marchent ?

Chez Theodo, on aime ce qu'a fait Toyota avec le lean

On a regardé ce que font les meilleurs...

Sadao Nomura

Many companies seem to be in trouble because product quality is not getting better despite company-wide [...] "quality first" policy

Avec des résultats certains

92% de réduction des défauts en 3 ans

Le livre est une compilation de feuilles A3

Le A3 principal : une procédure en 8 étapes pour

analyser les défauts et les éradiquer via des contremesures

Qu'est-ce qui fait l'expérience d'un dev ?

Photo d'un rookie, circa 2026

Rare photo d'un senior *avant*
les 3 verres de chartreuse

Regardons l'étymologie du mot...

expérience

ex - periri

Au delà

Épreuve

Même racine que

"periculum" = danger !

Un dev expérimenté, c’est un dev

qui a des centaines de cicatrices

Combat de la facture cloud qui a augmenté de 3.000€

Souvenir des 2000 emails envoyés par accident

Cicatrice du

truncate de la table user en prod

Depuis 2 ans, je regarde des tas de défauts

Chaque semaine, on regarde un défaut avec tous les devs

Voici la compil'

des cicatrices que

je vois le plus souvent

Problème

Lors de la mise en production, il y a un downtime de 10 minutes

Défaut

public function up(Schema $schema): void
{
  $this->addSql('ALTER TABLE product ADD enabled TINYINT(1) NOT NULL');
}

Le dev ne savait pas que :

Cause racine

  • Modifier le schéma d'une table pose un lock exclusif sur la table
  • Le comportement de ALTER TABLE dépend :
    • Si DEFAULT explicite, c'est ajouté dans la définition de la table
    • Si DEFAULT implicite, la table est réécrite pour remplir le champ

Problème

Le frontend crash à cause d'une erreur 500 renvoyée par le back

Défaut

getTokenInformation(): Claims {
  return this.isIsamAuthenticated()
    ? (this.authenticationService.getUserData() as Claims)
    : this.mcbUserAsClaims(this.getMcbUserData() as McbUserData);
}

mcbUserAsClaims(userData: McbUserData): Claims {
  return {
    firstName: userData.given_name, // userData is null
    lastName: userData.family_name,
    emailAddress: userData.email,
    // ...
  };
}

L'utilisation de `as` met sous silence les erreurs du compilateur

Cause de détection tardive

J'ai fait un quick fix, j'ai pas le temps pour les actions long terme

J'aimerai faire une refacto mais le métier me dit qu'il n'y a pas de place dans le sprint

On a réussi à négocier 20% pour faire de la qualité. En pratique on arrive pas à les faire mais bon...
On y arrivera jamais, j'ai abandonné

NON !

Est-ce qu'un chirurgien demande au patient

le droit de se laver les mains avant d'opérer ?

NON !

Est-ce qu'un pompier demande au syndic de copro

"Je peux enfoncer la porte de l'immeuble en feu ?"

...

Est-ce qu'un dev demande au PO

"Je peux faire cette refacto ?"

Arrêtons de demander la permission de bien faire notre travail ! 

Le pouvoir ça ne se demande pas, ça se prend

Méthode pour devenir un JEDI

  1. Choisissez un problème
  2. Résolvez-le

Exemple : cantine d'entreprise

Moins de 40 events par semaine pour :

1 app mobile

1 app de caisse

1 backend cloud

1 backend on premise

2 frontends web

 

Utilisés par 250 personnes chaque jour

Quality will surely improve by thoroughly addressing and solving all the problems...
There are no shortcuts to quality assurance

Problème

On ne peut plus [tab] en dehors d'un input de type nombre

Défaut

<input 
  type="number"
  onKeyDown={event => {
    const testInput = /[0-9,.]|Backspace|Enter/.test(event.key)
    testInput && event.preventDefault()
  }}
/>

Pourquoi vouloir changer le comportement par défaut d'un élément HTML qui prend déjà en compte les bonnes pratiques ?

Cause racine

Ne jamais oublier la possibilité nulle !

(= ne rien faire)

Problème

Toutes les interactions JS sont cassées

Défaut

<script type="esms-options">{"shimMode":true}</script>
<script type="module-shim" src="main-XDPCJWQE.js" "="">

Ce n'est pas parce que ça ressemble à une string

que ça doit être manipulé comme une string...

Cause racine

indexContent = indexContent.replace(
  /<script src="(.*?main.*?)><\/script>/,
  '<script type="module-shim" src="$1"></script>'
);

Dans le process du builder Angular

Problème

Un bilan PDF ne se génère pas (crash)

Défaut

public class VirtualQuestionService {
  // the G-4bis question is wrongly labelled as a virtual question
  // should be Set.of( "G-4bisbis");
  private static final Set<String> VIRTUAL_QUESTION_CODES = Set.of("G-4bis", "G-4bisbis");

  // virtual question = questions that are optional
  public boolean isAVirtualQuestion(String questionCode) {
    return (VIRTUAL_QUESTION_CODES.contains(questionCode));
  }
}

given choice between complexity

or one on one against t-rex,

grug take t-rex: at least grug see t-rex

Vous connaissez la différence entre une bonne et une mauvaise contremesure ?

Une mauvaise contremesure a tendance à "rajouter un if"

Une bonne contremesure a tendance à simplifier le code

Problème

Problème de rendu PDF

Défaut

L'affichage était correct en local sur le poste du dev.

Cela était dû à un écart de versions dans la logique de rendu :

Cause de détection tardive

Un élément page-break est utilisé au mauvais endroit

 

Local

  • Node 20
  • HeadlessChrome/121.0.6167.85
  • Puppeteer 21

 

Staging

  • Node 14
  • HeadlessChrome/97.0.4691.0
  • Puppeteer 22

Problème

Lorsque l'on ajout une 8ème fonds,

le simulateur de fonds ne marche plus

Défaut

for ($i = 0; $i < 7; $i++) {
    $this->updateFund($funds[$i]);
}

Cause racine

Le dev a utilisé un pattern (boucle for "à la main") qui a beaucoup d'erreurs potentielles

foreach ($funds as $fund) {
    $this->updateFund($fund);
}

Quand on passe outre un poka-yoke...

Problème

Faille XSS via les avis Google injectés dans les données JSON-LD

Défaut

export const StructuredDataScript = ({
  id,
  jsonLd,
}: StructuredDataScriptProps): JSX.Element => {
  return (
    <script
      id={id}
      type="application/ld+json"
      dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
    />
  );
};

Cause racine

Le dev a utilisé "dangerouslySetInnerHTML"

sans se poser de question

Of course it goes to 11!

await this.entityManager.transaction(async (transactionalEntityManager) => {
  await transactionalEntityManager.save(CashRegisterImage, {
    id: imageId,
    storageId: blobName,
  });

  await this.apiStorageService.uploadBlob(IMAGES_CONTAINER, blobName, file);
});

Exemple : utilisation de transactions SQL

On se prémunit contre les données inconsistantes :

  • en cas d'erreur de la BDD
  • en cas d'erreur de l'upload de fichier

Pour aller plus loin...

Le livre de Nomura

Les modèles mentaux sous format post de blog

Ils marchent aussi pour d'autres métiers que le dev !

Le meilleur...

Merci !

Albéric Trancart

Lien vers les modèles mentaux : dantotsu.tech

QRCode pour le feedback 🙏

10 modèles mentaux pour du code de meilleure qualité

By Albéric Trancart

10 modèles mentaux pour du code de meilleure qualité

  • 153