So after reading "Implementing Domain-Driven Design by Vaughn Vernon" I've decided to refactor my code for better re usability by isolating what I believe to be core domain concepts into separate modules.
Each module contains their own set of distinct architectural layers which include the Domain, Infrastructure and the Application/Presentation layer (per Vaughn's recommendation I've decided to further separate the responsibilities of the Application layer from routes, MVC controllers + templates which exist in the Presentation Layer).
I've decided to place each of these layers within their own package; and each package is referencing the layer beneath it as a dependency. ie: Presentation Layer depends on the Application Layer, Application depends on Infrastructure, etc. Since the Repository is a part of the Domain, each Repository Interface exists within the Domain layer/package with implementation being a responsibility of the Infrastructure layer/package (Doctrine, etc).
I'm hoping that by restructuring my code in this way I'll be able to swap out the Application layer and reuse my Domain across multiple Web Applications.
The code finally looks like it's starting to shape again however what still confuses me is this distinction between Application, Infrastructure and Domain Services.
One common example of a Domain Service is something which you would use to hash passwords. This makes sense to me from a SRP perspective since the User entity shouldn't concern itself with the many different hashing algorithms which might be used to store a user's credentials.
So with that in mind I treated this new Domain service the same way as my Repositories; by defining an interface in the Domain and leaving the implementation up to Infrastructure layer. However, now I'm wondering about what should be done with the Application Services.
As it stands now, each Entity has its own Application Service, i.e. the User Entity has a UserService within the Application Layer. The UserService in this case is responsible for parsing primitive data types and handling a common use-case "UserService::CreateUser(string name, string email, etc) : User.
What concerns me is the fact that I'll need to re-implement this logic across multiple applications should I decide to swap out the Application layer. So I guess this leads me to my next few questions:
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.
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!).
Does this belong in the Infrastructure layer as an implementation of some interface defined within the Domain layer or is the Application Layer in fact more appropriate due to primitive data type arguments, etc?
example:
Access/Domain/Services/UserServiceInterface
and
Access/Infrastructure/Services/UserService implements UserServiceInterface
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)?
Do Application Layer Services require a Separate Interface? If the answer is yes then where should they be located?