Question

Mon collègue affirme que nous devrions disséquer notre application C ++ (C ++, Linux) dans des bibliothèques partagées pour améliorer la modularité, la testabilité et la réutilisation du code.

De mon point de vue, c’est un fardeau, car le code que nous écrivons n’a pas besoin d’être partagé entre les applications de la même machine pour être chargé ou déchargé dynamiquement et nous pouvons simplement lier une application exécutable monolithique.

De plus, encapsuler les classes C ++ avec des interfaces de fonction C à mon humble avis le rend encore plus laid.

Je pense également qu'il sera beaucoup plus facile de mettre à niveau une application à fichier unique sur le site d'un client.

Les bibliothèques dynamiques doivent-elles être utilisées lorsqu'il n'est pas nécessaire de partager du code binaire entre les applications ni de charger du code dynamique?

Était-ce utile?

La solution

Je dirais que diviser le code en bibliothèques partagées pour améliorer sans objectif immédiat est un signe d'un environnement de développement infesté de mots à la mode. Il est préférable d’écrire du code qui peut être facilement divisé à un moment donné.

Mais pourquoi devriez-vous envelopper les classes C ++ dans des interfaces de fonctions C, à l'exception peut-être de la création d'objets?

De plus, la division en bibliothèques partagées here ressemble à un état d'esprit interprété. Dans les langages compilés, vous essayez de ne pas reporter à l'exécution ce que vous pouvez faire au moment de la compilation. La liaison dynamique inutile est exactement le cas.

Autres conseils

L’application de bibliothèques partagées garantit que les bibliothèques n’ont pas de dépendances circulaires. L'utilisation de bibliothèques partagées entraîne souvent une liaison plus rapide et les erreurs de liaison sont découvertes plus tôt que s'il n'y avait pas de liaison avant que l'application finale ne soit liée. Si vous souhaitez éviter l'envoi de plusieurs fichiers aux clients, vous pouvez envisager de lier l'application de manière dynamique dans votre environnement de développement et de manière statique lors de la création de versions.

EDIT: Je ne vois pas vraiment pourquoi vous devez emballer vos classes C ++ à l'aide d'interfaces C - cela se fait en coulisse. Sous Linux, vous pouvez utiliser des bibliothèques partagées sans aucune manipulation particulière. Sous Windows, toutefois, vous aurez besoin de ___ declspec (exportation) et de ___ declspec (importation).

Améliorer la réutilisation même s’il n’y en aura pas? Cela ne semble pas être un argument puissant.

La modularité et la testabilité du code ne dépendent pas nécessairement de l'unité de déploiement ultime. Je pense que la liaison sera une décision tardive.

Si vous avez réellement un produit à livrer et que vous n’envisagez jamais de changement, cela ressemble à une surcharge excessive et à une complexité inutile.

Réponse courte: non.

Réponse plus longue: les bibliothèques dynamiques n’ajoutent rien à ajouter aux tests, à la modularité ou à la réutilisation qui ne se fait pas aussi facilement dans une application monolithique. Le seul avantage auquel je puisse penser est que cela peut forcer la création d'une API dans une équipe qui n'a pas la discipline pour le faire elle-même.

Il n’ya rien de magique dans une bibliothèque (dynamique ou autre). Si vous avez tout le code pour construire une application et les bibliothèques assorties, vous pouvez tout aussi facilement tout compiler dans un seul exécutable.

En général, nous avons constaté que les coûts liés au traitement de bibliothèques dynamiques ne valaient pas la peine, sauf en cas de nécessité impérieuse (bibliothèques de plusieurs applications, nécessitant de mettre à jour plusieurs applications sans recompiler, permettant à l'utilisateur de ajouter des fonctions à l'application).

Disséquer les arguments de votre collègue

S'il estime que le fractionnement de votre code en bibliothèques partagées améliorera la modularité, la testabilité et la réutilisation du code, il suppose alors que cela signifie que vous rencontrez des problèmes avec votre code et que l'application d'une "bibliothèque partagée". l'architecture le corrigera.

Modularité?

Votre code doit avoir des interdépendances non souhaitées qui ne se seraient pas produites avec une séparation plus nette entre " code de bibliothèque " et "code utilisant le code de la bibliothèque".

Maintenant, cela peut aussi être réalisé via des bibliothèques statiques.

Test?

Votre code pourrait être mieux testé, peut-être en construisant des tests unitaires pour chaque bibliothèque partagée distincte, automatisés à chaque compilation.

Maintenant, cela peut aussi être réalisé via des bibliothèques statiques.

Réutilisation du code?

Votre collègue souhaite réutiliser un code qui n'est pas exposé, car caché dans les sources de votre application monolithique.

Conclusion

Les points 1 et 2 peuvent toujours être atteints avec des bibliothèques statiques. Les 3 rendraient les bibliothèques partagées obligatoires.

Maintenant, si vous avez plus d’une profondeur de liaison de bibliothèque (je pense lier deux bibliothèques statiques qui ont déjà été compilées en reliant les autres bibliothèques), cela peut être complexe. Sous Windows, cela entraîne une erreur de liaison car certaines fonctions (généralement les fonctions d'exécution C / C ++, lorsqu'elles sont liées statiquement) sont référencées plusieurs fois, et le compilateur ne peut pas choisir la fonction à appeler. Je ne sais pas comment cela fonctionne sous Linux, mais je suppose que cela pourrait aussi arriver.

Dissection de vos propres arguments

Vos propres arguments sont quelque peu biaisés:

Charge de compilation / liaison de bibliothèques partagées?

Le fardeau de la compilation et de la liaison à des bibliothèques partagées, par rapport à la compilation et à la liaison à des bibliothèques statiques, est inexistant. Donc, cet argument n'a aucune valeur.

