78 votes

Plusieurs classes dans un fichier d'en-tête contre un seul fichier d'en-tête par classe

Quelle que soit la raison, notre société dispose d'un codage de directive qui prévoit que:

Each class shall have it's own header and implementation file.

Donc, si on écrit une classe appelée MyString , nous aurions besoin d'un associé MyStringh.h et MyString.cxx.

Quelqu'un d'autre le faire? Quelqu'un a vu toute la compilation de la performance des répercussions par la suite? N'5000 classes de 10000 fichiers compiler tout aussi rapidement que 5000 classes de 2500 fichiers? Si non, est la différence notable?

[Nous le code C++ et utiliser GCC 3.4.4 que le quotidien de notre compilateur]

83voto

James Devlin Points 6699

Le terme est ici unité de traduction et que vous voulez vraiment (si possible) avoir une classe par unité de traduction, c'est à dire, une implémentation de la classe par .fichier cpp, avec un correspondant .h fichier du même nom.

Il est souvent plus efficace (à partir d'une compilation/lien) point de vue à faire les choses de cette façon, surtout si vous êtes en train de faire des choses comme la liaison incrémentielle et ainsi de suite. L'idée étant, les unités de traduction sont isolés tels que, quand une unité de traduction changements, vous n'avez pas à reconstruire un tas de choses que vous auriez si vous avez commencé à regrouper de nombreuses abstractions en une seule unité de traduction.

Aussi, vous trouverez de nombreuses erreurs de diagnostic sont signalés par nom de fichier ("Erreur dans Myclass.cpp ligne 22") et ça aide si il y a une correspondance entre les fichiers et les classes. (Ou je suppose que vous pourriez appeler un 2 pour 1 correspondance).

72voto

paercebal Points 38526

Submergé par des milliers de lignes de code?

Avoir un jeu de tête/source des fichiers par catégorie dans un répertoire peut sembler exagéré. Et si le nombre de classes va vers les 100 ou 1000, il peut même être effrayant.

Mais après avoir joué avec des sources dans la philosophie "nous allons mettre ensemble tout", la conclusion est que seul celui qui a écrit le fichier a aucun espoir de ne pas être perdu à l'intérieur. Même avec un IDE, il est facile de manquer des choses parce que quand vous jouez avec une source de 20 000 lignes, vous venez de fermer votre esprit pour ce qui n'est pas exactement se référant à votre problème.

Exemple réel: la hiérarchie de classe définie dans ces milliers de lignes de sources refermé sur lui-même dans un diamant, de l'héritage, et certaines méthodes ont été redéfinies dans les classes enfant par des méthodes avec exactement le même code. Cela a été très facile de les oublier (qui veut explorer/check 20 000 lignes de code source?), et quand la méthode originale a été modifiée (correction de bug), l'effet n'était pas aussi universelle que l'exception.

Dépendances de devenir circulaire?

J'ai eu ce problème avec basé sur un modèle de code, mais j'ai vu des problèmes similaires avec des régulière, C++ et C du code.

Briser vos sources en 1 en-tête par struct/classe vous permet de:

  • Accélérer la compilation car vous pouvez utiliser le symbole de l'avant-déclaration à la place de, y compris l'ensemble des objets
  • Ont des dépendances circulaires entre les classes (§) (c'est à dire la classe A est un pointeur vers B, et B est un pointeur vers Une)

Dans sous contrôle de code source code, classe dépendances pourrait conduire à des déplacements réguliers de classes en haut et en bas du fichier, juste pour faire de l'en-tête de la compilation. Vous ne voulez pas d'étudier l'évolution de ces mouvements lorsque l'on compare le même fichier dans différentes versions.

La séparation des en-têtes rend le code plus modulaire, plus rapide à compiler, et facilite l'étude de son évolution à travers les différentes versions de diff

Pour mon modèle de programme, j'ai divisé mes en-têtes en deux fichiers: Le .PHP est un fichier contenant le modèle de déclaration de classe/de la définition et de la .INL fichier contenant les définitions des dit les méthodes de la classe.

Mettre tout ce code à l'intérieur d'un et un seul en-tête unique mettrait les définitions de classe au début de ce fichier, et la méthode définitions à la fin.

Et puis, si quelqu'un aurait besoin de seulement une petite partie du code, avec un en-tête de la seule solution, ils auraient à payer pour le ralentissement de la compilation.

(§) Notez que vous pouvez avoir des dépendances circulaires entre les classes si vous connaissez le nom de la classe qui possède. C'est une discussion sur les classes ayant connaissance de l'existence d'autres classes, pas shared_ptr dépendances circulaires antipattern.

Un dernier mot: les en-Têtes doivent être auto-sufficients

Une chose, cependant, qui doit être respectée par une solution de plusieurs en-têtes et de sources multiples.

Quand vous y ajoutez un en-tête, n'importe qui d'en-tête, votre source doit compiler proprement.

Chaque en-tête doit être auto-suffisante. Vous êtes censé développer le code, pas de trésor-la chasse par greping vos 10.000+ fichiers source du projet à trouver de qui en-tête définit le symbole de dans la de 1 000 lignes d'en-tête, vous devez inclure tout simplement parce que d' un enum.

Cela signifie que chaque en-tête définit ou de l'avant-déclarer tous les symboles qu'il utilise, ou inclure les en-têtes (et seulement les en-têtes).

12voto

Magnus Westin Points 658

Nous faisons cela au travail, il est simplement plus facile de trouver des choses si la classe et les fichiers ont le même nom. En ce qui concerne les performances, vous ne devriez vraiment pas avoir 5000 classes dans un seul projet. Si vous le faites, une refactorisation pourrait être appropriée.

Cela dit, il y a des cas où nous avons plusieurs classes dans un seul fichier. Et c'est à ce moment-là qu'il ne s'agit que d'une classe d'assistance privée pour la classe principale du fichier.

10voto

Chris Marasti-Georg Points 17023

+1 pour la séparation. Je viens d’arriver sur un projet où certaines classes sont dans des fichiers avec un nom différent, ou regroupées avec une autre classe, et il est impossible de les trouver rapidement et efficacement. Vous pouvez consacrer plus de ressources à une construction - vous ne pouvez pas rattraper le temps perdu par le programmeur car il (s) ne peut pas trouver le bon fichier à éditer.

9voto

Matt Dillard Points 9040

En plus d'être simplement "plus claire", la séparation des classes dans des fichiers séparés permet à plusieurs développeurs de ne pas se marcher sur les pieds. Il y aura moins de fusion au moment de valider les modifications apportées à votre outil de contrôle de version.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X