Albéric Trancart
Fullstack dev @ Theodo
Albéric Trancart
Photo d'un rookie, circa 2026
Rare photo d'un senior *avant* les 3 verres de chartreuse
💥
Soudure
qui lâche
Déconnecté
en changeant
de page
Mauvaise font
Page qui plante une fois
sur deux au refresh
Dure 30 ans
Dure depuis 160 ans
Sadao Nomura
Many companies seem to be in trouble because product quality is not getting better despite company-wide [...] "quality first" policy
92% de réduction des défauts en 3 ans
Le A3 principal : une procédure en 8 étapes pour
analyser les défauts et les éradiquer via des contremesures
Photo d'un rookie, circa 2026
Rare photo d'un senior *avant*
les 3 verres de chartreuse
expérience
ex - periri
Au delà
Épreuve
Même racine que
"periculum" = danger !
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
Chaque semaine, on regarde un défaut avec tous les devs
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
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é
Est-ce qu'un chirurgien demande au patient
le droit de se laver les mains avant d'opérer ?
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 ?"
Le pouvoir ça ne se demande pas, ça se prend
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 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
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
Staging
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);
}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
await this.entityManager.transaction(async (transactionalEntityManager) => {
await transactionalEntityManager.save(CashRegisterImage, {
id: imageId,
storageId: blobName,
});
await this.apiStorageService.uploadBlob(IMAGES_CONTAINER, blobName, file);
});On se prémunit contre les données inconsistantes :
Le livre de Nomura
Les modèles mentaux sous format post de blog
Albéric Trancart
Lien vers les modèles mentaux : dantotsu.tech
QRCode pour le feedback 🙏
By Albéric Trancart