Meilleures pratiques pour le partage de minuscules extraits de code entre projets


102

J'essaie toujours de suivre le principe DRY strictement au travail; chaque fois que je répète du code par paresse, il mord plus tard lorsque je dois le conserver à deux endroits.

Mais souvent, j'écris de petites méthodes (peut-être 10 à 15 lignes de code) qui doivent être réutilisées dans deux projets qui ne peuvent pas se référencer. Cette méthode peut être liée à la mise en réseau / aux chaînes / au MVVM, etc. Il s’agit d’une méthode généralement utile qui n’est pas spécifique au projet dans lequel elle est placée

La méthode standard pour réutiliser ce code consiste à créer un projet indépendant pour le code réutilisable et à référencer ce projet lorsque vous en avez besoin. Le problème, c’est que nous nous retrouvons dans l’un des deux scénarios suivants:

  1. Nous nous retrouvons avec des dizaines / centaines de petits projets - chacun pour héberger les petites classes / méthodes que nous devions réutiliser. Vaut-il la peine de créer un tout nouveau .DLLpour juste un petit bout de code?
  2. Nous nous retrouvons avec un seul projet contenant une collection croissante de méthodes et de classes sans rapport. Cette approche est celle d’une entreprise pour laquelle j’ai travaillé auparavant; ils avaient un projet nommé base.commonqui contenait des dossiers pour les choses que j'ai mentionnées ci-dessus: réseau, manipulation de chaîne, MVVM, etc. Il était incroyablement pratique, mais le référencer entraînait inutilement tout le code inutile dont vous n'aviez pas besoin.

Donc ma question est:

Comment une équipe de logiciels réagit-elle au mieux pour la réutilisation de petits morceaux de code entre projets?

Je m'intéresse particulièrement si quelqu'un a travaillé dans une entreprise qui a des politiques dans ce domaine ou qui a personnellement rencontré ce dilemme, comme moi.


Remarque: mon utilisation des mots "Projet", "Solution" et "Référence" provient d'un contexte de développement .NET dans Visual Studio. Mais je suis sûr que ce problème est indépendant de la langue et de la plateforme.


21
+1, bien que je pense qu'il y a un élément d'humour chez une personne travaillant avec .NET qui craint de faire glisser du code non pertinent via une référence de DLL.
JDB

2
@ColeJohnson .NET est en soi une énorme référence! Probablement beaucoup plus gros que les dll que je me ferais.
George Powell

2
Je comprends ça. Cependant, le compilateur JIT de .NET charge uniquement les méthodes requises dans la RAM (lorsqu'elles sont appelées)
Cole Johnson

1
Vrai. Bien que vous ayez toujours à distribuer tout le framework .NET à tous ceux qui souhaitent utiliser votre produit, les gros projets et les solutions complexes sont plus difficiles à gérer.
George Powell

Réponses:


75

Si ce sont vraiment des méthodes / classes réutilisables, vous pouvez les écrire dans un petit nombre de bibliothèques 'Swiss Army Knife'. Nous le faisons assez souvent dans mon entreprise. nous les appelons bibliothèques de cadres:

  • Framework.Data - Utilitaires pour travailler avec des requêtes de base de données.
  • Framework.ESB - Méthodes standard d'interaction avec notre bus de service d'entreprise
  • Framework.Logging - Système de journalisation unifié
  • Framework.Services - Utilitaires pour interagir avec les services Web
  • Framework.Strings - Utilitaires de manipulation avancée de chaîne / recherche de chaîne fuzzy, etc.
  • ...

En tout, il y a environ une douzaine de bibliothèques. Vous pouvez vraiment distribuer le code comme bon vous semble, de sorte que vous n'ayez pas à vous retrouver avec des centaines de personnes ou à tout jeter dans un assemblage géant. Je trouve que cette approche convient, car seuls certains de nos projets en auront besoin Framework.Dataet quelques-uns n'en auront jamais besoin Framework.Strings, de sorte que les consommateurs ne peuvent sélectionner que les parties du cadre pertinentes pour leur projet.

S'ils ne sont que des extraits, et non des méthodes / classes pouvant être facilement réutilisées, vous pouvez simplement les distribuer sous forme d'extraits de code dans l'EDI (par exemple , Extraits de code Visual Studio ). Les équipes avec lesquelles j'ai travaillé par le passé disposaient d'une bibliothèque commune d'extraits de code facilitant le respect de nos pratiques de codage standard avec le code interne.


4
+1 Ce serait aussi mon approche. Intéressé de savoir comment vous avez décidé de mettre du code qui traite des éléments de deux ou plusieurs aspects. Par exemple, IPAddressToString. Et si vous autorisez ces bibliothèques à s’utiliser les unes les autres. Par exemple, les services et les données peuvent probablement bénéficier de l'exploitation forestière ...
Marjan Venema

5
@MarjanVenema Pour le code transversal, cela dépend de ce que les consommateurs vont trouver la méthode plus utile. En effet IPAddressToString, il est probable que les consommateurs utilisant des protocoles de réseau devront l'utiliser, mais les consommateurs qui manipulent beaucoup de chaînes ne se soucient peut-être pas beaucoup des adresses IP. Cela aboutirait probablement dans un paquet de mise en réseau plutôt que Framework.Strings.
pswg

@MarjanVenema Nous essayons d'éviter les interdépendances. Nos services et nos infrastructures de données sont conçus de manière à ne pas effectuer de journalisation par eux-mêmes, mais facilitent l’écriture par le consommateur du code de journalisation approprié. Les bibliothèques de structure sont autorisées à se référencer les unes les autres, mais uniquement par extension, par exemple Framework.Logging.Gibraltarun complément particulier au système de journalisation.
pswg

5
+1 Vous pouvez prendre ces bibliothèques d'infrastructure et les déployer dans un référentiel NuGet interne (aussi simple qu'un dossier réseau) et vous disposez d'un moyen agréable de le gérer.
Steven Evers

