Pourquoi développer des bibliothèques internes pour les applications internes?

10

J'ai du mal à comprendre pourquoi vous devriez développer des bibliothèques internes à utiliser exclusivement pour développer des applications internes. J'apprécie que si je veux utiliser un logiciel écrit par quelqu'un en dehors de l'organisation, il peut m'envoyer ses fichiers d'en-tête et ses fichiers .a ou .so et je peux simplement le lier à mon projet (en supposant qu'ils soient compilés dans le même environnement) .

Mais pourquoi une bibliothèque interne devrait-elle être développée uniquement pour être liée à une application interne lorsque j'ai accès à l'en-tête et aux fichiers d'implémentation et que je peux simplement les inclure dans mon arborescence source et les compiler tous ensemble?

En d'autres termes: si du code source est écrit, comment décidez-vous s'il doit être compilé dans une bibliothèque binaire et lié à votre application ou simplement inclus dans les fichiers source du projet et compilé régulièrement?

Quand je dis «inclure» des fichiers dans chaque projet, je ne veux pas copier et coller chaque fichier dans l'arborescence source du projet en cours de développement. Je veux dire développer un répertoire / bibliothèque (séparé de tout projet) contenant du code source commun qui peut être inclus dans les fichiers d'un projet de la manière habituelle, c'est-à-dire #include.

ps Je parle du développement c / c ++ ici pour plusieurs applications de bureau.

Andrew Murtagh
la source

Réponses:

25

Il existe de nombreuses raisons de créer des bibliothèques et des bibliothèques partagées (dans des fichiers .dll ou .so) même pour un usage interne:

  1. La réutilisation entre projets est beaucoup plus propre
  2. Séparation des responsabilités - une partie de votre code peut être plus adaptée aux différents développeurs ou équipes
  3. Vous pouvez bénéficier d'améliorations dans les bibliothèques que d'autres équipes font sans avoir à localiser le code spécifique
  4. Des temps de construction plus rapides, si la bibliothèque est stable, elle n'a pas besoin d'être reconstruite.
  5. Espace disque - vous pouvez avoir juste la bibliothèque et les en-têtes dans le projet
  6. Si vous utilisez des bibliothèques partagées, vous pouvez faire des économies de mémoire avec une seule copie chargée dans la RAM même si plusieurs programmes l'utilisent
  7. Vous vous retrouvez généralement avec une meilleure documentation et des tests des bibliothèques
  8. Conception et code plus propres - penser à structurer les choses en bibliothèques devrait entraîner des groupes de fonctionnalités associés dans chaque bibliothèque et vous avez tendance à séparer le code générique, dans les bibliothèques , des spécificités de l'application, dans l'application .
  9. Si vous avez des algorithmes propriétaires dans les bibliothèques, vous pouvez restreindre l'accès à la source, par exemple en ne permettant pas aux sous-traitants ou aux équipes externes d'accéder à la source.
  10. Le code de la bibliothèque peut être placé sous une licence différente de l'Application à laquelle il a été initialement écrit, certaines entreprises sont même connues des bibliothèques Open Source dont elles sont fières - gagnant des félicitations majeures dans la communauté Open Source et parfois d'importantes améliorations apportées retour.

Certaines entreprises ont même une pratique comptable où les projets qui créent des bibliothèques sont remboursés à chaque réutilisation.

Steve Barnes
la source
1
Ou dans une variante du point 9, vous pouvez libérer la bibliothèque sous une licence différente du code de l'application principale.
Michael Borgwardt
@MichaelBorgwardt - Bon point invitant le point 10 ci-dessus.
Steve Barnes
En outre, le fait d'avoir du code en tant que bibliothèque distincte permet d'éviter les raccourcis lors de la programmation, tels que "Je vais simplement ajouter ce paramètre supplémentaire ici .." et aide à trouver de meilleures façons d'implémenter les fonctionnalités requises.
Valdas
11

Quelques autres raisons possibles qui peuvent s'appliquer à des projets plus importants et non triviaux:

  • Temps de compilation: d' énormes projets monolithiques C ++ avec des milliers de fichiers, des milliers de classes, de fonctions, etc. peuvent prendre très longtemps à compiler (ce qui nuit à la productivité si vous souhaitez recompiler chaque fois que vous modifiez quelques lignes de code). Les bibliothèques liées statiquement et liées dynamiquement sont compilées indépendamment et n'ont pas besoin d'être recompilées si leur source n'a pas changé.

  • Séparation logique de modules ou sous-systèmes distincts : les grands systèmes sont généralement plus faciles à gérer si des domaines de fonctionnalité distincts sont placés dans des modules séparés, et les développeurs ne sont pas confrontés à la recherche dans d'énormes dossiers / projets contenant des milliers de fichiers / classes.

  • Limites entre les développeurs / équipes : les développeurs qui créent simultanément de nouvelles fonctionnalités distinctes peuvent réduire le risque de conflits de fusion s'il est possible que chaque développeur travaille dans des modules différents.

  • Code qui ne doit pas être publié dans un environnement en direct : par exemple, des bibliothèques de tests unitaires ou des bibliothèques `` fictives '' qui sont utilisées pour les tests des développeurs pour remplacer un composant du système en direct (matériel, API, systèmes distants, bases de données, etc.)

  • Drapeaux du compilateur : si vous vous trouvez dans une position très malheureuse d'intégration avec une API tierce qui attend un drapeau de compilateur étrange, la bibliothèque peut être une "couche de décontamination" située entre l'API tierce et le reste de l'application.

  • Fonctionnalités facultatives / optimisation : dans les grands systèmes, une application peut attendre avant de charger certains modules liés dynamiquement dans la mémoire au moment de l'exécution s'ils ne sont pas essentiels à la fonctionnalité de base de l'application.


En général, de nombreux projets internes sont souvent de petites micro-applications qui ne bénéficient pas d'être divisées en bibliothèques distinctes. Si vous travaillez sur un petit projet en tant que développeur seul, vous n'avez peut-être pas besoin de vous soucier de diviser votre code en bibliothèques (pour le moment ...). N'oubliez pas le principe YAGNI .

Ben Cottrell
la source
3
@downvoter - pourriez-vous expliquer la raison du vote négatif? Les commentaires sur les réponses sont utiles pour améliorer la qualité de ce site pour tout le monde.
Ben Cottrell
4

Votre question d'origine pourrait avoir causé un malentendu ici pour la plupart de ces autres réponses. Étant donné que vous n'avez pas l'intention de copier le code existant entre les projets, mais d'inclure les mêmes fichiers source de différents projets comme références , tout argument de "code en double" devient inutile, ainsi que de nombreux autres arguments présentés.

Notez que c'est parfois (- pas toujours -) une technique sensée . En fait, lorsque vous placez tous les fichiers source que vous souhaitez réutiliser dans plusieurs projets dans un dossier d'inclusion distinct, vous avez également créé une bibliothèque - une bibliothèque de code source, pas une bibliothèque binaire. Surtout en C ++, lors de la création de bibliothèques génériques avec des modèles, il n'est pas inhabituel d'avoir des bibliothèques uniquement en-tête, qui ont juste besoin d'une simple inclusion et d'aucune préparation de liaison séparée.

Donc, je suppose que votre vraie question est - quand construire des bibliothèques de code source, ou quand préférer des bibliothèques binaires précompilées? Dans cette ancienne réponse sur ce site , j'ai discuté de certains avantages et inconvénients des bibliothèques uniquement en-tête, peut-être que cela vous aide. Le principal avantage des bibliothèques de code source est qu'elles ne nécessitent pas d'être compilées avec les mêmes indicateurs de compilateur / éditeur de liens compatibles et d'exécution que l'application qui les utilise. Les inconvénients sont les temps de compilation supplémentaires et la nécessité de donner accès au code source (ce qui n'est évidemment pas un problème pour le type de projets "internes" que vous avez en tête).

