If the 'business logic' you mention is only relevant for a view then it may not be 'business logic' as you call it. It could simply be presentation logic, having an if statement somewhere doesn't immediately mean it's business logic.
Populating a view or edit model I usually do either in the controller, sometimes I let the view or edit model populate itself by passing in a domain object. If possible I prefer creating AutoMapper mappings to do most of the work.
If it really is business logic then maybe your domain model needs some improvement. This is not uncommon, if a view or edit model really differs a lot with the domain concepts maybe there is something fishy about the domain model.
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
Separate the user's need for some order number from the Primary Key/ID in the database. Make sure you identify why they want this numbering system and what they plan on doing with it.
If this represents the order they've entered their Activities, how do you handle a deletion? Do you leave a gap in the numbering? If order of entry is the driving force, save the date/time of entry and then you can create an order number / ID on the fly. This can even be a part of a select statement from a database using some type of Row_Number function if you don't want to do it in your app. They're very efficient, but you would have to perform this on all the records and then retrieve a subset of those records. If performance becomes a problem, you're going to have to save the values and then have some a ReOrdering function after a deletion.
If gaps in the numbering system are OK, then you can make this number permanant. To add a new number, you just need to query the database and get the last one. It's no different than retreiving any other value. DBs are pretty efficient at getting Max() values.
EDIT: I don't see any reason why this can't be generated in the database. It doesn't have to be the primary key just auto incremented. I know a DBA might change PK's if this app grows into some replicated environment or someone wants to put some intelligence in the number. The users need to understand by changing these numbers they run the risk of not being able to reference them the same way in their future meetings (Assuming someone keeps all the paper copies.).