2
@SteveEvers Je travaille actuellement sur la configuration. : P
pswg

21

Je ne suis pas d'accord avec la réponse acceptée pour plusieurs raisons.

D'après mon expérience, quand je vois des bibliothèques "diverses" comme la réponse acceptée, elles sont une excuse pour réinventer la roue (ou ne sont pas inventées ici ), un péché bien plus grave que celui de violer Dont Repeat Yourself (DRY) .

Parfois, violer DRY peut être un compromis raisonnable, c'est mieux que d'introduire un couplage serré. La réutilisation est une préoccupation secondaire par rapport à une bonne conception orientée objet. Un peu (je veux dire un petit montant, appliquer la règle de trois ) de la duplication est plus facile à comprendre qu'une base de code spaghetti.

L'approche de nombreuses bibliothèques d'usage général donne le mauvais exemple. Cela conduit à une fine granularité d'assemblage et trop d'assemblages est mauvais. J'ai récemment réduit une maison de 24 bibliothèques à 6 bibliothèques. Le temps de compilation est passé de quelques minutes à environ 20 secondes. Visual Studio est également plus lent à charger et moins réactif avec plus d'assemblages. Avoir trop de bibliothèques mène également à la confusion quant à où le code devrait vivre; préférez moins de règles simples.

Pourquoi les éléments du .Net Framework ne sont-ils pas suffisants? Le cadre est assez grand; j'ai souvent vu du code réimplémenter des éléments existants. Assurez-vous vraiment que vos frameworks comblent des lacunes dans le framework .Net et n'existent pas uniquement pour des raisons esthétiques (par exemple, "je n'aime pas le framework .Net ici" ou peut-être une optimisation prématurée ).

L'introduction d'une autre couche dans votre architecture a un coût de complexité important. Pourquoi la couche existe-t-elle? J'ai vu de fausses réutilisations, je veux dire par là que le code est construit sur un framework interne. Il aurait été beaucoup plus efficace de l’appliquer directement au-dessus des bibliothèques standard.

L'utilisation de technologies normalisées (telles que le framework .Net et les bibliothèques populaires tierces / open source) présente des avantages qui contrebalancent souvent les avantages technologiques comparatifs de sa création par vous-même. Il est plus facile de trouver des talents connaissant ces technologies et vos développeurs existants investiront davantage dans leur apprentissage.

Mes recommandations:

  • Ne pas partager ce code.
  • Créez une nouvelle bibliothèque si elle a un objectif cohérent. N'utilisez pas le modèle de conception boule de boue .
  • Réutilisez les bibliothèques tierces existantes si possible.
  • Préférez moins d'assemblys, avec des règles plus simples quant à l'emplacement du code.

