Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

After dealing with DDD for months now, I'm still confused about the general purposes of domain services, factories and aggregate roots in relation to each other, e.g. where they overlap in their responsibility.

Example: I need to 1) create a complex domain entity in a saga (process manager) which is followed by 2) a certain domain event that needs to be handled elsewhere whereas 3) the entity is clearly an aggregate root that marks a bounded context to some other entities.

  1. The factory IS be responsible for creation of the entity/aggregate root
  2. The service CAN create the entity, since he also throws the domain event
  3. The service CAN act as a aggregate root (create 'subentity' of 'entity' with ID 4)
  4. The aggregate root can create and manage 'subentities'

When I introduce the concept of a aggregate root as well as a factory to my domain, a service seems no longer needed. However, if I'm not, the service can handle everything needed as well with the knowledge and dependencies he has.

Code Example based on the ubiquitous language of a car repair shop

public class Car : AggregateRoot {

    private readonly IWheelRepository _wheels;
    private readonly IMessageBus _messageBus;

    public void AddWheel(Wheel wheel) {
        _wheels.Add(wheel);
        _messageBus.Raise(new WheelAddedEvent());
    }

}

public static class CarFactory {

    public static Car CreateCar(string model, int amountofWheels);

}

..or...

public class Car {

    public ICollection<Wheel> Wheels { get; set; }

}

public interface ICarService {

    Car CreateCar(args);
    void DeleteCar(args);
    Car AddWheel(int carId, Wheel wheel);

}
share|improve this question
    
I use domain services to implement domain use cases. I rarely use factories, don't really need them. –  MikeSW May 6 at 13:41

1 Answer 1

DDD is in part a reaction to anaemic domain models, where your entities would only have state, but not behaviour.

It's true that in a sense you could put all the behaviour of Car in a separate service, but why would you want to? For that to work, you'd need to expose all sorts of state in Car, which you would normally like to keep private (like Wheels).
If you expose Wheels like that, any code could do all sorts of funky stuff to that collection, outside of any normal business flow. Keep in mind that the point of an aggregate is to have something that is transactionally consistant between business flow transactions. Exposing Wheels like that completely undermines that safety.
For example: say your business only wants to support cars with four wheels. If you encapsulate access to Wheels, you can enforce that. If you don't, it's completely possible to add a hundred wheels to a car, because Wheels would be exposed.

A service is generally used as a coordinator. A commandhandler (assuming something like CQRS) translates a command object to more strongly typed parameters, reducing primitive obsession. Then it can call a service with those more "domain-ish" parameters. The service retrieves entities from repositories and invokes behaviours on them. Depending on your architecture, it can then collect any changes (events) and pass them to a bus or whatever.
In more advanced scenarios, you'd use a unit of work that keeps track of all your entities and can collect the changes from all of them in one swoop.

As for a factory (as an aside), nothing's stopping you from adding a static factory method your aggregate class, instead of creating a separate factory.

share|improve this answer
    
"DDD is in part a reaction to anaemic domain models, where your entities would only have state, but not behaviour." Your explaination sounds reasonable. I see more and more that DDD is about thinking in DDD, not doing DDD. The only concern I have with your suggestion is when I want to expose parts of my domain to other applications (let's say I've got a frontend application and a backend service which communicate over WCF), then I need to introduce new models just for the sake of communication (because the frontend might not know what a aggregate is and what behavior it has) –  Acrotygma May 5 at 9:09
    
@Acrotygma Odds are that your frontend will need data in a completely different form than the form in which your aggregates will be modelled. This is almost always the case, so you're better off making that distinction explicit and creating separate write and read models. I know this sounds like a lot of work, but you can't have one model that suits all scenarios; in the best case, you'll wind up with something not particularly suited for read nor write. E.g. aggregates are great for business logic, not so much for sending accross the wire as a DTO. –  Stefan Billiet May 5 at 9:19

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.