9

请原谅这里的任何无知,我对 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 意义上的流程、验证、业务规则(规则引擎)的协作进行建模?

我喜欢 Onion 架构,并且可以使用 UI -> App Services -> Core -> Infrastructure 来保持良好的关注点分离。但核心可能是上面提到的合作者,而不是真正的“领域概念”。

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

添加更多信息。鉴于我上面的问题,我正在努力寻找一个看起来像这样的解决方案:

org.example.app

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

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

org.example.infrastructure

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

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

4

2 回答 2

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,您最终会得到大量样板代码,这些代码最终会隐藏您的所有意图。

于 2012-09-12T08:18:39.023 回答
1

这取决于您的业务领域到底是什么。

如果您正在构建大型的额外可配置 crm 某些构造函数执行所有应用程序 - 那么您的业务领域就是使这成为可能,因此像 等这样的名词ProcessExecutors您领域的一部分。

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

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

于 2012-09-13T13:12:31.517 回答