Doc Brown
la source
Il est vrai que je voulais dire une bibliothèque de code source commune à plusieurs projets où vous faites simplement référence aux fichiers dont vous avez besoin via la directive #include typique - je ne connaissais pas le terme jusqu'à ce que vous le disiez et question maintenant. Votre réponse liée est également très utile.
Andrew Murtagh
@AndrewMurtagh: le fait que vous ayez accepté si rapidement la réponse de MichaelBorgwardt m'a étonné, car ce qu'il a écrit semble être une incompréhension de lui ou de la mienne.
Doc Brown
Eh bien, il a clarifié la confusion initiale que j'avais sur le moment de regrouper le code qui serait commun à plusieurs projets dans un seul package (que ce soit dans des bibliothèques binaires ou des bibliothèques de code source) mais d'accord, je parlais d'avoir un seul répertoire de source code qui pourrait être partagé entre les projets et ne pas copier et coller chaque fichier dans chaque projet car je pourrais en avoir besoin.
Andrew Murtagh du
2

Je suis d'accord avec les autres commentateurs lorsqu'ils écrivent que vous ne devez pas dupliquer de code. Dans votre cas, cependant, il semble que vous (ou les personnes avec lesquelles vous travaillez) créez des bibliothèques pour du code qui n'est pas dupliqué ailleurs.

