Я запропоную кілька пропозицій. Деякі з них суперечать один одному. Але, можливо, деякі корисні.
Розгляньте списки проти прапорів
Ви можете переглядати по всьому світу та перевіряти прапор на кожному елементі, щоб вирішити, чи робити прапор. Або ви можете зберегти список лише тих предметів, які повинні робити прапор.
Розгляньте списки та перерахування
Ви можете продовжувати додавати булеві поля до класу позицій, це ТАК і це. Або у вас може бути список рядків або елементів перерахунків, наприклад {"isAThis", "isAThat"} або {IS_A_THIS, IS_A_THAT}. Таким чином ви можете додавати нові в перерахунку (або рядкові строки) без додавання полів. Не те, що насправді щось не так з додаванням полів ...
Розглянемо функціональні покажчики
Замість списку прапорів або перерахунків може бути список дій, які потрібно виконати для цього елемента в різних контекстах. (Entity-ish…)
Розгляньте об’єкти
Деякі люди вважають за краще підходи, керовані даними, або сценарії, або компоненти компонентів. Але також варто врахувати старомодні ієрархії об'єктів. Базовий клас повинен прийняти такі дії, як "грати в цю карту для покрокової фази B" або будь-що інше. Тоді кожен тип карт може переосмислити та відповісти, якщо це доречно. Напевно, є також об’єкт гравця та ігровий об’єкт, тому гра може робити такі речі, як, якщо (player-> isAllowedToPlay ()) {do play ...}.
Розглянемо можливість налагодження
Колись приємна річ із купою полів прапора полягає в тому, що ви можете вивчити та роздрукувати стан кожного елемента однаково. Якщо стан представлений різними типами, або мішками компонентів, або покажчиками функцій, або перебуває в різних списках, можливо, недостатньо просто переглянути поля предмета. Це все компроміси.
Зрештою, рефакторинг: Розгляньте одиничні тести
Скільки б ви не узагальнили свою архітектуру, ви зможете уявити речі, які вона не охоплює. Тоді вам доведеться зробити рефактор. Може, небагато, може, багато.
Спосіб зробити це безпечнішим - це тест одиничних тестів. Таким чином, ви можете бути впевнені, що навіть якщо ви переставляли речі під ними (можливо, багато!), Існуюча функціональність все ще працює. Кожен блок тесту виглядає, як правило, так:
void test1()
{
Game game;
game.addThis();
game.setupThat(); // use primary or backdoor API to get game to known state
game.playCard(something something).
int x = game.getSomeInternalState;
assertEquals(“did it do what we wanted?”, x, 23); // fail if x isn’t 23
}
Як бачимо, для забезпечення стабільності цих викликів API вищого рівня щодо гри (або гравця, картки та ін.) Є ключовим у стратегії тестування одиниць.