Entonces, después de leer "Implementando el diseño impulsado por el dominio por Vaughn Vernon", he decidido refactorizar mi código para una mejor usabilidad al aislar lo que creo que son conceptos básicos del dominio en módulos separados.
Cada módulo contiene su propio conjunto de capas arquitectónicas distintas que incluyen el dominio, la infraestructura y la capa de aplicación / presentación (según la recomendación de Vaughn, he decidido separar aún más las responsabilidades de la capa de aplicación de las rutas, controladores MVC + plantillas que existen en el Capa de presentación).
He decidido colocar cada una de estas capas dentro de su propio paquete; y cada paquete hace referencia a la capa debajo de él como una dependencia. es decir: la capa de presentación depende de la capa de aplicación, la aplicación depende de la infraestructura, etc. Dado que el repositorio es parte del dominio, cada interfaz de repositorio existe dentro de la capa / paquete del dominio y la implementación es responsabilidad de la capa / paquete de infraestructura (Doctrine , etc.)
Espero que al reestructurar mi código de esta manera pueda intercambiar la capa de Aplicación y reutilizar mi Dominio en múltiples Aplicaciones Web.
El código finalmente parece que está empezando a formarse nuevamente, sin embargo, lo que aún me confunde es esta distinción entre Aplicación, Infraestructura y Servicios de dominio.
Un ejemplo común de un Servicio de dominio es algo que usaría para hacer hash de contraseñas. Esto tiene sentido para mí desde la perspectiva de SRP, ya que la entidad User no debería preocuparse por los diferentes algoritmos de hash que podrían usarse para almacenar las credenciales de un usuario.
Con eso en mente, traté este nuevo servicio de Dominio de la misma manera que mis Repositorios; definiendo una interfaz en el Dominio y dejando la implementación a la capa de Infraestructura. Sin embargo, ahora me pregunto qué debería hacerse con los Servicios de aplicación.
Tal como está ahora, cada entidad tiene su propio servicio de aplicación, es decir, la entidad de usuario tiene un servicio de usuario dentro de la capa de aplicación. El UserService en este caso es responsable de analizar los tipos de datos primitivos y manejar un caso de uso común "UserService :: CreateUser (nombre de cadena, cadena de correo electrónico, etc.): Usuario.
Lo que me preocupa es el hecho de que tendré que volver a implementar esta lógica en varias aplicaciones si decidiera cambiar la capa de aplicación. Así que supongo que esto me lleva a mis próximas preguntas:
¿Los servicios de dominio son simplemente una interfaz que existe para proporcionar una capa de abstracción entre la capa de infraestructura y su modelo? es decir: repositorios + servicios de hash, etc.
Mencioné tener un Servicio de Aplicación que se ve así:
Access / Application / Services / UserService :: CreateUser (nombre de cadena, cadena de correo electrónico, etc.): Usuario
La firma del método acepta argumentos de tipo de datos primitivos y devuelve una nueva entidad de usuario (¡no un DTO!).
¿Pertenece esto a la capa de Infraestructura como una implementación de alguna interfaz definida dentro de la capa de Dominio o la Capa de Aplicación es de hecho más apropiada debido a los argumentos de tipo de datos primitivos, etc. ?
ejemplo:
Access/Domain/Services/UserServiceInterface
y
Access/Infrastructure/Services/UserService implements UserServiceInterface
Cómo deben manejar los módulos separados las relaciones unidireccionales. ¿Debería el módulo A hacer referencia a la capa de aplicación del módulo B (como lo está haciendo ahora) o la implementación de la infraestructura (a través de una interfaz separada)?
¿Los servicios de capa de aplicación requieren una interfaz separada? Si la respuesta es sí, ¿dónde deberían ubicarse?