views:

1127

answers:

3

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 (e.g. C#) would do.

A: 

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. 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.

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#):

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. 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. 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.

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. 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.

Daniel T.
I don't think this is an example of a rich domain model, because the domain you describe doesn't contain any behavior.
JasonTrue
A: 

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.

Maybe Domain Driven design Step by Step will give you some answers.

Marek Tihkan
+2  A: 

I'll give you a simple example of real production code:

Person.groovy:

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

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)

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.

Miguel Ping