Для таких питань Мартін Фаулер запропонував модель специфікації :
... модель дизайну, згідно з якою бізнес-правила можна рекомбінувати, з'єднавши бізнес-правила разом, використовуючи булеву логіку.
Шаблон специфікації окреслює ділове правило, сумісне з іншими правилами ведення бізнесу. У цій схемі одиниця бізнес-логіки успадковує свою функціональність від абстрактного сукупного класу Композитні специфікації. Клас складених специфікацій має одну функцію під назвою IsSatisfiedBy, яка повертає булеве значення. Після ідентифікації специфікація "прикута" до інших специфікацій, що робить нові технічні характеристики легко рентабельними, але при цьому легко налаштовує бізнес-логіку. Крім того, при створенні примірника бізнес-логіка може через виклик методу або інверсію контролю змінити свій стан, щоб стати делегатом інших класів, таких як постійне сховище ...
Вище звучить трохи високо-пришвидшено (принаймні, для мене), але коли я спробував це у своєму коді, він пройшов досить плавно і виявився простим у виконанні та читанні.
Як я це бачу, основна ідея полягає в тому, щоб "витягнути" код, який робить перевірки у виділених методах / об'єктах.
У вашому netWorth
прикладі це може виглядати так:
int netWorth(Person* person) {
if (isSatisfiedBySpec(person)) {
return person->assets - person->liabilities;
}
log("person doesn't satisfy spec");
return -1;
}
#define BOOLEAN int // assuming C here
BOOLEAN isSatisfiedBySpec(Person* person) {
return Person != NULL
&& person->isAlive
&& person->assets != -1
&& person->liabilities != -1;
}
Ваш випадок видається досить простим, тому всі чеки виглядають нормально, щоб увійти в звичайний список в рамках одного методу. Мені часто доводиться розбиватися на більше методів, щоб зробити його краще для читання.
Я також зазвичай групую / витягую "специфічні" методи, пов'язані з об'єктом, хоча ваш випадок виглядає нормально без цього.
// ...
Specification s, *spec = initialize(s, person);
if (spec->isSatisfied()) {
return person->assets - person->liabilities;
}
log("person doesn't satisfy spec");
return -1;
// ...
Це питання на переповнення стека рекомендує кілька посилань на додаток до одного згаданих вище:
Приклад шаблону специфікацій . Зокрема, відповіді пропонують Dimecasts "Вивчення шаблону специфікацій" для ознайомлення з прикладом і згадують документ "Технічні характеристики", автор автор Ерік Еванс та Мартін Фаулер .