Coder vs Développeur : Configuration partie 2, le retour
Autre aspect de l'épineuse question de la configuration, j'ai bien parlé de comment faire de la bonne config dans mon post précédent sur le sujet, là on va aborder le sujet sous un autre angle. J'ai une application, on a certaines exigences concernant la configuration, qui commence à avoir une taille méritant réorganisation, quelle(s) stratégie(s) adopter pour faire cette réorganisation. Et on va le voir ensembles, ce n'est pas exactement une mince affaire.
Je précise aussi que je ne rentrerai pas dans le détail de ce que fait exactement cette application, c'est 100% hors sujet.
Ce qui nous intéresse dans cet exemple c'est comment réfléchir autour de ce problème, comment raisonner pour rationnaliser l'usage de la configuration dans ce projet, comment ne pas produire un foutoir et tenter de garantir un résultat exploitable à terme. En gros, c'est la logique et la discussion qui sont intéressants ici, l'exemple de l'application, ce n'est qu'un exemple qui sert à illustrer la manière de réfléchir, rien de plus.
Rentrons dans le vif du sujet. Voici les informations utiles concernant l'application qui vont permettre de comprendre la réflexion :
Du coup, assez vite on se retrouve avec une config qui contient :
Et bien sûr on a appliqué autant que possible les réflexions de l'autre post sur le fait d'en rentre le moins possible explosifs (allez lire l'autre post si vous ne voyez pas de quoi je parle 😉), de mettre des valeurs par défaut, etc.
Et nous avons atteint la fameuse étape du "Vite, il faut faire du rangement tant que c'est pas trop cher, ça devient un sacré bazar !"
Du coup, que fait-on ? Comment on découpe pour mieux ranger ?
Premier sujet absolument non négociable, le gros bloc de données de références suit son propre chemin à part du reste pour coller au besoin métier qui le concerne. Ça fait un gros paquet en moins, mais pour le reste, que fait-on ? Le dev en charge a fait un exemple et m'a appelé pour qu'on en parle à partir d'un cas concret.
Son idée : faire un découpage technique. En gros, la config centrale d'un côté, les configs de chaque composant d'un autre, les chemins vers les binaires ailleurs, les chemins vers les dossiers de travail ailleurs, etc.
Ma réaction : "c'était pas ça que j'avais en tête que on a parlé de faire du découpage et des regroupements, mais si ça se trouve c'est mieux que ce à quoi je pensais, on pose tout à plat sur un tableau et on en parle"
On a d'abord listé les principales stratégies sur ce type de problème (tout en gardant nos contraintes bien sûr, comment par exemple de garder une configuration centralisée pour n'avoir à la mettre à jour qu'à un seul emplacement), en voici un résumé :
Découpage technique
Recommandé par LinkedIn
Découpage par composant
Découpage par étape
Le découpage technique a l'avantage de ne presque jamais bouger, structurellement parlant. On va assez rarement avoir besoin de rajouter de nouveaux classes de sérialisation de configuration, et tout ce qu'on doit ranger est simple et rentre dans peu de catégories. Il a le défaut qu'un même composant va être présent dans plusieurs catégories de découpe, rendant le nettoyage compliqué et l'ajout de nouveaux composants peut-être "à risque" (un jour quelqu'un risque de se dire "je range tout là, c'est plus simple").
Le découpage par composant a l'avantage qu'au moins tout est simple et bien regroupé, sauf qu'il faut créer une nouvelle classe de sérialisation pour chaque nouveau composant à intégrer. La suppression d'un composant est simple comme bonjour, la maintenance en général est simple, c'est juste la solution qui implique le plus de travail à chaque nouveau composant.
Le découpage par étape a l'avantage de bouger relativement peu lui aussi, mais pose le même soucis de redondance que le découpage technique mais uniquement pour le cas des rares composants qui interviennent sur plusieurs étapes. Le vrai risque est si on doit changer la manière dont les étapes sont organisées, car on couple la structure de la configuration avec le détail des étapes dans le process. Tant qu'on ne fait qu'en rajouter ça ne pose pas de soucis mais le jour où une étape est supprimée ou découpée en plusieurs par exemple, on va se retrouver avec une charge de travail assez forte "pour rien".
On a donc plusieurs coûts et gains à chaque fois : combien ça me coûte d'ajouter un nouveau composant, d'ajouter juste un nouveau paramètre de configuration (est-ce que je trouve facilement où il va et est-ce que j'ai des chances raisonnables d'appeler son objet de configuration dans le code, en gros), de supprimer un composant et sa configuration associée, est-ce que je peux retrouver facilement tout la configuration associée à un composant si celui-ci doit bouger ou être remplacé ou complété par un autre, ce genre de choses.
Pour tenter de gagner le meilleur des mondes, on a finit par estimer une solution alternative, connue comme étant très bancale, que voici :
Découpage par unicité
Très vite la conclusion est tombée sur cette dernière option : trop de risque qu'elle ne supporte pas la durée et aggrave le foutoir à partir du moment où quelqu'un devra ajouter quelque chose sans trop comprendre le pourquoi du comment.
Du coup, que fait-on ? Reste-t-on sur le découpage technique qui va répandre chaque composant dans toutes les catégories mais est très simple à mettre en place et à comprendre, va-t-on sur un découpage par étape de traitement qui a des avantages similaires mais un risque accru en cas d'évolution de l'algo central ou encore un découpage par composant qui implique un coup plus élevé à chaque nouveau composant mais une encapsulation maximale et une simplicité aussi élevée qu'avec les autres ?
Et bien le choix a été tourné vers le découpage par composant. Parce que le surcoût de développement (comparé aux autres solutions s'entend) n'est pas si énorme, parce que le gain en maintenance est important (ex : si on désactive un composant on sait qu'on peut retirer tout son bloc de configuration ou au moins le commenter pour les frileux côté exploitation), parce que ça permet d'agir en toute confiance.
J'insiste sur une chose : ce choix n'est rien de plus qu'une prise de décision avec un objectif et l'espoir que ça se passe comme on l'imagine. Je ne prétends ni que ce choix est le bon, ni que quelqu'un de compétent aurait fait le même.
Simplement maintenant, il y a un exemple qui illustre comment on fait pour organiser sa configuration. Et c'est ce genre de réflexion qui fait la différence entre des gens qui savent "juste" coder et d'autres qui savent faire plus. Non pas que certains seraient moins légitimes pour coder que d'autres, simplement qu'à différence de profil il peut y avoir différence de poste, tout simplement, comme toujours dans cette série de billets.
Et ensuite la question qui fâche : là on a eu la chance de voir ce besoin tôt dans le cycle de vie du produit. Qu'en est-il quand il a de nombreuses années d'existence et quelques dizaines ou centaines de paires de mains et de cerveaux qui lui sont passés dessus, générant des cohortes de lignes de configuration dont on ignore si ça sert encore à quelque chose ? Vous pensez que ça pourrait faire l'objet d'un troisième billet, la Vengeance de la Configuration ? J'ai quelques notes à ce sujet, si jamais ça tente certains...