11

我正在寻找一个简单的示例来说明使用富域模型的好处。理想情况下,我想要一个之前和之后的代码清单(应该尽可能短)。

之前的代码清单应该显示使用贫乏的领域模型解决的问题,以及许多相当程序化的服务层代码,而之后的代码清单应该显示使用丰富的面向对象的领域模型解决相同的问题。

理想情况下,代码清单应该用 Java 或 Groovy 编写,但任何类似的代码(例如 C#)都可以。

4

3 回答 3

3

我会给你一个真实生产代码的简单例子:

Person.groovy:

  List addToGroup(Group group) {
    Membership.link(this, group)
    return groups()
  }

会员资格.groovy:

 static Membership link(person, group) {
    def m = Membership.findByPersonAndGroup(person, group)
    if (!m) {
        m = new Membership()
        person?.addToMemberships(m)
        group?.addToMemberships(m)
        m.save()
    }
    return m
}

每当我想将一个人绑定到一个组时,我可以做person.addToGroup(group)

在您的控制器上,程序代码将是这样的:

def m = Membership.findByPersonAndGroup(person, group)
 if (!m) {
        m = new Membership()
        person?.addToMemberships(m)
        group?.addToMemberships(m)
        m.save()
}

乍一看,你可以说你可以把它包装在一个函数中,你就可以开始了。但是,恕我直言,富域设计的优势在于它更接近您的思维方式,因此更接近于合理化。在这个特定的示例中,我只想将一个人添加到一个组中,并且代码只会读取它。

就像您问的那样,这是一个简短的示例,但是扩展此示例很容易,并且您可以使用适当的域建模来构建复杂的交互。

您还可以查看 Martin Fowler 的Transaction Script vs Domain Model来简要解释这两种模式,我认为这与 DDD 有关。

于 2009-11-17T09:59:16.490 回答
2

我认为没有人做过这种比较,如果是这样,那就不会小了。领域驱动设计试图解决复杂性,一个简单的例子不包含复杂性。

也许Domain Driven design Step by Step会给你一些答案。

于 2009-11-02T22:30:17.720 回答
-5

这并不能完全回答您的问题,但我认为域驱动设计与数据库驱动设计相反。在数据库驱动设计中,首先创建数据库模式,然后在完全了解模式的情况下创建类。优点是您可以更好地了解“幕后”发生的事情,并将阻抗不匹配的影响降至最低。然而,缺点是数据库模式,因为它是关系的而不是面向对象的,不能很好地转换为对象(例如,关系数据库中没有集合的概念)。

在域驱动设计中,理论上您可以像创建任何其他类一样创建数据对象,并将数据库视为简单的持久层。用 Layman 的话来说,数据库只是一个存储容器,你不关心对象是如何存储的,只关心它们是以某种方式存储的。这消除了阻抗不匹配,您不必担心一件事。然而,在实践中,您仍然需要了解对象的存储方式,并且当您使用的 ORM 试图发出复杂的 SQL 查询时,可能会出现性能问题。

编辑:

原则上,这是一个领域驱动设计应该是什么样子的示例。假设您有一个 Person 类,就像这样(在 C# 中):

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Address Address { get; set; }
    public ICollection<Person> Relatives { get; set; }
    public Company Employer { get; set; }
}

现在,在关系数据库中,这可能会转换为 3 个表,一个 Person 表、一个 Address 表和一个 Company 表,它们之间有一堆关系。然而,这与程序员看待这个对象的方式大不相同。程序员将其视为具有 4 个参数的 Person 对象的实例,其中一个是ICollection. 这与数据库表结构不太匹配,因此“阻抗不匹配”,或者用外行的话来说,是关系模型和对象模型之间的布局差异。

在领域驱动设计中,我应该能够做到这一点:

Person person = new Person();
// set each property to something
Database.Save(person);

现在,person 对象被保存。我可以像这样检索它:

Person databasePerson = Database.Get<Person>(idOfPerson);

它会返回我的Person对象​​,就像我保存它之前一样。这样,我根本不关心数据库如何保存它,或者担心阻抗不匹配。我只是保存它并根据需要检索它。

不过,这都是理论上的。在实践中,您可能必须手动指定“映射”,或者类如何知道从数据库中的哪个表/列获取数据。当您尝试映射到更复杂的类型(例如字典和其他 ADT)以及尝试将多个表中的数据提取到一个类中时,它可能会变得非常复杂。

于 2009-11-02T22:12:21.283 回答