Per questo tipo di problemi Martin Fowler ha proposto Schema delle specifiche :
...design pattern, whereby business rules can be recombined by chaining the business rules together using boolean logic.
A specification pattern outlines a business rule that is combinable with other business rules. In this pattern, a unit of business logic inherits its functionality from the abstract aggregate Composite Specification class. The Composite Specification class has one function called IsSatisfiedBy that returns a boolean value. After instantiation, the specification is "chained" with other specifications, making new specifications easily maintainable, yet highly customizable business logic. Furthermore upon instantiation the business logic may, through method invocation or inversion of control, have its state altered in order to become a delegate of other classes such as a persistence repository...
Sopra sembra un po 'acuto (almeno per me), ma quando l'ho provato nel mio codice è andato abbastanza agevolmente e si è rivelato facile da implementare e leggere.
Per come la vedo io, l'idea principale è di "estrarre" il codice che esegue i controlli in metodi / oggetti dedicati.
Con il tuo esempio di netWorth
, questo potrebbe apparire come segue:
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;
}
Il tuo caso sembra piuttosto semplice, così tutti i controlli sembrano OK per rientrare in un elenco semplice in un unico metodo. Spesso devo dividere a più metodi per farlo leggere meglio.
Generalmente, inoltre, raggruppo / estrai i metodi correlati "spec" in un oggetto dedicato, anche se il tuo caso sembra OK senza quello.
// ...
Specification s, *spec = initialize(s, person);
if (spec->isSatisfied()) {
return person->assets - person->liabilities;
}
log("person doesn't satisfy spec");
return -1;
// ...
Questa domanda su Stack Overflow consiglia alcuni link oltre a uno sopra menzionato:
Esempio di modello di specifica . In particolare, le risposte suggeriscono Dimecasts "Apprendimento dello schema delle specifiche" per una procedura dettagliata di un esempio e menzioni "Specifiche tecniche" scritto da Eric Evans e Martin Fowler .