본문 바로가기

소프트웨어-이야기/프로그래밍 언어와 프레임워크

[Rule Engine] 비즈니스 규칙 엔진

비즈니스 규칙 엔진이란?

비즈니스 규칙 엔진이란, 어떤 조건에 따라 액션을 유발하는 규칙이 있는 비즈니스 기능을 구현할 때 사용하는 프로그램이다. 

비즈니스 규칙 엔진의 요구사항은 크게 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();

기반 지식

 

 

참고

실전 자바 소프트웨어 개발 5장. 비즈니스 규칙 엔진

https://github.com/sojeongw/real-world-software-development/tree/main/buisiness-rule-engine

https://tech.kakaopay.com/post/msa-transaction/#%EC%98%88%EC%99%B8%EB%A5%BC-%EC%9E%98-%EB%8B%A4%EB%A3%A8%EB%8A%94-%EB%B0%A9%EB%B2%95 

-> API 응답을 처리하는 ActResult 클래스 예제가 Fluent API 인터페이스를 잘 구현한 예제로 보인다. 

 

MSA 환경에서 네트워크 예외를 잘 다루는 방법 | 카카오페이 기술 블로그

결제시스템(페이상품권)에서 분산 트랜잭션을 보장하고 안전하게 다루기 위해 고민한 내용을 공유합니다.

tech.kakaopay.com

 

GitHub - sojeongw/real-world-software-development: 실전 자바 소프트웨어 개발

실전 자바 소프트웨어 개발. Contribute to sojeongw/real-world-software-development development by creating an account on GitHub.

github.com

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()
      }