소프트웨어-이야기/프로그래밍 언어와 프레임워크
[Rule Engine] 비즈니스 규칙 엔진
americano_people
2022. 6. 11. 10:02
비즈니스 규칙 엔진이란?
비즈니스 규칙 엔진이란, 어떤 조건에 따라 액션을 유발하는 규칙이 있는 비즈니스 기능을 구현할 때 사용하는 프로그램이다.
비즈니스 규칙 엔진의 요구사항은 크게 4가지로 나뉜다.
- 팩트 : 규칙이 확인할 수 있는 정보
- 액션 : 수행하려는 동작
- 조건 : 액션을 언제 발생시킬지 지정
- 규칙 : 실행하려는 비즈니스 규칙을 지정
- 보통 팩트/액션/조건을 한 그룹으로 묶어서 규칙으로 만든다.
비즈니스 규칙 엔진 구현 방법은 다음과 같다.
Diagram
Code
Class
@FunctionalInterface
public interface Action {
void execute(Facts facts);
}
@FunctionalInterface
public interface Condition {
boolean evaluate(Facts facts);
}
interface Rule {
void perform(Facts facts);
}
class DefaultRule implements Rule {
private final Condition condition;
private final Action action;
public DefaultRule(final Condition condition, final Action action) {
this.condition = condition;
this.action = action;
}
@Override
public void perform(Facts facts) {
if(condition.evaluate(facts)) {
action.execute(facts);
}
}
}
public class RuleBuilder {
private Condition condition;
private RuleBuilder(final Condition condition) {
this.condition = condition;
}
public static RuleBuilder when(final Condition condition) {
return new RuleBuilder(condition);
}
public Rule then(final Action action) {
return new DefaultRule(condition, action);
}
}
import java.util.HashMap;
import java.util.Map;
public class Facts {
private final Map<String, String> facts = new HashMap<>();
public String getFact(final String name) {
return this.facts.get(name);
}
public void addFact(final String name, final String value) {
this.facts.put(name, value);
}
}
import java.util.ArrayList;
import java.util.List;
public class BusinessRuleEngine {
private final List<Rule> rules;
private final Facts facts;
public BusinessRuleEngine(final Facts facts) {
this.rules = new ArrayList<>();
this.facts = facts;
}
public void addRule(final Rule rule) {
this.rules.add(rule);
}
public void run() {
this.rules.forEach(rule -> rule.perform(facts));
}
}
Client
final Rule ruleSendEmailToSalesWhenCEO = RuleBuilder
.when(facts -> "CEO".equals(facts.getFact("jobTitle")))
.then(facts -> {
var name = facts.getFact("name");
Mailer.sendEmail("sales@company.com", "Relevant customer: " + name);
});
final facts = new Facts();
facts.addFact("name", "김복세");
facts.addFact("jobTitle", "CEO");
final BusinessRuleEngine businessRuleEngine = new BusinessRuleEngine(facts);
businessRuleEngine.addRule(ruleSendEmailToSalesWhenCEO);
businessRuleEngine.run();
기반 지식
- @FunctionalInterface (함수형 인터페이스)
- 1 개의 추상 메소드를 갖는 인터페이스를 말한다.
- Fluent interface
- 메소드 체이닝을 지원하는 디자인 패턴
- 메소드 체이닝을 잘 사용한 예시 : 카카오페이의 결제 네트워크 에러 예외처리 코드
참고
실전 자바 소프트웨어 개발 5장. 비즈니스 규칙 엔진
https://github.com/sojeongw/real-world-software-development/tree/main/buisiness-rule-engine
-> API 응답을 처리하는 ActResult 클래스 예제가 Fluent API 인터페이스를 잘 구현한 예제로 보인다.
https://sabarada.tistory.com/72
classDiagram
DefaultRule ..|> Rule : Realization(실체화)
BusinessRuleEngine-->Rule: Association(연관)
BusinessRuleEngine-->Facts: Association(연관)
DefaultRule-->Condition: Association(연관)
DefaultRule-->Action: Association(연관)
Action..> Facts: ependency(의존)
Condition ..> Facts: Dependency(의존)
DefaultRule ..> Facts : Dependency(의존)
RuleBuilder-->Condition: Association(연관)
RuleBuilder..>Action: Association(연관)
class Rule{
+perform(Facts facts)
}
class Action{
+ execute(Facts facts)
}
class Condition{
+bool evaluate(Facts facts)
}
class RuleBuilder{
-Condition condition
+when(Condition condition)
+ Rule then(Action action)
}
class DefaultRule{
-Condition condition
-Action action
+perform(Facts facts)
}
class Facts{
-Map<String, String> facts
+String getFact(String name)
+addFact(String name, String value)
}
class BusinessRuleEngine{
- List<Rule> rules;
- Facts facts;
+addRule(Rule rule)
+run()
}