For the user validation part of your question, the guiding principle is Postel's law: be conservative in what you send, liberal in what you accept. That means you should always display the serial number with the dashes, but assuming you can correctly reconstruct the serial number without them, allow the users to enter serial numbers either with or without the dashes.
As for storage, it really depends on if you frequently need to do queries on subfields of the number. If you don't, it's most robust to store it in the preferred format for reading it, that is, with the dashes. That way a developer or database admin running a query from a non user-facing interface like a CLI won't have to parse it out in his head.
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
The common handling (as I see it) is to raise an exception and log the error. You always will have cases where business logic comes to places where nobody has been before. That means you need to handle the exception gracefully: