Styles de codage lors de l'utilisation de plusieurs bibliothèques disparates

9

Je travaille sur du code C ++ qui utilise plusieurs bibliothèques, dont certaines bibliothèques C, qui ont toutes des styles de codage différents. Il sera open source une fois qu'il aura atteint un stade utilisable. Qu'est-ce qui causerait le moins de confusion à un contributeur à court terme qui vérifie le code pour corriger un bogue ou ajouter une fonctionnalité?

  • Avoir un style de codage cohérent dans toute l'application, même s'il ne correspond parfois pas au style de codage typique des bibliothèques utilisées.
  • Lorsqu'une bibliothèque est fortement utilisée dans un certain module, conformez-vous au style de codage typique de cette bibliothèque (c'est-à-dire le style de codage utilisé dans le code et la documentation de la bibliothèque) dans ce module.

Je pense que ce dernier permettra aux experts de cette bibliothèque particulière de faire des contributions uniques et facilitera l'incorporation de didacticiels / exemples de code pendant le développement. Cependant, cela rend également le style de codage incohérent dans l'application. Quels sont les avantages et les inconvénients de chaque approche?

Karl Bielefeldt
la source
4
Serait-il possible d'éviter ce problème en encapsulant toutes les bibliothèques dans vos propres abstractions personnalisées? Votre propre code et abstractions pourraient alors suivre un style de codage unique.
MetaFight
Une grande partie de ce que je fais résume ces bibliothèques. La question est de savoir quel style de codage utiliser à l'intérieur de l'abstraction.
Karl Bielefeldt
6
Ah. Je ne suis pas un expert ici, mais il semble que vous feriez mieux d'utiliser la convention de la bibliothèque elle-même. L'utilisation d'une convention inadaptée ressemble à un cauchemar de maintenance. Et tant que le style de la bibliothèque est contenu dans la classe / module qui l'abstrait, je suppose que ce serait OK. Encore une fois, je ne suis pas un pro ici, mais cela semble être un bon équilibre qui vous permet une maintenance plus facile dans vos abstractions et vous permet également d'avoir votre propre style dans le reste de l'application.
MetaFight
1
Parfois, des abstractions comme celle-ci peuvent devenir un peu laides, faites de votre mieux pour les garder propres quelles que soient les conventions utilisées, mais surtout assurez-vous simplement que l'API que vous présentez à partir de l'abstraction est de qualité suffisante pour que vous n'ayez pas besoin de revenir en arrière dans l'ingérence dans l'abstraction et les consommateurs seront en mesure de travailler facilement et de manière cohérente avec vos abstractions pour s'assurer que leur code ne devienne pas un gâchis comme ce qui peut être dans vos abstractions. Donc, en bref, il n'y a pas de bonne réponse, mais tant que vos abstractions présentent de bonnes API, au moins vous empêchez le problème de se propager.
Jimmy Hoffa
1
Qu'entendez-vous exactement par «style de codage» - des trucs simples comme using_underscores / camelCase / PascalCase et l'emplacement des accolades, ou des choses plus complexes comme la disposition des classes / méthodes / fonctions et le style impératif / fonctionnel?
Izkata

Réponses:

10

Je pense que cela dépend de la taille du projet dans son ensemble.

À un extrême, disons que vous avez un projet de 1 Mloc. Pour un projet aussi vaste, il est peu probable qu'une seule personne soit un "expert" dans tous les domaines concernés. Donc, dans ce cas, je m'en tiendrai aux styles de code existants pour chaque composant principal. Les nouveaux développeurs choisiront une zone, l'apprendront et il est peu probable qu'ils voient de nombreux autres composants qui peuvent avoir des styles de code différents.

Si le projet est beaucoup plus petit, où il est probable que les individus comprennent l'intégralité de la base de code, je choisirais un style de code dominant et je m'en tiendrai à cela. Dans ce cas, je pense que la cohérence dans l'ensemble du projet est plus logique, car les nouveaux développeurs seront susceptibles de travailler dans tous les domaines du projet.

Les projets de taille moyenne sont peut-être les plus difficiles à prendre pour cette décision. Dans ce cas, vous devez peser les coûts de chaque approche et décider de celle qui, selon vous, sera la moins chère à long terme. Le défi est que les projets de taille moyenne se sont généralement développés juste assez pour qu'un refactoring de style complet semble prohibitif. Vous voudrez peut-être jeter un deuxième coup d'œil à la structure de l'arborescence de code pour voir si les choses peuvent être organisées pour regrouper des styles de code particuliers.

Quoi qu'il en soit, la décision finale devrait appartenir à l'équipe sur laquelle vous composez ce package.


Certaines des valeurs aberrantes qui pourraient déplacer mon raisonnement d'en haut:

  • Si un ou plusieurs des modules ont un style atroce, alors cela n'a aucun sens de le garder, même sur un projet plus important. Oui, le style est subjectif, mais si vous et vos collègues participants au projet n'aimez vraiment, vraiment pas la façon dont les zones particulières coulent, nuquez l'ancien style et donnez-lui un meilleur.

  • Si tous les styles sont raisonnablement proches les uns des autres, il pourrait être tout aussi facile de déclarer «voici la nouvelle façon» et de l'utiliser pour tout nouveau code et refactorisations importantes. Cela peut rendre les critiques un peu pénibles, mais d'après mon expérience, la plupart des gens sont assez capables de s'adapter à cette approche. Il fournit également un signe révélateur de l'emplacement de l'ancien code.

  • Parfois, le style est modifié en fonction de nouvelles fonctionnalités ajoutées au langage. C ++ a repris un certain nombre de fonctionnalités au fil des ans. Il peut être judicieux de refactoriser au besoin l'ancien style en un style plus récent qui tire parti de ces fonctionnalités.

  • Certaines bibliothèques peuvent avoir une approche ou un style particulièrement idiomatique. Si c'est le cas, je m'en tiendrai à ce style pour cette bibliothèque même s'il peut entrer en conflit avec le reste du projet. L'intention ici est d'augmenter les chances qu'une personne qui travaille sur frobnosticatorsd'autres projets travaille également sur votre projet.


Certains commentaires ont mentionné les styles impératifs et orientés objet comme étant une considération.

Les modules qui sont "lourds" dans un style particulier devraient probablement le rester si le module est de taille moyenne ou plus grande. J'ai travaillé avec les trois styles principaux (impératif, objectif et fonctionnel), et j'ai refactorisé les styles impératifs lourds en un style OO. Avec une quantité de code moyenne ou supérieure, la refactorisation peut être (exceptionnellement) difficile. Mon expérience a été confondue car je n'avais aucun support d'outillage pour aider au refactoring.

J'imagine qu'il existe une forte corrélation entre les modules de style fortement impératif et ces modules étant idiomatiques pour des niches de développement particulières, ce qui remonte au dernier point que j'ai soulevé avec les valeurs aberrantes. Donc, tout module que vous trouverez pour cette fonctionnalité ressemblera à cela, et vous voulez que les experts de ce domaine puissent également travailler facilement sur votre projet. Mais s'il y a des options et que votre équipe n'aime pas le style de ce module, alors j'examinerais les options.

De même, j'ai travaillé avec un module de style OO lourd où les principes OO ont été poussés trop loin et mal utilisés. Par exemple, les interfaces étaient utilisées comme substitut à l'héritage multiple. Et comme vous vous en doutez, c'était une implémentation grossière. J'ai pu faire des progrès raisonnables dans la refonte de ce module, mais j'ai finalement abandonné cette approche car j'ai trouvé de meilleurs packages à utiliser à la place.


la source
C'est une bonne façon de le dire. Des projets similaires sont d'environ 300 KLOC.
Karl Bielefeldt
3

On dirait qu'il y a plusieurs couches à considérer, au moins:

  1. Les bibliothèques existantes et leurs modifications.
  2. Nouveau code de test unitaire pour ces bibliothèques.
  3. La couche d'abstraction.
  4. L'API présentée par la couche d'abstraction.
  5. Exemple et test de code à l'aide de la couche d'abstraction.

Je vais supposer que cela n'a pas de sens de simplement refactoriser tout le code dans un style commun à l'avance - si c'était le cas, vous n'auriez pas posé la question.