1
Un avantage supplémentaire à l'utilisation des bibliothèques Open Source lorsqu'elles sont disponibles: si vous apportez des améliorations, vous pouvez les partager avec la communauté! Par exemple, avec .Net MS a publié une EnterpriseLibrary (maintenant Open Source) qui donne un assez bon ensemble d’outils pour les scénarios courants. Trouvez quelque chose qui pourrait être amélioré et hop! Tout le monde en profite!
Glenatron

2
Je ne vois pas vraiment de désaccord avec la réponse acceptée ici :-). "moins d'assemblages, avec des règles plus simples quant à l'endroit où le code devrait exister" n'est pas une contradiction avec la réponse acceptée. La réponse préconise également de n'utiliser que le nombre d'assemblages différents qui semble raisonnable.
Sleske

Cinq ans plus tard, les conseils de Microservice ont également convergé vers cette pratique: medium.com/standard-bank/…
Dave Hillier

11

Pour de petits morceaux de code - disons une classe unique sans dépendances - nous avons tendance à simplement copier et coller le code dans des projets. Cela ressemble à une violation de DRY, et j'admets que cela peut être parfois. Mais à long terme, cela a été beaucoup mieux que d’avoir une sorte de projet commun massif à plusieurs têtes pour plusieurs raisons.

Premièrement, il est simplement plus simple d’avoir le code à portée de main, en particulier lors de la création et du débogage.

Deuxièmement, invariablement, vous voudrez apporter quelques modifications au code commun de ce projet. Si vous avez une copie locale de la source, vous pouvez simplement modifier le réglage et l'appeler un jour. S'il existe une bibliothèque partagée, vous pouvez peut-être modifier cette bibliothèque, puis vous assurer de ne pas détruire toutes les autres applications ou de créer un cauchemar de gestion des versions.

Donc, s'il n'est pas assez costaud pour son propre espace de noms, nous avons tendance à l'insérer dans les éléments appropriés du projet et à l'appeler un jour.


5
Je ne suis pas d'accord avec cette approche. J'apprécie les problèmes de maintenance liés à la gestion de petits morceaux de code, mais je dirais qu'une bibliothèque commune pourrait être créée à partir de chacun d'entre eux, comme le suggère @psw. Avoir des copies de code dupliquées avec des ajustements mineurs pose des problèmes. Des hypothèses seront faites, les corrections de bugs seront manquées.
Andrew T Finnell

2
-1 (à la réponse). Il est certainement plus facile que tout le monde ait sa propre copie de sa propre version de programme. Voici comment le logiciel a été développé dans les années 80. J'ai depuis appris que - à long terme - cela conduisait à un désordre. Il est plus difficile de faire ce qui convient et de disposer d'une bibliothèque commune, car les gens devront alors communiquer beaucoup plus à propos de leur travail. Eh bien, ils devraient.
Michael Durrant

3
+1 - Je pense que cela vaut la peine de mentionner cette approche même si vous ne souhaitez pas l'utiliser très souvent. Certains extraits ressemblent davantage à des modèles de conception: vous les réutiliserez, mais un peu différemment partout, et peut-être dans différentes langues, et vous voudrez peut-être les modifier. En outre, une bibliothèque largement réutilisée est inflexible dans la mesure où les modifications apportées à son API sont très risquées. Enfin, avoir cette approche comme solution de secours augmente la qualité des bibliothèques partagées en leur laissant un peu plus longtemps le matériel expérimental.
Eamon Nerbonne le

6

La deuxième solution que vous décrivez n'est pas si mauvaise. Dans .NET, vous référencez également un assemblage à partir du GAC même si vous n'en utilisez qu'une seule classe. "Traîner du code non pertinent" n'est pas un problème comme vous pourriez le penser. Dans ce cas, il est essentiel de garder au moins les méthodes et les classes liées bien organisées dans différents espaces de noms. De plus, les bonnes pratiques de conception des API doivent être appliquées pour éviter que cette solution ne devienne un gâchis.

S'il s'agit de très petits morceaux de code, je pense que l'approche suivante complète bien un projet commun: autorisez leur duplication dans différentes solutions. Traitez-les comme des meilleures pratiques: documentez-les et communiquez-les à l'équipe.


1
Sauf que pour les bibliothèques non standard, cela signifie que vous devrez expédier un assemblage volumineux uniquement à cause d'une ou de plusieurs utilisations. Ce n’est pas un problème pour les produits standard, car ils sont disponibles de toute façon, mais j’éviterais certainement d’expédier des assemblages volumineux mais surtout inutilisés si vous pouviez les répartir correctement.
Poke

