Dalam hal ini, saya akan mengatakan jawaban yang ideal adalah bahwa itu tergantung pada bagaimana enum dikonsumsi, tetapi dalam sebagian besar keadaan mungkin yang terbaik untuk mendefinisikan semua enum secara terpisah, tetapi jika salah satu dari mereka sudah digabungkan dengan desain, Anda harus memberikan sarana untuk memperkenalkan enum yang digabungkan tersebut secara kolektif. Akibatnya, Anda memiliki toleransi kopling hingga jumlah kopling yang disengaja sudah ada, tetapi tidak lebih.
Mempertimbangkan hal ini, solusi yang paling fleksibel kemungkinan untuk mendefinisikan masing-masing enum dalam file yang terpisah, tetapi menyediakan paket yang digabungkan ketika masuk akal untuk melakukannya (sebagaimana ditentukan oleh penggunaan yang dimaksud dari enum yang terlibat).
Menentukan semua enumerasi Anda di file yang sama memasangkannya bersama-sama, dan dengan ekstensi menyebabkan kode apa pun yang bergantung pada satu atau lebih enum bergantung pada semua enum, terlepas dari apakah kode tersebut benar-benar menggunakan enum lain.
#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()
lebih suka hanya tahu tentang map_t
, karena jika tidak ada perubahan pada yang lain akan mempengaruhinya meskipun tidak benar-benar berinteraksi dengan yang lain.
#include "mapEnum.h" // Theoretical file defining map_t.
void renderMap(map_t, mapIndex);
Namun, dalam kasus di mana komponen sudah digabungkan bersama, menyediakan beberapa enum dalam satu paket dapat dengan mudah memberikan kejelasan dan kesederhanaan tambahan, asalkan ada alasan logis yang jelas untuk enum yang akan digabungkan, bahwa penggunaan enum tersebut juga digabungkan, dan bahwa menyediakannya juga tidak memperkenalkan sambungan tambahan.
#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);
Dalam hal ini, tidak ada koneksi logis langsung antara tipe entitas dan tipe material (dengan asumsi bahwa entitas tidak terbuat dari salah satu material yang ditentukan). Namun, jika kami memiliki kasus di mana, misalnya, satu enum secara eksplisit tergantung pada yang lain, maka masuk akal untuk menyediakan satu paket berisi semua enum yang digabungkan (serta komponen yang digabungkan lainnya), sehingga penggandengan dapat terisolasi ke paket itu sebanyak mungkin.
// 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()];
}
Tetapi sayang ... bahkan ketika dua enum secara intrinsik digabungkan bersama, bahkan jika itu sekuat "enum kedua menyediakan subkategori untuk enum pertama", mungkin masih ada waktu di mana hanya satu enum yang diperlukan.
#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;
}
Oleh karena itu, karena kita tahu keduanya bahwa selalu ada situasi di mana mendefinisikan beberapa enumerasi dalam satu file dapat menambahkan kopling yang tidak perlu, dan bahwa menyediakan enum yang digabungkan dalam satu paket dapat memperjelas penggunaan yang dimaksudkan dan memungkinkan kita untuk mengisolasi kode kopling yang sebenarnya itu sendiri sebagai Sebisa mungkin, solusi ideal adalah mendefinisikan setiap enumerasi secara terpisah, dan menyediakan paket bersama untuk enum yang dimaksudkan untuk sering digunakan bersama. Satu-satunya enum yang didefinisikan dalam file yang sama akan menjadi yang secara intrinsik terhubung bersama, sehingga penggunaan salah satu mengharuskan penggunaan yang lain juga.
// 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"