Solución:
En pocas palabras
La arquitectura en capas simplemente facilitará el mantenimiento y la consistencia del código cuando se vuelva enorme y complejo.
Lo que hay que recordar es que hay que hacer un diseño de software adecuado antes de realizar la implementación.
- Encapsulación: la lógica empresarial específica para un modelo de dominio debe ir dentro de ella.
- Abstracción: separe las interfaces de acuerdo con la agrupación de servicios mientras escribe la lógica comercial común en la abstracción.
- Herencia: utilícelo cuando esté redactando los objetos de su dominio
- Polimorfismo: junto con la herencia cuando desea cambiar la lógica empresarial de los modelos secundarios.
En detalle
A continuación, estoy haciendo todo lo posible para proporcionar un ejemplo de una aplicación ERP para esta discusión. Espero que un ERP sea suficiente gran proyecto para ver la complejidad de la lógica empresarial.
La siguiente descripción es para cualquier desarrollador que necesite una idea para comprender y hacer uso de la estructura de proyecto en capas en Spring (o cualquier otro marco).
Pero tenga en cuenta que estas no son reglas que deben seguirse, sino las mejores prácticas que deben utilizarse. 🙂
1. Capa de acceso a datos: objetos de modelo / dominio
Contiene el mapeo de tablas reales a clases.
En un ejemplo de ERP, aquí es donde obtienes los modelos:
CustomerOrder
,CustomerOrderLine
Esto también contiene la lógica encapsulada de los objetos del dominio hijo y la lógica del dominio del yo. Por ejemplo, el
CustomerOrderLine
es hijo deCustomerOrder
. El niño no puede existir sin los padres. Entonces, el padre tendrá el control total de la construcción de los hijos dentro de él. es decir Encapsulación de lógica empresarial.. es decir:Add CustomerOrderLine
,RemoveCustomerOrderLine
etc. Y en lo que respecta a la lógica del dominio propio,ApproveCustomerOrder
,RejectCustomerOrder
etc.
2. Capa de acceso a datos: repositorio
Esto no contiene nada más que CRUD simple a la base de datos con SELECT, INSERT, UPDATE and DELETE SQLs
. Puede usar el patrón de repositorio en Spring junto con Spring Data JPA
.
Nota clave: no escriba ninguna lógica compleja en esta capa a menos que su lógica sea muy intensiva en datos
En ese caso, es posible que deba escribir una o más funciones para realizar declaraciones de consulta complejas. (Preferiblemente en JPQL
)
En un ejemplo de ERP, este es el lugar para el que escribe lógica
GetCustomerOrders
,GetCustomerOrderByCustomer
,GetCustomerOrderLines
,GetOrderByStatus
En términos simples, esta capa define cómo la aplicación se comunicará con las entidades externas, como la base de datos.
3. Capa de servicio
Este es el lugar donde debe poner su lógica de negocios compleja que involucró múltiples modelos de dominio no conectados (no hijo – padre). Estos se reutilizarán en los controladores web y los controladores API de descanso.
Así que para mantener la consistencia y implementar la seguridad, Preferiría que toda la lógica empresarial, incluso la que se escribió en los modelos de dominio, se envuelva en esta capa.
En el ejemplo de ERP, este es el lugar donde escribe la lógica o envuelve la lógica que está escrita en el Modelo de dominio. Por ejemplo
CreateCustomerOrder
,ListCustomerOrder
,ApproveCustomerOrderLine
,ReleaseCustomerOrder
…
En caso de que esta lógica se ejecute junto con otras lógicas de modelo, también se debe llamar en la secuencia dentro de la capa de servicio. Por ejemplo.
Varios ejemplos sobre lógica empresarial compleja
Si desea crear un
Purchase Order
para su proveedor, cuando elCustomer Order
en lanzamiento.
Entonces, esto se puede hacer creando un servicio llamado SupplyChainService
enlazado usando Spring AOP al CustomerOrderService.ReleaseCustomerOrder
. En el diseño de microservicios, esto se puede realizar mediante un evento publicado por Supply chain
microservicio de dominio a una cola y ser consumido por Customer Order
microservicio de dominio
4. Controladores
Los controladores se pueden clasificar en dos, a saber: controladores web y controladores REST. No se debe implementar ninguna lógica empresarial en esta capa porque se puede requerir la misma lógica para llamar tanto en la Web como en el nivel de API.
En el sistema ERP, este es el lugar donde escribirá el controlador para su formulario de pedido de cliente para ingresar datos y guardarlos para crear un nuevo pedido de cliente.
Este será el lugar donde también creará un controlador API como REST para crear el pedido del cliente a través de una aplicación móvil o desde un cliente de Windows.
Gracias a la comunidad de SO que me mostró áreas que no cubrí en los principios de OOP en esta respuesta
Editar
Esta es una respuesta cuando el microservicio no es demasiado común. Aunque respondió a los conceptos de OOP, también observe el diseño basado en CQRS, ya que es más común en la arquitectura moderna basada en microservicios. De cualquier manera, puede incorporar conceptos de programación orientada a objetos independientemente del patrón de arquitectura de software que utilice.
El diseño de la aplicación Spring y OOD no son mutuamente excluyentes.
La aplicación típica de Spring (MVC) tiene la siguiente estructura:
- Uno o mas
@Controller
clases. Estos son los puntos de entrada de su aplicación. No deben contener ninguna lógica empresarial. A pesar del nombre, los identifico como el V en MVC (Modelo-Vista-Controlador) - Uno o mas
@Service
clases. Aquí es donde desarrolla su lógica empresarial (BL). Uno de los beneficios de poner su BL aquí es que puede ser reutilizado por varios controladores (por un@Controller
y por un@RestController
por ejemplo). Ellos son las C en MVC. - Uno o mas
@Repository
clases, donde implementas tu capa de persistencia (base de datos, en memoria, lo que sea …). Además, puede implementar un conjunto de@Component
s clases que describen los objetos de su dominio. Estos son los METRO en MVC. - Otras clases que no puede asignar en el patrón MVC, como
@Configuration
,@ControllerAdvice
y otras clases de configuración / gestión de Spring.
Al diseñar cada uno de estos objetos, puede seguir cualquier enfoque OOD que desee.
En el ejemplo de OOD que mencionaste, diseñaría mi aplicación así:
- Una vista (
@Controller
) para cada actor - Uno
@Service
para cada caso de uso - Uno
@Repository
y uno@Component
para cada clase de dominio
EDITAR: puedes encontrar un proyecto de ejemplo que escribí para la universidad aquí. Implementa lo que expliqué en los últimos tres puntos con una capa adicional (entre @Controller y @Service) porque había un requisito para minimizar las dependencias en el C capa. Los conceptos aún se aplican.
Creo que estás haciendo una pregunta incorrecta aquí. La arquitectura en capas no está intrínsecamente orientada a objetos y, por lo tanto, aunque sería posible o incluso aconsejable utilizar (algunas de) las prácticas orientadas a objetos con ella, no debería ser el objetivo en sí mismo. Es similar a preguntar cómo utilizo las mejores prácticas de conducción de camiones para andar en bicicleta.
¿Por qué digo que la arquitectura en capas no está orientada a objetos? Bueno, como sabemos, hay tres principios que distinguen el diseño orientado a objetos: encapsulación, herencia y polimorfismo.
Si bien los dos últimos pueden estar presentes o no, dependiendo de sus elecciones de diseño, la arquitectura en capas es, más o menos, la opuesto de encapsulación: por la naturaleza de este enfoque, separa explícitamente sus datos (“DTO”) de su lógica (“servicios”).
No me malinterpretes, el hecho de que este enfoque no esté orientado a objetos no significa que tenga nada de malo. Y viceversa, “orientado a objetos” no es sinónimo de “bueno”, es una de las muchas herramientas en la caja de herramientas de un programador y, como con cualquier herramienta, es más adecuada para resolver algunos problemas que otros.
La arquitectura en capas es un buen patrón de diseño que se puede utilizar con éxito para resolver muchos problemas de ingeniería de la vida real. Tiene su propio conjunto de mejores prácticas que pueden y deben usarse, y aunque ese conjunto puede tener algunas intersecciones con su contraparte de OOP, los dos ciertamente no son equivalentes.