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 2025

Rare photo d'un senior avant son départ pour une autre boîte

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

Le livre est une compilation de feuilles A3

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

Photo d'un rookie, circa 2025

Rare photo d'un senior avant son départ pour une autre boîte

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.authenticationService.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

NON !

Est-ce qu'un technicien de maintenance d'avions

demande aux 150 passagers

"Je peux prendre 30 minutes avant le vol pour inspecter ?"

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 (JEDI !)

Exemple #1 : plateforme interne d'achats

Exemple #2 : 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

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

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.authenticationService.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

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.authenticationService.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

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.authenticationService.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

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.authenticationService.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

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.authenticationService.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

Quand on passe outre un poka-yoke...

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.authenticationService.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

Of course it goes to 11!

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.authenticationService.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

Merci !

Albéric Trancart

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

By Albéric Trancart

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

  • 132