Fractionnement en fichiers - combien de fractionnement?

9

Si je dis que j'ai un cadre d'entité hiérarchique, plutôt qu'un modèle de composant. Quelque chose comme:
(Oui, c'est inventé)

Weapon-> Gun-> AutomaticGun-> MP44
Ou, plus d'un exemple classique:
Entity-> MovableEntity-> Enemy-> WalkingEnemy

Dans quelle mesure diviseriez-vous les fichiers source / en-tête pour la lisibilité et l'organisation? Est-il préférable d'aller quelque chose comme Entity.cpp, MovableEntity.cpp, Enemy.cpp, etc. ou une approche comme Entity.cpp [contenant Entity et MovableEntity] et Enemy.cpp [contenant Enemy et WalkingEnemy] serait-elle meilleure? (Ou d'une manière plus indépendante de la langue, un fichier ennemi et un fichier d'entité par rapport à un fichier pour chaque classe?)
De plus, cela affecterait-il autre chose que la lisibilité et l'organisation?

Le canard communiste
la source
1
Nitpicky, mais je ne pense pas que ce language-agnosticsoit une balise appropriée car cela dépend beaucoup de la langue que vous utilisez quant aux effets secondaires.
Tetrad
Bon point, je pense que je peux repenser.
The Communist Duck

Réponses:

12

C'est entièrement une question de préférence. Cependant, je pense personnellement qu'il vaut mieux se tromper du côté de plusieurs fichiers. Java nécessite une classe par fichier , avec le nom de fichier identique au nom de classe, par exemple; ils le font par politique pour appliquer cette bonne pratique (bien que vous puissiez avoir des sous-classes qui contournent essentiellement cela).

De plus, les systèmes de contrôle de source sont assez bons pour fusionner les modifications dans un fichier, mais c'est moins compliqué si vous travaillez uniquement dans des fichiers totalement séparés. Vous pouvez également voir plus facilement qui a changé de classe. Supposons qu'un autre développeur modifie le fichier AllEntities.h; vous n'avez aucune idée exactement de quelle entité (ou entités) il a changé jusqu'à ce que vous ouvriez le fichier et que vous regardiez la sortie diff.

C'est génial de regrouper les petites structures et énumérations liées à la classe dans le fichier d'une classe , cependant. Si vous avez une énumération qui n'est utilisée que par une seule classe, pourquoi la diviser en son propre fichier? Mettez-les ensemble. Mais s'il est utilisé par une autre classe (c'est-à-dire qu'un autre membre de la classe est du type de cette énumération), c'est alors qu'il est temps de lui donner son propre fichier.

Ricket
la source
D'accord. La complexité de vos types devrait certainement être un facteur. Si votre langage prend en charge les classes partielles (ou si les implémentations membres peuvent être organisées de manière similaire à C ++), je recommanderais même de diviser des types particulièrement complexes en plusieurs fichiers. Par exemple, s'il existe une (grande) interface que votre classe doit implémenter, mais que le code est assez générique et pas très pertinent pour le reste, vous pouvez décomposer ce code en un fichier séparé / classe partielle. Pour les types d'énumérations, je pense que vous pourriez vous en sortir en plaçant toutes les énumérations pour un espace de noms donné dans un seul fichier.
Mike Strobel
1
Le regroupement de vos énumérations ne signifie-t-il pas que la modification d'une seule valeur entraînerait une recompilation de chaque fichier qui utilise une énumération dans cet espace de noms?
The Communist Duck,
Eh bien, cela dépend vraiment de la langue, mais oui, cela pourrait certainement avoir cet effet. Ce n'est pas vraiment un problème pour moi, car je développe principalement en C # (pas de compilation fichier par fichier), mais cela pourrait être problématique en C ++ et dans d'autres langages. Comme toujours, il y a des facteurs spécifiques à la langue à considérer, et ce serait l'un d'entre eux :).
Mike Strobel
2

De nombreux langages en dehors de C / C ++ imposent des contraintes sur les fichiers. Ricket a mentionné «une classe par fichier» de Java; Python utilise des fichiers comme espaces de noms; d'autres langues copient souvent l'esprit de celles-ci.

Si vous utilisez C ou C ++, plus de fichiers inclus signifie généralement des temps de compilation plus longs par fichier; d'un autre côté, moins signifie plus à recompiler lors de petits changements. Étant donné que les énumérations ne peuvent pas être déclarées en aval en C, vous devez toujours les placer dans des fichiers d'en-tête contenant uniquement d'autres énumérations, pour des raisons de cohérence.

Sinon, "un fichier par classe" de Java est raisonnable, mais pendant longtemps Java a pris en charge les classes internes - comme un conteneur, et une classe interne de son itérateur. De même, dans toute autre langue, vous voudrez probablement un enregistrement / structure / classe / type / interface / blorb dominant par en-tête, mais vous pouvez également décider d'inclure des assistants ou des conteneurs associés.

(Vous n'avez pas besoin d'utiliser un modèle de composant, mais si vous avez une hiérarchie de classe approfondie et spécifique comme celle-là, vous allez vous détester plus tard.)


la source
J'utilisais la hiérarchie comme exemple; Je sentais que cela mettait l'accent sur ce que je voulais dire de mieux. Dans le code réel, je m'efforce vers les composants.
The Communist Duck