この場合、理想的な答えは列挙型の消費方法に依存することですが、ほとんどの場合、すべての列挙型を個別に定義するのがおそらく最善ですが、それらのいずれかが既に設計によって結合されている場合は、提供する必要があります結合列挙をまとめて導入する手段。実際には、すでに存在する意図的なカップリングの量までのカップリング許容差がありますが、それ以上はありません。
このことを考慮すると、最も柔軟なソリューションは、別のファイルに各列挙型を定義し、する可能性があるが、(関与列挙型の使用目的によって決定される)それはそうするのが妥当だ時に結合されたパッケージを提供しています。
すべての列挙を同じファイルで定義すると、それらが結合され、拡張により、コードが実際に他の列挙を使用するかどうかに関係なく、1つ以上の列挙に依存するコードはすべての列挙に依存します。
#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()
むしろのみについて知っているだろうmap_t
他の人にそれ以外の変更は、それに影響を与えますので、それは他の人と実際に相互作用しないにもかかわらず、。
#include "mapEnum.h" // Theoretical file defining map_t.
void renderMap(map_t, mapIndex);
ただし、コンポーネントが既に一緒に結合されている場合、単一のパッケージで複数の列挙型を提供すると、列挙型が結合される明確な論理的理由があり、それらの列挙型の使用も結合されていれば、簡単に追加の明確さと単純さを提供できます、また、それらを提供しても追加のカップリングは導入されません。
#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);
この場合、エンティティタイプとマテリアルタイプの間に直接の論理的な接続はありません(エンティティが定義されたマテリアルのいずれかで作成されていないことを前提としています)。ただし、たとえば、1つの列挙が他の列挙に明示的に依存している場合、すべての結合列挙(および他の結合コンポーネント)を含む単一のパッケージを提供するのが理にかなっています。合理的に可能な限りそのパッケージに隔離されます。
// 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()];
}
しかし、悲しいかな... 2つの列挙型が本質的に一緒に結合されている場合でも、「2番目の列挙型が最初の列挙型のサブカテゴリを提供する」ほど強力な場合でも、1つだけの列挙型が必要な場合があります。
#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;
}
したがって、単一のファイルで複数の列挙を定義すると不必要な結合が追加される状況が常に存在する可能性があること、および単一のパッケージで結合列挙を提供することで意図する使用法を明確にし、実際の結合コード自体を分離できることの両方を知っているためできる限り、理想的な解決策は、各列挙を個別に定義し、頻繁に一緒に使用することを目的とする列挙に共同パッケージを提供することです。同じファイルで定義されている列挙型は、本質的に一緒にリンクされている列挙型のみであるため、一方を使用するには他方も使用する必要があります。
// 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"