Dans ce cas, je mets en garde contre une généralisation prématurée . Il y a souvent des moments où l'on sent qu'un morceau de code sera réutilisable. Cependant, sans connaître les détails intimes de la façon dont le deuxième cas d'utilisation utilisera un tel code, il est très facile de consacrer plus de temps aux fonctionnalités de «réutilisabilité» qui ne seront pas réellement utiles dans les cas supplémentaires ou de faire des hypothèses qui s'avèrent erronées dans le deuxième cas.

Écrire une "bibliothèque" pour un cas d'utilisation peut se transformer en un exercice très coûteux sans aucun gain --- j'ai été mordu par cela plusieurs fois.

Exemples de coûts:

  1. Temps / énergie consacré à l'examen des cas d'utilisation «généraux»
  2. Temps passé à rendre la "bibliothèque" distribuable à votre "client" (votre propre code)
  3. Pression future pour utiliser la "bibliothèque" même si elle ne correspond pas entièrement au prochain cas d'utilisation

Ma règle générale est la suivante: ne transformez pas le code en bibliothèque à moins d'avoir au moins 2 emplacements distincts où le code est nécessaire.

Sam
la source
2
J'ai vu presque exactement les mêmes raisons utilisées par certains développeurs que pourquoi leur code est tout dans un seul fichier source de ligne> 20k. Lorsqu'il est combiné avec une dénomination originale et des commentaires médiocres, vous obtenez rapidement un code qu'il est plus rapide de réécrire que de maintenir.
Steve Barnes
Grand point: je ne m'oppose certainement pas à l'écriture de code lisible et maintenable. Des fichiers séparés, des méthodes / classes bien nommées et la structure du package sont tous des composants importants de la maintenabilité. Mon point est juste que les coûts d'écriture + de distribution d'une bibliothèque sont élevés à supporter lorsqu'il n'y a qu'un seul cas d'utilisation pour la "bibliothèque".
Sam
1
Inversement, je ne prétends pas que vous devez nécessairement empaqueter et distribuer une bibliothèque dans tous les cas, juste que l'écriture et la structuration comme si votre code pourrait un jour devenir une bibliothèque vaut généralement un petit effort et paie souvent des dividendes même si le code ne devient jamais distribué sous forme de bibliothèque.
Steve Barnes
1

pourquoi une bibliothèque interne devrait-elle être développée uniquement pour être liée à une application interne lorsque j'ai accès aux fichiers d'en-tête et d'implémentation et que je peux simplement les inclure dans mon arborescence source et les compiler tous ensemble?

Parce que si vous les "incluez simplement dans mon arbre source", vous dupliquez du code .

Le problème avec cela est que vous ne bénéficierez d'aucune amélioration (y compris les corrections de bogues critiques) apportées par le projet à partir duquel vous avez copié le code, et ils ne bénéficieront pas des améliorations que vous apporterez.

Vous pourriez penser que vous pouvez résoudre ce problème en copiant simplement la dernière version du code dans votre arborescence source régulièrement, peut-être même automatisée en utilisant un sous-module dans git ou quelque chose de similaire. Mais alors, vous aurez constamment votre pause de construction en raison de modifications d'API incompatibles. Une bibliothèque, d'autre part, a une API publique "officielle" dont ses développeurs savent qu'elle ne peut pas être modifiée sans coodiner avec les clients.

Enfin, il peut y avoir des raisons techniques - pourrait-il être nécessaire de conserver une partie du code en tant que bibliothèque afin qu'il puisse être chargé en option ou même chargé et déchargé à la demande, et ainsi réduire l'utilisation de la mémoire lorsque la fonctionnalité n'est pas nécessaire?

