In diesem Fall würde ich sagen, dass die ideale Antwort darin besteht, dass es davon abhängt, wie die Aufzählungen verbraucht werden. In den meisten Fällen ist es jedoch wahrscheinlich am besten, alle Aufzählungen separat zu definieren. Wenn jedoch eine der Aufzählungen bereits vom Design her gekoppelt ist, sollten Sie eine angeben Mittel zum gemeinsamen Einführen der gekoppelten Aufzählungen. Tatsächlich haben Sie eine Kopplungstoleranz bis zu dem Ausmaß der bereits vorhandenen absichtlichen Kopplung, jedoch nicht mehr.
In Anbetracht dessen ist es wahrscheinlich, dass die flexibelste Lösung wahrscheinlich jede Aufzählung in einer separaten Datei definiert, aber gekoppelte Pakete bereitstellt, wenn dies angemessen ist (wie durch die beabsichtigte Verwendung der beteiligten Aufzählungen bestimmt).
Alle Ihre Aufzählungen in der gleichen Datei Paare definieren sie zusammen, und durch die Erweiterung verursacht jeder Code, unabhängig davon , ob der Code tatsächlich auf allen Aufzählungen abhängig von einem oder mehreren Aufzählungen abhängig nutzt alle anderen Aufzählungen.
#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()
Ich würde viel lieber nur darüber Bescheid wissen map_t
, da sich sonst Änderungen an den anderen darauf auswirken, obwohl sie nicht wirklich mit den anderen interagieren.
#include "mapEnum.h" // Theoretical file defining map_t.
void renderMap(map_t, mapIndex);
In dem Fall, in dem Komponenten bereits miteinander gekoppelt sind, kann die Bereitstellung mehrerer Aufzählungen in einem einzigen Paket leicht zusätzliche Klarheit und Einfachheit bieten, vorausgesetzt, es gibt einen klaren logischen Grund für die Kopplung der Aufzählungen, und die Verwendung dieser Aufzählungen ist ebenfalls gekoppelt. und dass das Bereitstellen von ihnen auch keine zusätzlichen Kupplungen einführt.
#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);
In diesem Fall besteht keine direkte logische Verbindung zwischen Entitätstyp und Materialtyp (vorausgesetzt, die Entitäten bestehen nicht aus einem der definierten Materialien). Wenn wir jedoch einen Fall hatten, in dem beispielsweise eine Aufzählung explizit von der anderen abhängig ist, ist es sinnvoll, ein einzelnes Paket bereitzustellen, das alle gekoppelten Aufzählungen (sowie alle anderen gekoppelten Komponenten) enthält, damit die Kopplung erfolgen kann zu diesem Paket so weit wie möglich isoliert.
// 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()];
}
Aber leider ... selbst wenn zwei Aufzählungen eng miteinander verbunden sind, selbst wenn es so stark ist wie "zweite Aufzählung liefert Unterkategorien für erste Aufzählung", kann es immer noch zu einer Zeit kommen, in der nur eine der Aufzählungen erforderlich ist.
#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;
}
Da wir beide wissen, dass es immer Situationen geben kann, in denen das Definieren mehrerer Aufzählungen in einer einzelnen Datei zu unnötiger Kopplung führen kann und das Bereitstellen gekoppelter Aufzählungen in einem einzigen Paket die beabsichtigte Verwendung verdeutlichen und es uns ermöglichen kann, den tatsächlichen Kopplungscode selbst als zu isolieren Die ideale Lösung besteht darin, jede Aufzählung separat zu definieren und gemeinsame Pakete für alle Aufzählungen bereitzustellen, die häufig zusammen verwendet werden sollen. Die einzigen Aufzählungen, die in derselben Datei definiert sind, sind solche, die eng miteinander verbunden sind, sodass die Verwendung der einen auch die Verwendung der anderen erfordert.
// 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"