Embarrassant, j'ai introduit une bibliothèque "commune", nommée ainsi, dans un environnement d'équipe il y a quelques décennies. À l'époque, je ne comprenais pas vraiment la dynamique de ce qui pouvait se produire dans une équipe mal coordonnée en quelques mois seulement.
Quand je l'ai présenté, je pensais l'avoir précisé et documenté également que c'est pour des choses que nous serions tous d'accord que nous trouvons utiles au quotidien, qu'elle est destinée à être une bibliothèque minimaliste et que la bibliothèque ne devrait dépendre de rien d'autre que de la bibliothèque standard pour un déploiement aussi simple que possible dans les nouveaux projets. À l'époque, je pensais que c'était notre propre petite extension de la bibliothèque standard pour des choses que, dans notre domaine particulier, nous trouvions utiles au quotidien.
Et ça a commencé assez bien. Nous avons commencé avec une bibliothèque mathématique ( common/math*
) de routines que nous utilisions tous quotidiennement, car nous travaillions en infographie souvent lourde sur l'algèbre linéaire. Et comme nous interopérions souvent avec du code C, nous nous sommes mis d'accord sur certaines fonctions utilitaires utiles find_index
qui, contrairement àstd::find
en C ++, retournerait un index à un élément trouvé dans une séquence au lieu d'un itérateur qui imite le fonctionnement de nos fonctions C - des choses de ce genre - un peu éclectique mais minimaliste et largement utilisé pour rester familier et pratique pour tout le monde , et la familiarité instantanée est un critère extrêmement important tel que je le vois en essayant de faire tout ce qui est "commun" ou "standard" car s'il est vraiment "commun", il devrait avoir cette qualité familière à cause de sa large adoption et usage quotidien.
Mais au fil du temps, les intentions de conception de la bibliothèque m'ont échappé lorsque les gens ont commencé à ajouter des choses qu'ils utilisaient personnellement qu'ils pensaient simplement être utiles à quelqu'un d'autre, pour ne trouver personne d'autre l'utilisant. Et plus tard, quelqu'un a commencé à ajouter des fonctions qui dépendaient d'OpenGL pour les routines courantes liées à GL. Plus loin, nous avons adopté Qt et les gens ont commencé à ajouter du code qui dépendait de Qt, donc déjà la bibliothèque commune dépendait de deux bibliothèques externes. À un moment donné, quelqu'un a ajouté des routines de shader communes qui dépendaient de notre bibliothèque de shaders spécifique à l'application, et à ce moment-là, vous ne pouviez même pas le déployer dans un nouveau projet sans apporter Qt, OGL, et notre bibliothèque de shader spécifique à l'application et écrire un script de construction non trivial pour votre projet. Il s'est donc transformé en ce gâchis éclectique et interdépendant.
Mais j'ai également découvert en débattant de ce qui devrait et ne devrait pas entrer dans cette bibliothèque que ce qui est considéré comme "commun" peut facilement se transformer en une idée très subjective si vous ne définissez pas une règle de ligne très stricte selon laquelle ce qui est "commun" est ce que tout le monde a tendance à trouver utile au quotidien. Tout relâchement des normes et il se dégrade rapidement des choses que tout le monde trouve utiles au quotidien à quelque chose qu'un développeur unique trouve utile qui pourrait avoir la possibilité d'être bénéfique pour quelqu'un d'autre, et à ce moment-là, la bibliothèque se dégrade en un gâchis éclectique très rapidement .
Mais en outre, lorsque vous atteignez ce point, certains développeurs peuvent commencer à ajouter des choses pour la simple raison qu'ils n'aiment pas le langage de programmation. Ils pourraient ne pas aimer la syntaxe d'une boucle for ou d'un appel de fonction, à quel point la bibliothèque commence à se remplir de choses qui ne font que combattre la syntaxe fondamentale du langage, remplaçant quelques lignes de code simple qui n'est pas vraiment duplication de toute logique vers une seule ligne laconique de code exotique familier au développeur qui a introduit un tel raccourci. Un tel développeur pourrait alors commencer à ajouter plus de fonctionnalités à la bibliothèque commune implémentée à l'aide de tels raccourcis, À ce stade, des sections importantes de la bibliothèque commune deviennent entrelacées avec ces raccourcis exotiques qui peuvent sembler beaux et intuitifs pour le développeur qui les a présentés, mais laids et étrangers et difficiles à comprendre pour tout le monde. Et à ce stade, je pense que vous savez que tout espoir de faire quelque chose de vraiment «commun» est perdu, car «commun» et «inconnu» sont des idées polaires opposées.
Il y a donc toutes sortes de boîtes de vers là-bas, au moins dans un environnement d'équipe peu coordonné, avec une bibliothèque avec des ambitions aussi larges et aussi généralisées que des "trucs couramment utilisés". Et bien que le problème sous-jacent ait pu être la coordination lâche par-dessus tout, au moins plusieurs bibliothèques destinées à servir un objectif plus singulier, comme une bibliothèque destinée à fournir des routines mathématiques et rien d'autre, ne se dégraderaient probablement pas de manière aussi significative en termes de concevoir la pureté et les dépendances comme une bibliothèque "commune". Donc, rétrospectivement, je pense qu'il serait beaucoup mieux de se tromper du côté des bibliothèques qui ont des intentions de conception beaucoup plus claires. J'ai également constaté au fil des ans que le but et l'applicabilité sont des idées radicalement différentes.
De plus, je suis certes au moins un peu impraticable et me soucie peut-être un peu trop de l'esthétique, mais la façon dont j'ai tendance à percevoir mon idée de la qualité d'une bibliothèque (et peut-être même de la "beauté") est jugée davantage par son maillon le plus faible que C'est le plus fort, de la même manière que si vous me présentiez la nourriture la plus appétissante du monde mais, dans la même assiette, y mettez quelque chose de pourri qui sent vraiment mauvais, j'ai tendance à vouloir rejeter toute l'assiette. Et si vous êtes comme moi à cet égard et que vous faites quelque chose qui invite toutes sortes d'ajouts comme quelque chose appelé "commun", vous pourriez vous retrouver à regarder cette plaque analogique avec quelque chose de pourri sur le côté. Donc, de même, je pense que c'est bien si une bibliothèque est organisée, nommée et documentée d'une manière telle qu'elle ne fonctionne pas. t inviter de plus en plus et plus d'ajouts au fil du temps. Et cela peut même s'appliquer à vos créations personnelles, car j'ai certainement créé des trucs pourris ici et là, et ça "tache" beaucoup moins si ce n'est pas ajouté à la plus grande assiette. Séparer les choses en petites bibliothèques très singulières a également tendance à mieux découpler le code, ne serait-ce que par la simple vertu qu'il devient beaucoup moins pratique de commencer à tout coupler.
La déduplication du code a été martelée en moi au fil des ans, mais je pense que je devrais l'essayer cette fois-ci.
Ce que je pourrais suggérer dans votre cas, c'est de commencer à vous détendre sur la déduplication de code. Je ne dis pas de copier et coller de gros extraits de code mal testé et sujet aux erreurs ou quoi que ce soit de ce genre, ou de dupliquer d'énormes quantités de code non trivial qui ont une probabilité décente d'exiger des modifications à l'avenir.
Mais surtout si vous êtes d'humeur à créer une bibliothèque "commune", pour laquelle je suppose que votre désir est de créer quelque chose de largement applicable, hautement réutilisable, et peut-être idéalement quelque chose que vous trouvez tout aussi utile aujourd'hui que vous le feriez dans une décennie. , alors parfois vous pourriez même avoir besoin ou vouloir une duplication pour atteindre cette qualité insaisissable. Parce que la duplication pourrait en fait servir de mécanisme de découplage. C'est comme si vous voulez séparer un lecteur vidéo d'un lecteur MP3, alors vous devez au moins dupliquer certaines choses comme les piles et les disques durs. Ils ne peuvent pas partager ces choses ou bien ils sont couplés de manière indivisible et ne peuvent pas être utilisés indépendamment les uns des autres, et à ce stade, les gens pourraient ne plus être intéressés par l'appareil s'ils ne veulent que lire des MP3. Mais quelque temps après avoir séparé ces deux appareils, vous pourriez constater que le lecteur MP3 peut bénéficier d'une conception de batterie différente ou d'un disque dur plus petit que le lecteur vidéo, auquel cas vous ne dupliquez plus rien; ce qui a commencé au départ comme une duplication pour permettre à ce périphérique interdépendant de se diviser en deux périphériques distincts et indépendants pourrait s'avérer plus tard produire des conceptions et des implémentations qui ne sont plus du tout redondantes.
Cela vaut la peine de considérer les choses du point de vue de celui qui utilise une bibliothèque. Souhaitez-vous réellement utiliserune bibliothèque qui minimise la duplication de code? Il y a de fortes chances que vous ne le fassiez pas car celui qui en dépend dépendra naturellement d'autres bibliothèques. Et ces autres bibliothèques peuvent dépendre d'autres bibliothèques pour éviter de dupliquer leur code, et ainsi de suite, jusqu'à ce que vous ayez besoin d'importer / lier 50 bibliothèques différentes pour simplement obtenir des fonctionnalités de base comme le chargement et la lecture d'un fichier audio, et cela devient très lourd . Pendant ce temps, si une telle bibliothèque audio choisit délibérément de dupliquer certaines choses ici et là pour atteindre son indépendance, elle devient tellement plus facile à utiliser dans de nouveaux projets, et il est probable qu'elle n'aura pas besoin d'être mise à jour presque aussi souvent depuis qu'elle a gagné. t besoin de changer à la suite du changement d'une de ses bibliothèques externes dépendantes qui pourrait essayer de remplir un objectif beaucoup plus généralisé que ce dont la bibliothèque audio a besoin.
Donc, parfois, il vaut la peine de choisir délibérément de dupliquer un peu (consciemment, jamais par paresse - en fait par diligence) afin de découpler une bibliothèque et de la rendre indépendante parce que, grâce à cette indépendance, elle atteint un plus large éventail d'applicabilité pratique et même stabilité (plus de couplages afférents). Si vous souhaitez concevoir les bibliothèques les plus réutilisables possibles qui vous dureront d'un projet à l'autre et au fil des ans, alors en plus de restreindre sa portée au minimum, je suggère en fait d'envisager de dupliquer un peu ici. Et naturellement, écrivez des tests unitaires et assurez-vous qu'il est vraiment minutieusement testé et fiable dans ce qu'il fait. C'est uniquement pour les bibliothèques que vous voulez vraiment prendre le temps de généraliser à un point qui va bien au-delà d'un seul projet.