À tour de rôle:

  1. Pour la base de code existante, vous voudrez probablement vous en tenir à ce style.
  2. Le nouveau code de test unitaire pour le code existant se trouve dans une zone grise, en particulier en fonction de son intégration avec l'ancien code. Mais très probablement, j'essaierais de le faire dans le «style préféré».
  3. Le nouveau code dans la couche d'abstraction. En s'assurant qu'il s'agit bien d'une couche de code distincte, il ne devrait pas y avoir de difficulté à utiliser un style préféré même si le code fait beaucoup d'interfaçage avec un ou des styles hérités. La plupart du code doit s'interfacer avec d'autres styles, et je n'ai jamais trouvé cela un problème.
  4. De toute évidence, l'API elle-même a besoin de plus de réflexion et répond aux besoins d'utilisation maximale.
  5. Tout exemple ou code de test doit également pouvoir être écrit dans le style préféré. Selon l'exhaustivité de l'abstraction (c'est-à-dire si elle cache complètement les couches inférieures), cela peut être facile ou difficile. Bien sûr, vous assurer que le futur code client est lisible sera l'un de vos principaux objectifs.

Certaines choses que j'ai trouvées personnellement, c'est qu'avec une grande base de code héritée:

  • Définir un style préféré et appliquer les modifications de code ne fait pas comme par magie la migration de l'ancien code vers le nouveau style.

  • La plupart des ingénieurs ont tendance à aimer coder (plus ou moins) le style existant dans une bibliothèque donnée. Exiger autrement entraîne une grande application.

  • Exiger un style préféré dans une bibliothèque héritée a tendance à entraîner beaucoup d'incohérence dans le style de cette bibliothèque. Donc, pour les normes qui sont purement autour de la présentation, par opposition à la robustesse du code, il est difficile de voir aussi beaucoup d'avantages à les exiger.

Comme dernier problème (légèrement hors sujet, mais je pense que c'est pertinent), la vérité est que certains ingénieurs ont du mal à respecter n'importe quelle norme de style autre que celle qu'ils connaissent le mieux. Je recommande fortement d'engager l'équipe dans les décisions de style et de s'assurer qu'il y a adhésion. Cela fait, vous êtes bien mieux placé pour appliquer réellement une norme en code mixte.

Keith
la source
0

Je serai d'accord avec @MetaFight ici au cas où vous développez un projet de grande taille avec beaucoup de modules tiers.

Permet de cartographier votre problème avec un vrai problème de mots: " Supposons que vous ayez un style de vie calme dans votre maison. Vous aimez que votre endroit soit calme, vous ne parlez jamais plus fort et n'aimez jamais aucun membre de votre famille à le faire. Mais vous interagissez avec beaucoup de différentes personnes à l'extérieur tous les jours pour apporter quelque chose pour votre maison. Pas nécessairement, elles parleront également à voix basse, dans ce cas, vous vous façonnerez en conséquence tout en traitant avec de telles personnes. Ainsi, l'interface ou le wrapper pour ces personnes est très flexible juste pour le plaisir de votre travail à faire. "Exemple stupide ... lol

Mais mon point est de créer un wrapper pour ces bibliothèques selon leur norme de codage de telle manière que vous utilisez ces bibliothèques à travers ces wrappers en conservant votre style de codage d'origine à l'intérieur.

+1 pour MetaFight.

theinsaneone
la source
Exactement la bonne solution imo. J'utilise des wrappers pour attacher du code que d'autres personnes écrivent également pour mes projets. Définissez une interface à l'avance, puis quand ils l'implémentent, vous pouvez l'envelopper et la tester en boîte noire.
Kieveli
1
Pourquoi ce vote est-il rejeté? Je pense clairement que c'est la meilleure solution :)
MetaFight
0

Cela provoquerait clairement le moins de confusion possible en utilisant un seul style de codage tout au long de votre projet. L'intérêt même d'utiliser un style de codage en premier lieu est de faciliter la lecture et la modification du code.

Quant au style de code utilisé en interne dans une bibliothèque, je ne pense pas qu'il soit pertinent. Si la bibliothèque est trop impérative, l'écriture d'un wrapper OO est très bien, mais cela ne nécessite pas que vous utilisiez le même style de code que dans les exemples ou les internes de la bibliothèque.

Gustav Bertram
la source