Chargement / déchargement dynamique?

Le chargement / déchargement dynamique d'une bibliothèque partagée peut poser problème dans un cas d'utilisation très limité. Dans des cas normaux, le système d’exploitation charge / décharge la bibliothèque si nécessaire sans votre intervention et, de toute façon, vos problèmes de performances sont ailleurs.

Exposer du code C ++ avec des interfaces C?

En ce qui concerne l'utilisation d'une interface de fonction C pour votre code C ++, je ne comprends pas: vous liez déjà des bibliothèques statiques à une interface C ++. Lier des bibliothèques partagées n’est pas différent.

Vous auriez un problème si vous aviez plusieurs compilateurs pour produire chaque bibliothèque de votre application, mais ce n'est pas le cas, car vous liez déjà vos bibliothèques de manière statique.

Un fichier binaire simple est plus facile?

Vous avez raison.

Sous Windows, la différence est négligeable, mais le problème de DLL Hell , qui disparaît si vous ajoutez la version à vos noms de bibliothèque ou si vous utilisez Windows & XP.

Sous Linux, en plus du problème Windows ci-dessus, vous avez le fait que, par défaut, les bibliothèques partagées doivent se trouver dans certains répertoires système par défaut pour pouvoir être utilisées. Vous devez donc les copier à l'installation (qui peut être pénible ...) ou modifier certains paramètres d’environnement par défaut (ce qui peut également être pénible ...)

Conclusion: qui a raison?

Votre problème n'est pas "mon collègue a-t-il raison?". Il est. Comme vous êtes aussi.

Votre problème est:

  1. Que voulez-vous vraiment accomplir?
  2. Le travail nécessaire à cette tâche en vaut-il la peine?

La première question est très importante, car il me semble que vos arguments et ceux de votre collègue sont biaisés pour aboutir à une conclusion qui semble plus naturelle pour chacun d'entre vous.

En d'autres termes: chacun de vous sait déjà quelle devrait être la solution idéale (selon chaque point de vue) et chacun d'entre vous empile des arguments pour atteindre cette solution.

Il n’ya aucun moyen de répondre à cette question cachée ...

^ _ ^

Faites une simple analyse coûts-avantages - avez-vous vraiment besoin de modularité, de testabilité et de réutilisation? Avez-vous le temps de refactoriser votre code pour obtenir ces fonctionnalités? Plus important encore, si vous effectuez une refactorisation, les avantages dont vous bénéficiez justifieront-ils le temps requis pour effectuer la refactorisation?

À moins que vous ne rencontriez des problèmes de test, je vous conseillerais de laisser votre application telle quelle. La modularisation est bonne mais Linux a sa propre version de " DLL hell " (voir ldconfig ) et vous avez déjà indiqué que la réutilisation n’était pas une nécessité.

Si vous posez la question et que la réponse n’est pas évidente, restez où vous êtes. Si vous n'êtes pas arrivé au point où la création d'une application monolithique prend trop de temps ou si vous avez du mal à travailler ensemble, alors il n'y a aucune raison impérieuse de passer aux bibliothèques. Vous pouvez créer un framework de test qui fonctionne sur les fichiers de l'application si vous le souhaitez tel quel ou vous pouvez simplement créer un autre projet utilisant les mêmes fichiers, mais associez une API de test et construisez une bibliothèque avec cela.

À des fins d'expédition, si vous souhaitez créer des bibliothèques et expédier un gros exécutable, vous pouvez toujours y accéder de manière statique.

Si la modularité peut vous aider pour le développement, c'est-à-dire que vous bousculez toujours les autres développeurs au sujet des modifications de fichiers, les bibliothèques peuvent aider, mais ce n'est pas une garantie non plus. Utiliser une bonne conception de code orientée objet aidera quand même.

Et il n'y a aucune raison d'envelopper des fonctions avec les interfaces appelables en C nécessaires à la création d'une bibliothèque, sauf si vous souhaitez que celle-ci soit appelable à partir de C.

Les bibliothèques partagées sont source de maux de tête, mais je pense que les bibliothèques partagées sont la bonne solution. Je dirais que dans la plupart des cas, vous devriez pouvoir rendre des parties de votre application modulaires et réutilisables ailleurs dans votre entreprise. En outre, en fonction de la taille de cet exécutable monolithique, il sera peut-être plus facile de simplement télécharger un ensemble de bibliothèques mises à jour au lieu d'un gros fichier.

IMO, les bibliothèques en général conduisent à un meilleur code, à un code plus testable et permettent de créer des projets futurs de manière plus efficace car vous ne réinventez pas la roue.

En bref, je suis d'accord avec votre collègue.

Sous Linux (et Windows), vous pouvez créer une bibliothèque partagée à l'aide de C ++ sans avoir à la charger à l'aide des exportations de fonctions C.

C’est-à-dire que vous construisez classA.cpp dans classA.so et que vous construisez classB.cpp dans classB (.exe) qui est lié à classA.so. Vous ne faites que diviser votre application en plusieurs fichiers binaires. Cela présente l'avantage qu'ils sont plus rapides à compiler, plus faciles à gérer et que vous pouvez écrire des applications qui chargent uniquement ce code de bibliothèque pour les tests.

Tout est toujours C ++, tout est lié, mais votre .so est distinct de votre application liée statiquement.

Maintenant, si vous voulez charger un objet différent au moment de l'exécution (vous ne savez pas lequel charger jusqu'à l'exécution), vous devrez créer un objet partagé avec les exportations C, mais vous devrez également charger ces fonctions manuellement; vous ne pourrez pas utiliser l'éditeur de liens pour le faire à votre place.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top