What he's saying here is that you should avoid a scenario where a base class takes a dependency to meet the need of a descendant. Let's look at the case of a Switch and its descendant the TimedSwitch. The TimedSwitch is a Switch that resets itself after a certain amount of time. We have the TimedObject class already so it would make sense for TimedSwitch to derive from it...however TimedSwitch already derives from Switch. So in order to meet the needs of the TimedSwitch, Switch will inherit from TimedObject even though it doesn't need that functionality itself.
The Switch (abstraction) is dependent on the details of TimedSwitch. To fix this violation of the DIP, we have TimedSwitch implement ITimedObject and delegate to a contained TimedObject class (prefer composition over inheritance).
Another more generic example is the layered approach. The higher level layers are abstractions and in most cases they depend on the details. DIP says that instead, the lower layers should conform to an interface which they both take dependency on. Thus the dependency is inverted from Higher Layer depending on lower layer to both layers depending on an interface.
Are Domain Services merely an Interface which exist to provide a layer
of abstraction between the Infrastructure Layer and your Model? ie:
Repositories + HashingServices, etc.
Domain services responsibilities include several things. The most obvious is housing logic that doesn't fit into a single entity. For example, you may need to authorize a refund for a certain purchase, but to complete the operation you need data from the Purchase
entity, Customer
entity, CustomerMembership
entity.
Domain services also my provide operations needed by the domain to complete its functionality such as PasswordEncryptionService
, but the implementation of this service will reside in the infrastructure layer since it will mostly be a technical solution.
Infrastructure services are services which so an infrastructure operation such as opening a network connection, copy file from file system, talk to an external web service or talk to database.
Application services are the implementation of a use case in the application you are building. If you are cancelling a flight reservation you would:
- Query the database for the Reservation object.
- invoke Reservation->cancel.
- Save object to DB.
The application layer is the client of the domain. The domain has no idea what your use case is. It just exposes the functionality through its aggregates and domain services. The application layer however mirrors what you are trying to achieve by orchestrating the domain and infrastructure layers.
I mentioned having an Application Service which looks like this:
Access/Application/Services/UserService::CreateUser(string name,
string email, etc): User
The method signature accepts primitive data type arguments and returns
a new User Entity (not a DTO!).
PHP might not be the best place to start learning about DDD since many of the PHP frameworks out there (Laravel, Symfony, Zend,..etc) tend to promote RAD. They are focused more on CRUD and translating forms to entities. CRUD != DDD
Your presentation layer should be responsible for reading the form inputs from the request object and invoking the correct application service.
The application service will create the user and invoke the User repository to save the new user. You may optionally return a DTO of the user back to the presentation layer.
How should separate modules handle unidirectional relationships.
Should module A reference module B's application layer (as it's doing
now) or the infrastructure implementation (via separated interface)?
The word module in DDD lingo has a different meaning than what you are describing. A module should house related concepts. For example, an order module in the domain layer could house the Order aggregate, OrderItem entity, OrderRepositoryInterface and MaxOrderValidationService.
An Order module in the application layer could house the OrderApplicationServie, CreateOrderCommand and OrderDto.
If you are talking about layers then each layer should preferably depend on interfaces of other layers whenever possible. The presentation layer should depend on interfaces of the application layer. Application layer should reference interfaces of the repositories or domain services.
I personally don't create interfaces for entities and value objects coz I believe interfaces should be related to a behavior, but YMMV :)
Do Application Layer Services require a Separate Interface? If the
answer is yes then where should they be located?
It depends :)
for complex applications I build interfaces coz we apply rigorous unit, integration and acceptance testing. Loose coupling is key here and the interfaces are in the same layer (application layer).
For simple app I build against the app services directly.
Best Answer
It doesn't break DIP because Domain is the highest level, higher than Application, and doesn't have a dependency on it. The reverse (Domain depending on Application) would break DIP.
Also, the "should depend on abstraction" part of DIP doesn't necessarily apply here, because domain entities can't be abstracted -- they are already a pure conceptual model of your domain. The only exception may be Domain Services, because you could place an interface in front of those.
As a side note, you generally don't need to leverage dependency inversion inside the Domain model itself, because