6

Je n'ai jamais travaillé que dans des environnements «d'entreprise» où ce genre de problème était un problème et chaque fois, c'était la deuxième option adoptée. La plupart du temps, tout a bien fonctionné, car l'encombrement des applications n'a pas été limité.

Cependant, après avoir passé la semaine dernière avec une start-up qui exécute son propre serveur Nuget, je suis enclin à suggérer cela comme une alternative viable. Bien entendu, les problèmes que je compte voir se poseront autour de la capacité de découverte.

Si les projets sont suffisamment détaillés et que les espaces de noms sont sensibles, je peux voir que cela devient une approche populaire par endroits.


Dans quel sens vous attendez-vous à ce qu'ils ne soient pas découvrables? De cette manière, nous utilisons un nombre important et croissant de paquets de nugets. Le plus gros problème que nous avons concerne la gestion des versions et des dépendances.
pdr

Ah oui. Ceux aussi. Par problèmes de capacité de découverte, je veux dire que, étant donné un nombre suffisant de petits paquets avec une fonction spécifique, il devient peut-être plus difficile de cataloguer (et de trouver) chacun. Par exemple, comment votre équipe sait-elle quels paquets contiennent différentes fonctions? (montrant l'ignorance de la recherche de nuget ici)
Kofi Sarfo

Oh je vois. Oui, vous pouvez certainement mettre ce que vous voulez dans la description et cela devient interrogeable, mais je pense que nous avons assez bien regroupé les paquets pour que cela ne semble pas poser de problème.
pdr

@sarfeast Ce serait bien si vous pouviez partager un lien vers le serveur Nuget et en parler un peu.
Hans-Peter Störr

6

J'ai récemment réfléchi à cette question et ce qui m'est apparu était une grande bibliothèque de méthodes communes, comme cela a été mentionné jusqu'à présent, mais avec une torsion. Le projet de bibliothèque vous permettrait de configurer au moment de la compilation les éléments inclus, comme le projet BusyBox . Avec cette approche, vous pouvez avoir un dépôt de bibliothèque de style évier de cuisine, mais ne saisir que les outils dont vous avez besoin lors de la compilation.


5

GitHub a un outil très utile pour enregistrer des extraits de code https://gist.github.com/

Il stocke vos extraits de code sous forme de référentiels git que vous pouvez garder confidentiels ou utiliser pour partager des extraits de code avec d'autres personnes.


3

En fonction de la taille de l'équipe / du projet / de l'entreprise, ce sera assez difficile à faire efficacement, à moins qu'il ne soit déjà intégré à votre environnement, et chaque solution que vous trouverez (si vous la mettez en œuvre) coûtera de l'argent. (Cela peut vous protéger davantage, mais vous ne pourrez pas mesurer facilement). Vous devrez vérifier si cela vaut le prix. N'oubliez pas non plus que les solutions réutilisables ont tendance à devenir abstraites et s'adaptent souvent à de nombreuses situations sans être optimales.

Dans tous les cas, si vous souhaitez utiliser ce code pour le code produit par plusieurs personnes, vous devez d’abord prendre conscience de l’intérêt de tous et de la coopération. Cela inclut les développeurs et les gestionnaires.

Ensuite, vous devez vous assurer de connaître la portée dans laquelle vous souhaitez le faire. Équipe? Projet? Département? Compagnie? En fonction de la réponse, le type de code que vous utiliserez dans ces solutions variera, de même que la granularité avec laquelle vous personnaliserez les dll. Une fois que vous avez décidé de le faire, quelqu'un (de préférence avec un certain enthousiasme pour l’idée - vous?) Devrait s’asseoir et commencer à mettre en place une structure.

La création de telles DLL ne suffira pas pour faire l'affaire. Afin de les rendre utiles, vous devez les publier (auprès des utilisateurs et des contributeurs) et les gérer comme tout autre logiciel, ce qui signifie généralement que vous devez leur confier la responsabilité à long terme. Vous aurez également besoin d'une documentation fiable, qui nécessitera également un entretien. Avec un peu de chance et de coopération, vous pourrez vous retrouver avec certaines meilleures pratiques, mais cela peut aussi facilement devenir un projet à part, en fonction de la taille et du nombre d’équipes impliquées. Et pour cela, vous aurez toujours besoin d'un support de gestion.


3

Je me suis souvent heurté à des problèmes, et ma solution préférée consiste à publier le code dans un référentiel Web github / pubic. cela résout beaucoup de problèmes -

  1. accès facile et facile à partager. cvs / svn / enterprise-repos signifie que le projet est archivé dans plusieurs espaces de travail IDE et qu'il est parfois nécessaire de changer d'espace de travail ou d'ordinateur simplement pour faire référence à un petit extrait de code.
  2. en supposant que ces extraits de code ne sont pas des éléments de code exclusifs / classifiés et constituent des variantes de la connaissance accessible au public, les afficher sur un dépôt public comme github signifie que d'autres personnes l'examineront et pourraient même y contribuer.
  3. publier quelque chose dans le domaine public sous votre nom a la pression supplémentaire de la réputation. vous allez vérifier et mettre à jour les choses, car cela reflète vos capacités en tant que programmeur.
  4. mises à jour. La chose à propos de la conservation des extraits de code dans un référentiel est que, si un extrait n'a pas été utilisé depuis longtemps, il pourrait devenir périmé (contenir des apis / libs obsolètes). exemple - extrait de code Java permettant de lire un fichier. vous avez peut-être trouvé le meilleur moyen de le faire en 2009, mais en 2014, une nouvelle api de fichier apparaît qui change tout. votre extrait? toujours bloqué en 2009. dans un rapport public, les choses seront mises à jour, soit par vous (parce que la puce 3), vos coéquipiers, ou un membre de la population des programmeurs généraux, et dans le processus, vous pourriez même recevoir des suggestions pour corriger quelque chose qui vous avez peut-être mal agi pendant longtemps.

Une chose que je recommanderais - peu importe où vous gardez vos extraits, recherchez toujours Google avant de l'utiliser. les choses changent tout le temps. Les extraits sauvegardés font gagner du temps, mais génèrent également de la complaisance .


2

Nous avons un projet séparé "utilitaires" dans lequel nous stockons toutes ces petites méthodes avec des tests.

Lorsqu'un projet a besoin d'un utilitaire, il ajoute simplement le fichier source avec la méthode requise avec "add as link".

Cela signifie qu'aucune dépendance d'exécution n'a été ajoutée (sauf si le fichier inclus en a besoin).

Le système a bien fonctionné mais, comme tous les autres, il a besoin de la précision sur ce qu’est un utilitaire. L'exigence d'une couverture de test élevée a bien fonctionné pour nous et les tests constituent également une bonne documentation d'utilisation. La découverte reste un problème non résolu pour nous.

Une complexité du projet de service public consiste à décider du niveau de visibilité des éléments. En règle générale, les méthodes doivent être internes et les structures de données publiques.


2

Ma société utilise des services Web intranet locaux. Nous avons quelques services Web configurés en tant que services Web internes communs, et lorsqu'un autre projet a besoin d'accéder à l'un des services, il envoie une requête http avec une interface définie. Comme il se trouve sur l'intranet, hébergé dans la même batterie de serveurs, ces demandes sont très rapides.

Évidemment, cela ne fonctionne qu'avec les applications Internet (et ne le fait qu'une fois par milliseconde sur le même réseau local), mais il présente de très bons avantages.


0

J'ai récemment eu ce service: Snip2Code ( http://www.snip2code.com ).

C'est un moyen intéressant de partager uniquement vos extraits (pas entièrement des bibliothèques) avec votre équipe. Créer une bibliothèque commune qui devrait être référencée dans d’autres projets est en rupture avec le point de vue habituel. À mon avis, cette vision est précieuse.

En outre, il existe de nombreux scénarios dans lesquels l'utilisation d'une bibliothèque commune ne s'applique tout simplement pas: considérons par exemple certains modèles de conception tels que Singleton, Strategy ou Observer. Vous pouvez créer des bibliothèques pour prendre en charge de tels modèles, mais il n’ya toujours pas de couverture à 100%.

Le vrai besoin est de disposer d'un outil pour partager les pratiques communes au sein de l'équipe. J'ai essayé d'utiliser les bases de Github, mais je suis coincé avec leur recherche (vraiment médiocre) et avec le fait que je ne peux pas les partager uniquement avec mon équipe et pas avec d'autres ...

(Avertissement: je suis l'un des fondateurs de Snip2Code et, avec mes co-fondateurs, j'étais dans votre état d'esprit il y a quelque temps: c'est pourquoi nous avons décidé de démarrer ce projet !!)

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.