Michael Borgwardt
la source
1
Donc, si je comprends bien, la principale raison de faire un morceau de code dans une bibliothèque est quand il va être utilisé dans différents projets (même s'ils sont tous développés en interne) afin que ce code ne soit pas dupliqué, mis à jour, maintenu séparément? Et si vous ne développez qu'un seul projet, il n'est pas nécessaire d'en faire quelque chose dans une bibliothèque (sauf si vous avez l'intention de l'utiliser dans d'autres projets à une date ultérieure).
Andrew Murtagh
@AndrewMurtagh: Oui, c'est à peu près exactement ce que je dirais. Bien qu'il puisse y avoir aussi des raisons techniques; Je ne connais pas très bien le développement C / C ++ - peut-être que conserver une partie du code en tant que bibliothèque est nécessaire pour qu'il puisse être chargé en option ou même chargé et déchargé à la demande, et ainsi réduire l'utilisation de la mémoire lorsque la fonctionnalité n'est pas nécessaire?
Michael Borgwardt
Je pense que cela peut être possible grâce aux bibliothèques partagées. Merci d'avoir clarifié, je marquerai votre réponse comme acceptée.
Andrew Murtagh
Presque tous les VCS de la dernière décennie prennent en charge des références externes ou des sous-modules. Cela a supprimé le code en double et le problème de correction de bogue. Pourrait inclure plus d'informations sur les raisons pour lesquelles celles-ci ne sont pas une solution viable si vous pensez toujours qu'il s'agit de problèmes valables
Sirisian
Pensez aussi à la maintenance. 1) La bibliothèque peut être maintenue indépendamment et en parallèle. 2) Le code est-il facile à remplacer. 3) Les petites bases de code sont plus faciles à gérer pour les petites équipes et plus faciles à comprendre pour tout le monde. 4) si le délai de mise sur le marché est critique, vous préférerez des versions plus rapides. Le code dans les bibliothèques est du code que vous ne compilez pas encore et encore dans le pipeline (IMO). 5) C'est un code réutilisable fiable ... Vous l'avez fait ;-)
Laiv
1

Je voudrais préciser les coûts de votre solution à long terme.

De toute évidence, l'ajout d'une bibliothèque à un projet a des frais généraux, tous si c'est le premier: les flux de travail doivent être modifiés, parfois même l'infrastructure et certains membres de l'équipe peuvent ne pas l'aimer (au début). Les avantages de votre solution sont donc évidents, car elle impose désormais des coûts moindres .

Cependant, au fur et à mesure que votre projet se développe, les coûts de la "pseudo-bibliothèque" le seront également. Supposons que vous ayez une "pseudo-bibliothèque" Autilisée par une application et un testeur d'unité. Chaque fois que vous ajoutez un cpp à A, vous devez l'ajouter aux deux projets, sinon ils ne seront pas liés.

Et si votre "pseudo-bibliothèque" est utilisée par une autre "pseudo-bibliothèque" B? Vous devez ajouter votre nouveau cpp dans un tas de projets de plus. Et si Bpasser à utiliser une autre bibliothèque? Vous devrez supprimer les cpps de Atous les projets en fonction uniquement de B.

Tout cela serait gratuit si une vraie bibliothèque était utilisée. La question est donc de savoir combien de cpp sont nécessaires pour justifier le passage à une véritable bibliothèque?

Mais attendez, il y a encore plus de garanties: un développeur n'aime pas ce stupide travail de chasse à tous les projets nécessitant le nouveau cpp et ajoutera son code / ses classes quelque part dans des fichiers déjà existants, ce qui n'est pas une bonne chose dans le long terme.

L'utilisation de la "pseudo-bibliothèque" peut donc être une première étape pour casser un projet monolithique, mais il ne faut pas attendre trop longtemps pour en faire une véritable bibliothèque pour pouvoir utiliser ses avantages.

ead
la source
0

Mais pourquoi une bibliothèque interne devrait-elle être développée uniquement pour être liée à une application interne lorsque j'ai accès à l'en-tête et aux fichiers d'implémentation et que je peux simplement les inclure dans mon arborescence source et les compiler tous ensemble?

Si la bibliothèque n'est utilisée que par une seule application, vous n'en aurez probablement pas besoin en tant que bibliothèque distincte.

Si la bibliothèque est utilisée par 3500 applications alors vous absolument faire besoin comme une bibliothèque séparée.

Et s'il y a un bogue dans la bibliothèque et que vous devez le corriger? Ou un changement statutaire ou réglementaire survient, ce qui signifie que vous devez changer le fonctionnement de la bibliothèque?

S'il se trouve dans une bibliothèque distincte, vous pouvez (potentiellement) corriger la bibliothèque, la tester à nouveau et la redéployer et chaque application bénéficie du correctif.

Si ce n'est que dans le code source qui est «local» pour chaque application, vous devez modifier, recréer, tester et redéployer chaque application individuellement . C'est un exercice beaucoup plus important (c'est-à-dire plus coûteux).

Phill W.
la source