Let's start with a brief discussion of what a
Domain Service is, and why you would want to use one. Because I would hesitate, upon an initial inspection, to call your example a
Domain Services are most often employed to solve two problems: When you want to extract some sort of calculation or other side-effect-free process into an object of it's own to be used/re-used by many pieces of your domain, or when there exists business logic about the behavior of some process that naturally spans multiple
Entities. The former has many obvious manifestations, but the quintessential example of the latter is for the coordination of transactions that occur between
Entities. That is, the execution of the business process requires the execution of commands to more than one
Say, you have an
Atm and a
CheckingAccount. Withdrawing money from the
Atm requires knowledge that the
CheckingAccount has sufficient funds to complete the transaction. Because
Atm.WithdrawCurrency( decimal amount ) is completely separate from
CheckingAccount.Debit( decimal amount ) but both need to be coordinated to complete the transaction, a
Domain Service is an apt solution. In this case the
AtmService will hold the knowledge regarding whether or not we will be dispensing money.
Aside from the above considerations,
Domain Services will only serve to make your model more anemic. It can be incredibly tempting to button up all of the behavior of your system into discrete "services" that simply act on your model, but that is the antithesis of DDD and only hurts in the long run.
Looking at your example, does it contain business logic (we will get to that
Event in moment)? Not really. Your methods seem to simply be coordinating between your
Entities and the outside world. There aren't really any decisions being made. This reads more like an
Application Service (retrieve piece of model -> execute command -> save).
As for that
Event, I would refrain from raising
Events from an
Application Service. If, for some reason, you need there to be an
Event recording when an
AdministrationAccount is "opened", try to make it more explicit:
public void Open()
this.state = this.state.Open(this);
then in it's state:
public IAdministrationAccountState Open( AdministrationAccount account )
return new OpenedAdministrationAccountState(account);
The example above is using a FSM, but I could conceive of other options here. The important thing is that the logic and
Event is squarely inside your domain where they belong. Not floating out in some
Service method where they will inevitably be bypassed.
As for your other
RegisterNewAccount method. Is this really the right place to create the account? When you talk about a new account being opened in the office, do you say "The
AdministrationAccountService registered a new account with a
displayName"? Or do you say, "An
AdminUser registered a new account"? What I'm getting at here is that the method could easily be refactored to be part of what ever is holding the
displayName before registration. E.g.
AdminUser.Register(). Accounts (and their info) don't come out of nowhere. You can check out this link for a bit more: http://udidahan.com/2009/06/29/dont-create-aggregate-roots/
Refactoring towards the above helps purify and distill your application service.
As for whether or not a
Domain Service can also be a factory? I'd say, generally speaking, no. Is it conceivable? Sure, but you will be better off refactoring your model towards deeper insight such that it isn't necessary. This kind of question is almost always a sign of a deficient model. Not some missing technical detail.