이러한 종류의 문제에 대해 Martin Fowler는 다음과 같이 사양 패턴을 제안했습니다 .
부울 논리를 사용하여 비즈니스 규칙을 연결하여 비즈니스 규칙을 다시 결합 할 수있는 디자인 패턴.
사양 패턴은 다른 비즈니스 규칙과 결합 할 수있는 비즈니스 규칙을 설명합니다. 이 패턴에서 비즈니스 단위 (UOW) 논리는 추상 집계 복합 스펙 클래스에서 해당 기능을 상속합니다. Composite Specification 클래스에는 부울 값을 반환하는 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;
}
모든 검사가 단일 방법 내에서 일반 목록에 적합하도록보기에 다소 단순 해 보입니다. 더 잘 읽을 수 있도록 더 많은 방법으로 분할해야하는 경우가 종종 있습니다.
또한 일반적으로 전용 객체에서 "spec"관련 메소드를 그룹화 / 추출하지만 케이스가 없으면 괜찮습니다.
// ...
Specification s, *spec = initialize(s, person);
if (spec->isSatisfied()) {
return person->assets - person->liabilities;
}
log("person doesn't satisfy spec");
return -1;
// ...
Stack Overflow의이 질문은 위에서 언급 한 것 외에도 몇 가지 링크를 권장합니다 :
Specification Pattern Example . 특히, 답변은 Dimecasts의 '사양 학습 패턴'에 대한 예제를 제공 하고 Eric Evans와 Martin Fowler가 작성한 "사양"문서를 언급 합니다.