5

I'm still learning about DDD and I have these two (probably simple) questions:

If a Factory creates new object/graph/aggregate instances, but also "reconstitutes" objects/graphs from the Repository, then:

(1) Does your service layer functions/jobs/tasks/unit-of-work call into the Factory or a behavioural method on the Entity instance or a DomainService function? I'm lost as to the call stack based on the responsibility of these components.

(2) Do Entity instances even have "behavioural methods" like above? For example does a Post have p.UpdatePost(string bodyText) or is that not a concern of the domain model and so the same should be achieved with the Repository? Or the service layer function, should it be calling the Repository in this case and the entity instance simply have behavioural methods that are specific to the domain and not persistence? But then, why does it sound like "updating a post" is a domain function when that's the user's goal?

You can see I'm all over the place. Please help.

Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
Matt Kocaj
  • 11,278
  • 6
  • 51
  • 79
  • Am I [wrong in assuming](http://stackoverflow.com/questions/4196668/domain-driven-design-ddd-pitfalls/4200017#4200017) that a service layer (not Domain Services) should encapsulate how an interface interacts with the Domain Layer? – Matt Kocaj Nov 29 '10 at 04:41

1 Answers1

4

(1) Does your service layer functions/jobs/tasks/unit-of-work call into the Factory or a behavioral method on the Entity instance or a DomainService function? I'm lost as to the call stack based on the responsibility of these components.

Usually - top level retrieves necessary aggregate root and calls a function on it. Sometimes top level retrieves multiple aggregate roots and pass them to domain service, but not often because domain service is a quite strong sign that there is unrecognized aggregate root. At the end - top level ensures aggregate root is persisted.

(2) Do Entity instances even have "behavioural methods" like above? For example does a Post have p.UpdatePost(string bodyText) or is that not a concern of the domain model and so the same should be achieved with the Repository? Or the service layer function, should it be calling the Repository in this case and the entity instance simply have behavioural methods that are specific to the domain and not persistence? But then, why does it sound like "updating a post" is a domain function when that's the user's goal?

Yes, they do. Domain model should be aware of it's state changes. And that's much more beneficial as it seems at first. Great thing about this is that You gain extensibility point. If client will walk week later to You and say that he wants system to check additional things when user updates post - instead of searching every line of post.bodyText="new value", You will be able to go straight to post.UpdatePost method and attach necessary things there.

On the other hand - CRUD is not mutually exclusive with domain driven design. E.g. - in my application, management of users and their roles is uninteresting enough that I'm not even trying to model it granularly. You need to recognize parts what matters in business Your application is describing and working with.

Keep in mind that domain driven design makes sense for complex applications only. Simple blog application doesn't need it.

(3) Am I wrong in assuming that a service layer (not Domain Services) should encapsulate how an interface interacts with the Domain Layer?

As I see it - application services are more for orchestrating infrastructure. If there is no infrastructure involved - then application service loses value:

Application services basically are just facades. And every facade is bad if complexity it adds overweights problems it solves.


Inside domain:

//aggregate root is persistence ignorant. 
//it shouldn't reference repository directly
public class Customer{
  public string Name {get; private set;}
  public static Customer Register(string name){
    return new Customer(name);
  }
  protected Customer(string name){
    //here it's aware of state changes.
    //aggregate root changes it's own state
    //instead of having state changed from outside
    //through public properties
    this.Name=name;
  }
}

//domain model contains abstraction of persistence
public interface ICustomerRepository{
  void Save(Customer customer);
}

Outside of domain:

public class CustomerRepository:ICustomerRepository{
  //here we actually save state of customer into database/cloud/xml/whatever
  public void Save(Customer customer){
    //note that we do not change state of customer, we just persist it here
    _voodoo.StoreItSomehow(customer);
  }
}

//asp.net mvc controller
public class CustomerController{
  public CustomerController(ICustomerRepository repository){
    if (repository==null)throw new ArgumentNullException();
    _repository=repository;
  }
  public ActionResult Register(string name){
    var customer=Customer.Register(name);
    _repository.Save(customer);
  }
}
Community
  • 1
  • 1
Arnis Lapsa
  • 45,880
  • 29
  • 115
  • 195
  • While i agree with you that a blog application does not seem to warrant a DDD approach, i'm attempting to quantify the changes in my thinking by starting with a very abridged example. – Matt Kocaj Dec 02 '10 at 02:15
  • "top level retrieves"? I'm not sure what you mean by this? – Matt Kocaj Dec 02 '10 at 14:37
  • @cottsak in my application it's usually controller. sometimes application service. something that wants to spin business logic through aggregate root. – Arnis Lapsa Dec 02 '10 at 16:28
  • @Arnis Great, that's what i thought. Another query: "Domain model should be aware of it's state changes" - with this do you include persistence in the "state change"? I'm assuming you don't based on [other feedback i've received regarding this](http://stackoverflow.com/questions/4336819/persistence-encapsulated-via-the-domain-or-persistence-via-the-repository/4346704#4346704). – Matt Kocaj Dec 06 '10 at 01:16
  • @cottsak according to my understanding - domain model should contain abstraction of persistence that is implemented and used from outside. – Arnis Lapsa Dec 06 '10 at 12:34
  • I'm not sure if that's a yes or no? – Matt Kocaj Dec 08 '10 at 03:23
  • @cottsak added some code. maybe that helps to explain what I mean. – Arnis Lapsa Dec 08 '10 at 09:40