简体   繁体   English

是否有丰富的域模型示例?

[英]Is there a rich domain model example?

I'm looking for a simple example to illustrate the benefits of using a rich domain model. 我正在寻找一个简单的例子来说明使用丰富域模型的好处。 Ideally, I'd like a before and after code listing (which should be as short as possible). 理想情况下,我想要一个前后代码列表(应该尽可能短)。

The before code listing should show the problem being solved using an anemic domain model, and a lot of fairly procedural service-layer code, and the after code listing should show the same problem being solved using a rich, object-oriented domain model. 前面的代码清单应该显示使用贫血域模型解决的问题,以及许多相当程序化的服务层代码,后面的代码清单应该显示使用丰富的面向对象的域模型解决的相同问题。

Ideally the code listing should be in Java or Groovy, but anything fairly similar (eg C#) would do. 理想情况下,代码清单应该是Java或Groovy,但任何相似的东西(例如C#)都可以。

Perhaps this presentation by Jimmy Bogard contains what you ask for 也许Jimmy Bogard的这个演讲包含了你的要求

https://github.com/jbogard/presentations/tree/master/WickedDomainModels https://github.com/jbogard/presentations/tree/master/WickedDomainModels

I'll give you a simple example of real production code: 我将为您提供一个真实生产代码的简单示例:

Person.groovy: Person.groovy:

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

Membership.groovy: Membership.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
}

Whenever I want to bind a person to a group, I can just do person.addToGroup(group) 每当我想将一个人绑定到一个组时,我就可以做person.addToGroup(group)

The procedural code would be something like this, on your controller: 程序代码就像这样,在你的控制器上:

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

At first sight, you can say that you can wrap that in a function and you are good to go. 乍一看,你可以说你可以把它包装在一个函数中,你很高兴。 But the advantage of rich domain design IMHO is that it is closer with the way you think, thus closer to rationalize on. 但丰富的域名设计恕我直言的优势在于它与您的思维方式更接近,因此更接近合理化。 In this particular example, I just want to add a person to a group, and the code will read just that. 在这个特定的例子中,我只想将一个人添加到一个组中,代码将只读取它。

This is a short example like you asked, but it's easy to expand this example and see that you can build complex interactions with proper domain modeling. 这是一个简短的例子,就像你问的那样,但是很容易扩展这个例子,并且看到你可以通过适当的域建模来构建复杂的交互。

You can also see Martin Fowler's Transaction Script vs Domain Model for a brief explanation of these two patterns, which I consider related to DDD. 您还可以看到Martin Fowler的交易脚本域模型 ,以简要解释这两种模式,我认为这些模式与DDD有关。

I think that nobody have done that kind of comparison and if it had been, then it wouldn't be small. 我认为没有人做过这种比较,如果是的话,那就不会那么小了。 Domain Driven Design tries to solve complexity and a simple example doesn't contain complexity. Domain Driven Design试图解决复杂性,一个简单的例子不包含复杂性。

Maybe Domain Driven design Step by Step will give you some answers. 也许Domain Driven设计Step by Step会给你一些答案。

This doesn't exactly answer your question, but I see the opposite of domain-driven design as database-driven design. 这并不能完全回答您的问题,但我认为域驱动设计与数据库驱动设计相反。 In database-driven design, the database schema is created first, and then you create your classes with full knowledge of what the schema looks like. 在数据库驱动的设计中,首先创建数据库模式,然后在完全了解模式外观的情况下创建类。 The advantage is that you have a better understanding of what's going on 'under the hood', and minimize the effects of impedance mismatch. 优点是您可以更好地了解“引擎盖下”发生的情况,并最大限度地减少阻抗不匹配的影响。 However, the downside is that the database schema, because it's relational rather than object-oriented, doesn't translate very to objects (for example, there's no concept of a collection in relational databases). 但是,缺点是数据库模式,因为它是关系而不是面向对象,所以不能很好地转换为对象(例如,关系数据库中没有集合的概念)。

In domain-driven design, in theory you create your data objects just like you would any other class, and treat the database as simply a persistence layer. 在域驱动设计中,理论上您可以像创建任何其他类一样创建数据对象,并将数据库视为一个持久层。 In Layman's terms, the database is only a storage container and you don't care HOW the objects are stored, only that they are stored somehow. 在Layman的术语中,数据库只是一个存储容器,您不关心对象是如何存储的,只是它们以某种方式存储。 This eliminates the impedance mismatch and you have one less thing to worry about. 这消除了阻抗不匹配,您可以少担心一件事。 In practice, however, you still have to be aware of how the objects are stored, and there can be performance issues when the ORM you're using is trying to spit out a complex SQL query. 但是,实际上,您仍然需要了解对象的存储方式,并且当您使用的ORM尝试吐出复杂的SQL查询时,可能会出现性能问题。

Edit: 编辑:

Here's an example of what domain-driven design should be like, in principle. 这是一个原则上应该是域驱动设计的例子。 Let's say you have a Person class, like so (in C#): 假设你有一个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; }
}

Now, in a relational database, this will probably translate to 3 tables, a Person table, Address table, and Company table, with a bunch of relationships between them. 现在,在关系数据库中,这可能会转换为3个表,一个Person表,Address表和Company表,它们之间有很多关系。 However, this is vastly different than how the programmer sees this object. 但是,这与程序员看到此对象的方式大不相同。 The programmer sees it as an instance of a Person object with 4 parameters, one of which is a ICollection . 程序员将其视为具有4个参数的Person对象的实例,其中一个参数是ICollection This doesn't match up very well with the database table structure, hence the 'impedance mismatch', or in Laymen's terms, a difference in layout between the relational model and object model. 这与数据库表结构不匹配,因此“阻抗不匹配”,或者在Laymen的术语中,是关系模型和对象模型之间布局的差异。

In domain-driven design, I should be able to do this: 在域驱动设计中,我应该能够这样做:

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

Now, the person object is saved. 现在,人物对象被保存。 I can retrieve it like so: 我可以像这样检索它:

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

And it'll return my Person object, just like how it was before I saved it. 并且它将返回我的Person对象,就像我保存它之前的那样。 This way, I'm not concerned at all with how the databse is saving it, or worry about the impedance mismatch. 这样,我完全不关心数据库如何保存它,或者担心阻抗不匹配。 I simply save it and retrieve it as needed. 我只需保存它并根据需要检索它。

This is all in theory though. 这完全是理论上的。 In practice, you'll probably have to manually specify the 'mapping', or how the classes know which table/column in the database to get data from. 实际上,您可能必须手动指定“映射”,或者类如何知道数据库中的哪个表/列来从中获取数据。 It can get pretty complex when you're trying to map to more complex types such as dictionaries and other ADTs, and also when you're trying to pull data from multiple tables into one class. 当您尝试映射到更复杂的类型(如字典和其他ADT)时,以及当您尝试将数据从多个表中提取到一个类时,它会变得非常复杂。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM