Domain driven design 使用DDD实现用户定义的业务规则
假设我有一个应用程序,让用户创建业务规则,应用于域实体。规则可以是一个条件和多个操作的组合,如果条件的计算结果为true,则执行相应的操作。此规则由用户以自由格式文本格式创建,然后转换为规则引擎可以理解和执行的专有格式 例如,对于员工管理系统,如果有业务规则来检查员工是否在当前职位工作超过一年,并且表现优于预期,则可以通过10%的加薪提升到下一个职位。用户可以按如下方式输入此业务规则Domain driven design 使用DDD实现用户定义的业务规则,domain-driven-design,rule-engine,ddd-repositories,ddd-service,Domain Driven Design,Rule Engine,Ddd Repositories,Ddd Service,假设我有一个应用程序,让用户创建业务规则,应用于域实体。规则可以是一个条件和多个操作的组合,如果条件的计算结果为true,则执行相应的操作。此规则由用户以自由格式文本格式创建,然后转换为规则引擎可以理解和执行的专有格式 例如,对于员工管理系统,如果有业务规则来检查员工是否在当前职位工作超过一年,并且表现优于预期,则可以通过10%的加薪提升到下一个职位。用户可以按如下方式输入此业务规则 public class Rule : Entity { public Condition Condit
public class Rule : Entity
{
public Condition Condition { get; private set; }
public IList<Action> Actions { get; private set;}
public Rule(Condition condition, IList<Action> actions)
{
Condition = condition;
Actions = actions;
}
}
public sealed class Condition : ValueObject<Condition>
{
public string ConditionText { get; private set;}
public ExecutableScript ExecutableCondition{ get; private set;}
public Condition(string conditionText)
{
ConditionText = conditionText;
}
public Parse()
{
ExecutableCondition = // How to parse using external rule engine ??;
}
public Execute()
{
// How to execute using external rule engine ??;
}
}
public sealed class Action : ValueObject<Action>
{
public string ActionText{ get; private set;}
public ExecutableScript ExecutableAction{ get; private set;}
public Action(string actionText)
{
ActionText = actionText;
}
public Parse()
{
ExecutableAction = // How to parse using external rule engine ??;
}
public Execute()
{
// How to execute using external rule engine ??;
}
}
条件:Employee.CurrentRoleLength>1和Employee.ExcepedExpections()操作:Employee.PromoteToNextRole()|Employee.GiveSalaryIncrement(10) 请注意,多个操作用|分隔。同样为了执行此规则,应用程序使用单独的规则引擎类库将此条件和两个操作解析为专有格式,例如,ExecutableScript也在规则引擎类库中定义 现在,为了使用DDD对该需求建模;我提出了以下域对象 规则(实体)
条件(值对象)
动作(值对象) 其中,Rule是一个实体,它包含一个条件值对象和一个操作值对象列表,如下所示
public class Rule : Entity
{
public Condition Condition { get; private set; }
public IList<Action> Actions { get; private set;}
public Rule(Condition condition, IList<Action> actions)
{
Condition = condition;
Actions = actions;
}
}
public sealed class Condition : ValueObject<Condition>
{
public string ConditionText { get; private set;}
public ExecutableScript ExecutableCondition{ get; private set;}
public Condition(string conditionText)
{
ConditionText = conditionText;
}
public Parse()
{
ExecutableCondition = // How to parse using external rule engine ??;
}
public Execute()
{
// How to execute using external rule engine ??;
}
}
public sealed class Action : ValueObject<Action>
{
public string ActionText{ get; private set;}
public ExecutableScript ExecutableAction{ get; private set;}
public Action(string actionText)
{
ActionText = actionText;
}
public Parse()
{
ExecutableAction = // How to parse using external rule engine ??;
}
public Execute()
{
// How to execute using external rule engine ??;
}
}
公共类规则:实体
{
公共条件条件{get;private set;}
公共IList操作{get;private set;}
公共规则(条件、IList操作)
{
条件=条件;
行动=行动;
}
}
公共密封类条件:ValueObject
{
公共字符串条件文本{get;private set;}
public ExecutableScript ExecutableCondition{get;private set;}
公共条件(字符串条件文本)
{
条件文本=条件文本;
}
公共解析()
{
ExecutableCondition=//如何使用外部规则引擎进行解析??;
}
公共执行()
{
//如何使用外部规则引擎执行??;
}
}
公共密封集体诉讼:ValueObject
{
公共字符串ActionText{get;private set;}
public ExecutableScript ExecutableAction{get;private set;}
公共操作(字符串actionText)
{
ActionText=ActionText;
}
公共解析()
{
ExecutableAction=//如何使用外部规则引擎进行解析??;
}
公共执行()
{
//如何使用外部规则引擎执行??;
}
}
基于上述领域模型,我有以下问题
Supervisor.reviewSubordinates(EvaluationService es) {
for ( Employee e : this.subbordinates ) {
// Note: state is an immutable value type; you can't
// change the employee entity by mutating the state.
Employee.State currentState = e.currentState;
Actions<Employee.State> actions = es.evaluate(currentState);
for (Action<Employee.State> a : actions ) {
currentState = a.apply(currentState);
}
// replacing the state of the entity does change the
// entity, but notice that the model didn't delegate that.
e.currentState = currentState;
}
}
Supervisor.reviews子坐标(评估服务){
适用于(员工e:此为下级){
//注意:state是不可变的值类型;不能
//通过更改状态来更改员工实体。
Employee.State currentState=e.currentState;
动作动作=评估(当前状态);
针对(行动a:行动){
currentState=a.apply(当前状态);
}
//替换实体的状态会更改
//实体,但请注意,模型并没有委托该实体。
e、 currentState=currentState;
}
}
技术领域可能受益于DDD战术模式,但创建正确抽象的成本通常高于其他领域,因为它通常需要抽象出复杂的数据结构
开始思考所需抽象的一个好方法是问问自己,如果要交换底层技术,需要哪些抽象
这里有一个复杂的基于文本的表达式,规则引擎根据该表达式创建了一个ExecutableScript
如果你想一想,这里有三个主要元素:
可执行脚本
;我假设这是一个带有嵌入式解释器的抽象语法树(AST)