Então, depois de ler "Implementando o design orientado a domínio por Vaughn Vernon", decidi refatorar meu código para obter melhor reutilização, isolando o que eu acredito serem os conceitos principais de domínio em módulos separados.
Cada módulo contém seu próprio conjunto de camadas arquiteturais distintas, que incluem as camadas Domínio, Infra-estrutura e Aplicativo / Apresentação (por recomendação de Vaughn, decidi separar ainda mais as responsabilidades da camada Aplicativo das rotas, controladores MVC + modelos existentes no diretório Camada de apresentação).
Decidi colocar cada uma dessas camadas dentro de seu próprio pacote; e cada pacote está referenciando a camada abaixo dela como uma dependência. ou seja: a camada de apresentação depende da camada de aplicativo, a aplicação depende de infraestrutura etc. Como o repositório faz parte do domínio, cada interface de repositório existe dentro da camada / pacote do domínio, sendo a implementação uma responsabilidade da camada / pacote de infraestrutura (Doctrine etc).
Espero que, ao reestruturar meu código dessa maneira, seja possível trocar a camada de aplicativos e reutilizar meu domínio em vários aplicativos da web.
Finalmente, o código parece que está começando a se moldar novamente, mas o que ainda me confunde é essa distinção entre aplicativos, infraestrutura e serviços de domínio.
Um exemplo comum de um serviço de domínio é algo que você usaria para senhas de hash. Isso faz sentido para mim do ponto de vista do SRP, pois a entidade Usuário não deve se preocupar com os muitos algoritmos de hash diferentes que podem ser usados para armazenar as credenciais de um usuário.
Então, com isso em mente, tratei esse novo serviço de Domínio da mesma maneira que meus Repositórios; definindo uma interface no domínio e deixando a implementação na camada Infraestrutura. No entanto, agora estou pensando no que deve ser feito com os Serviços de Aplicativo.
Como está agora, cada Entidade possui seu próprio Serviço de Aplicativo, ou seja, a Entidade do Usuário possui um UserService na Camada de Aplicativo. O UserService nesse caso é responsável por analisar tipos de dados primitivos e manipular um caso de uso comum "UserService :: CreateUser (nome da string, email da string, etc): Usuário.
O que me preocupa é o fato de precisar reimplementar essa lógica em vários aplicativos, caso decida trocar a camada de aplicativos. Então eu acho que isso me leva às minhas próximas perguntas:
Os Serviços de Domínio são apenas uma Interface que existe para fornecer uma camada de abstração entre a Camada de Infra-estrutura e seu Modelo? ou seja: Repositórios + Serviços de hash, etc.
Eu mencionei ter um Serviço de Aplicativo que se parece com isso:
Acesso / Aplicativo / Serviços / UserService :: CreateUser (nome da string, email da string, etc): User
A assinatura do método aceita argumentos de tipo de dados primitivos e retorna uma nova Entidade do Usuário (não um DTO!).
Isso pertence à camada Infraestrutura como uma implementação de alguma interface definida na camada Domínio ou a Camada de Aplicação é de fato mais apropriada devido a argumentos primitivos do tipo de dados, etc. ?
exemplo:
Access/Domain/Services/UserServiceInterface
e
Access/Infrastructure/Services/UserService implements UserServiceInterface
Como os módulos separados devem lidar com relacionamentos unidirecionais. O módulo A deve referir a camada de aplicação do módulo B (como está fazendo agora) ou a implementação da infraestrutura (via interface separada)?
Os serviços de camada de aplicativo exigem uma interface separada? Se a resposta for sim, então onde eles devem estar localizados?