Dans ce cas, je dirais que la réponse idéale est que cela dépend de la façon dont les énumérations sont consommées, mais que dans la plupart des cas, il est probablement préférable de définir toutes les énumérations séparément, mais si l'une d'entre elles est déjà couplée par conception, vous devez fournir un des moyens pour introduire collectivement lesdits énumérations couplées. En effet, vous avez une tolérance de couplage jusqu'à la quantité de couplage intentionnel déjà présente, mais pas plus.
Compte tenu de cela, la solution la plus flexible est susceptible de définir chaque énumération dans un fichier distinct, mais de fournir des packages couplés lorsque cela est raisonnable (tel que déterminé par l'utilisation prévue des énumérations impliquées).
La définition de toutes vos énumérations dans le même fichier les couple et, par extension, tout code qui dépend d'une ou plusieurs énumérations dépend de toutes les énumérations, que le code utilise réellement d'autres énumérations.
#include "enumList.h"
// Draw map texture. Requires map_t.
// Not responsible for rendering entities, so doesn't require other enums.
// Introduces two unnecessary couplings.
void renderMap(map_t, mapIndex);
renderMap()
préfère de beaucoup ne savoir que cela map_t
, car sinon tout changement apporté aux autres l'affectera même s'il n'interagit pas réellement avec les autres.
#include "mapEnum.h" // Theoretical file defining map_t.
void renderMap(map_t, mapIndex);
Cependant, dans le cas où les composants sont déjà couplés ensemble, fournir plusieurs énumérations dans un seul package peut facilement fournir une clarté et une simplicité supplémentaires, à condition qu'il y ait une raison logique claire pour les énumérations à coupler, que l'utilisation de ces énumérations est également couplée, et que leur fourniture n'introduit pas non plus de couplages supplémentaires.
#include "entityEnum.h" // Theoretical file defining entity_t.
#include "materialsEnum.h" // Theoretical file defining materials_t.
// Can entity break the specified material?
bool canBreakMaterial(entity_t, materials_t);
Dans ce cas, il n'y a pas de lien direct et logique entre le type d'entité et le type de matériau (en supposant que les entités ne sont pas constituées d'un des matériaux définis). Si, cependant, nous avions un cas où, par exemple, une énumération dépend explicitement de l'autre, alors il est logique de fournir un seul package contenant toutes les énumérations couplées (ainsi que tout autre composant couplé), de sorte que le couplage puisse être isolé de ce paquet autant qu'il est raisonnablement possible.
// File: "actionEnums.h"
enum action_t { ATTACK, DEFEND, SKILL, ITEM }; // Action type.
enum skill_t { DAMAGE, HEAL, BUFF, DEBUFF, INFLICT, NONE }; // Skill subtype.
// -----
#include "actionTypes.h" // Provides action_t & skill_t from "actionEnums.h", and class Action (which couples them).
#include "entityEnum.h" // Theoretical file defining entity_t.
// Assume ActFlags is or acts as a table of flags indicating what is and isn't allowable, based on entity_t and Action.
ImplementationDetail ActFlags;
// Indicate whether a given type of entity can perform the specified action type.
// Assume class Action provides members type() and subtype(), corresponding to action_t and skill_t respectively.
// Is only slightly aware of the coupling; knows type() and subtype() are coupled, but not how or why they're coupled.
bool canAct(entity_t e, const Action& act) {
return ActFlags[e][act.type()][act.subtype()];
}
Mais hélas ... même lorsque deux énumérations sont intrinsèquement couplées, même si c'est quelque chose d'aussi fort que "la deuxième énumération fournit des sous-catégories pour la première énumération", il peut arriver un moment où une seule énumération est nécessaire.
#include "actionEnums.h"
// Indicates whether a skill can be used from the menu screen, based on the skill's type.
// Isn't concerned with other action types, thus doesn't need to be coupled to them.
bool skillUsableOnMenu(skill_t);
// -----
// Or...
// -----
#include "actionEnums.h"
#include "gameModeEnum.h" // Defines enum gameMode_t, which includes MENU, CUTSCENE, FIELD, and BATTLE.
// Used to grey out blocked actions types, and render them unselectable.
// All actions are blocked in cutscene, or allowed in battle/on field.
// Skill and item usage is allowed in menu. Individual skills will be checked on attempted use.
// Isn't concerned with specific types of skills, only with broad categories.
bool actionBlockedByGameMode(gameMode_t mode, action_t act) {
if (mode == CUTSCENE) { return true; }
if (mode == MENU) { return (act == SKILL || act == ITEM); }
//assert(mode == BATTLE || mode == FIELD);
return false;
}
Par conséquent, puisque nous savons à la fois qu'il peut toujours y avoir des situations où la définition de plusieurs énumérations dans un seul fichier peut ajouter un couplage inutile, et que la fourniture d'énumérations couplées dans un seul package peut clarifier l'utilisation prévue et nous permettre d'isoler le code de couplage lui-même comme Dans la mesure du possible, la solution idéale consiste à définir chaque énumération séparément et à fournir des packages communs pour toutes les énumérations qui sont fréquemment utilisées ensemble. Les seules énumérations définies dans le même fichier seront celles qui sont intrinsèquement liées entre elles, de sorte que l'utilisation de l'une nécessite également l'utilisation de l'autre.
// File: "materialsEnum.h"
enum materials_t { WOOD, STONE, ETC };
// -----
// File: "entityEnum.h"
enum entity_t { PLAYER, MONSTER };
// -----
// File: "mapEnum.h"
enum map_t { 2D, 3D };
// -----
// File: "actionTypesEnum.h"
enum action_t { ATTACK, DEFEND, SKILL, ITEM };
// -----
// File: "skillTypesEnum.h"
enum skill_t { DAMAGE, HEAL, BUFF, DEBUFF, INFLICT, NONE };
// -----
// File: "actionEnums.h"
#include "actionTypesEnum.h"
#include "skillTypesEnum.h"