DDD在可配置规则驱动的系统中

时间:2012-09-11 13:32:08

标签: domain-driven-design rules

请原谅任何无知,我对DDD很新,所以要温柔。

我正在研究一个大型配置驱动的数据管理系统。通过在外部语法中指定配置(如业务规则,进程和验证)来构建系统。我们只是说语法是基于Groovy的DSL和Drools的集合体。

我喜欢DDD提供的简单性概念,特别是将基础架构问题与域的核心概念分开。

但是,由于系统的可配置性,我正在努力应用DDD的一些概念。行为(流程),验证和业务规则都是在系统外部定义的。因此,域中的实体本质上没有自己的行为。相反,它们对“验证器”或“规则引擎”或“工作流引擎”很敏感。

我将用一个例子来澄清。假设我的系统管理公司的员工。没有太多想法,您可以想象我的域中有员工实体和公司实体。

在DDD之后,我试图模拟一个员工晋升的场景。您可能会在Employee上看到一个名为promote(Employee.promote)的新方法。我们可以有一个业务规则,表明一个员工在同一年内不能被提升两次(是的,这一切都是弥补的)。因此,我可以有类似的东西:

public void promote( EmployeeLevel newLevel ) {
  if ( hasBeenPromotedThisYear( this ) {
    throw new InvalidPromotionException

好吧,在我正在使用此业务规则的应用程序中,将外部化为规则引擎。在DDD之后,我可以做类似的事情:

if( promotionRules.isEligibleForPromotion(this)

外化我的规则。但是,该系统比这更通用。 “促销”操作本身通过外部配置定义为“过程”。因此,在编译时,我甚至不知道我是否为该员工提供了“推广”操作。因此,从代码角度来看,我的员工对象变得非常简单,将所有功能委派给配置。它可能看起来像:

public class Employee {
  public void execute( Process process )

或者

public class EmployeeProcess {
  public void process( Employee employee )

我的问题是:DDD在这个应用程序中是否有意义?我是否应该在非DDD意义上模拟流程,验证,业务规则(规则引擎)的协作?

我喜欢洋葱架构,可以使用UI - >应用服务 - >核心 - >基础设施保持良好的关注点分离。但核心可能是上面提到的合作者,而不是真正的“领域概念”。

我的一部分认为,在这种情况下,“域概念”是验证器,处理器,业务规则,因为它们构成了我们在讨论系统时所讨论的无处不在的语言。在这种情况下,我会让实体没有真正的行为(大部分),以及处理器,验证器,规则引擎方面的域概念,以实现系统中的行为。

添加更多信息。鉴于我的上述问题,我正在努力寻找一个看似如下的解决方案:

org.example.app

org.example.domain - 员工 - 公司 - EmployeeLevel

org.example.domain.shared - 过程 - BusinessRule - 验证器

org.example.infrastructure

希望这个小片段增加一点清晰度。

因此,Process,BusinessRule和Validator概念将位于域内,但会根据系统所做的事情支持域模型。

2 个答案:

答案 0 :(得分:2)

来自维基百科:

  

域驱动设计(DDD)是一种开发软件的方法   通过将实施与不断发展的实施深度联系起来的复杂需求   核心业务概念的模型

我认为验证者,流程,规则不是您的核心业务概念。这些是相当常见的软件抽象。

我不是“乱七八糟”DDD的忠实粉丝,但为了更加“领域驱动”您的DSL,您的规则实际上应该围绕您的业务概念构建,以便更好地理解它。

在幕后,您仍然可以使用验证器,流程,管理器,执行器等,但如果您使用其中的业务概念而不是软件抽象,则您的DSL /规则将更具可读性。

更新:由于您使用Groovy来定义DSL,因此您可以使用Groovy的动态方法名称解析和构建器功能来创建可读的规则和类。您还可以利用“约定优于配置”原则来勾选某些逻辑。例如,在Groovy中,您可以尝试构造类似于:

的内容
if (employee is "promotable") {
  start "promotion" for employee
}

is将是一个基础域对象上的方法,它将检查是否存在让我们说EmployeePromotableValidator类,它本身也可以是一个利用Groovy的DSL表现力的Groovy类。

class EmployeePromotableValidator extends Validator<Employee> {

  boolean validate(Employee employee) {
    employee.age > 25 && employee.workingYears > 2
  }

}

start将是您的基本规则脚本上的一个方法,它将搜索EmployeePromotionProcess类,该类也可以是Groovy类。

在这种情况下,规范模式非常简单,因为它基本上成为语言的一部分:

if (employee is "promotable" && 
    employee is "advanced" && 
    employee.salary < 10000) {
  start( "salary increase", "10%" ) for employee
}

通常,借助Groovy / Scala等(半)函数语言的DSL可用于隐藏软件抽象,并使您的业务逻辑在代码中更加突出。使用普通Java,你最终会得到很多锅炉板代码,最终会隐藏你的所有意图。

答案 1 :(得分:1)

这取决于您的业务领域究竟是什么。

如果你正在构建一个额外的可配置crm,那么构造函数可以做所有应用程序 - 那么你的业务领域就是可以实现这一点,因此ProcessExecutors等名词是你域的一部分。

如果您正在构建应该跟踪员工信息及其可推广性的应用程序 - 那么您的业务领域就是员工,薪水,绩效评估。在这种情况下,请将ProcessExecutors和类似对象视为您域中的入侵者。

在某种程度上 - 甚至编程语言本身也是一种侵入性工具,可以模糊您在脑海中绘制的问题解决方案。但这是必要的 - 否则你将无法实现它。