Estructura de la aplicación Java: división horizontal versus vertical

15

Tener un poco de debate sobre la estructura inicial del proyecto (usando Maven / Eclipse) para una gran aplicación Java.

Opción 1:

entities (i.e. the whole database using Hibernate classes-first)
services (i.e. sets of read/write operations on the entities)
app (perhaps split up more further down the line)

Opcion 2:

area1-entities
area1-services
area1-app
area2-entities
area2-services
area2-app
...
(where area1, area2 etc. are functional areas of the system)

La opción 2 claramente dará como resultado muchos más proyectos / módulos de Maven y significa que las clases que generarían la base de datos se distribuyen entre múltiples proyectos. ¿Alguien podría aconsejar pros / contras de cada enfoque?

Steve Chambers
fuente
3
Ninguno. En mi humilde opinión (aquí vamos) deberíamos dejar de separarnos en capas técnicas que simplemente conducen a una gran bola de barro. En su lugar paquete funcionalmente. Solo area1 / area2 que debe contener el núcleo de su aplicación (entidades, servicios (división en la interfaz pública e implementación privada del paquete), repositorios (si es necesario). Ahora debe conectar su capa web / ws / messaging a ese núcleo. quiero echar un vistazo aquí y aquí
Todavía se opina :). Pero puliré un poco para ponerlo en respuesta.
Es posible que desee consultar stackoverflow.com/questions/11733267/…
Gracias, pero esta pregunta es sobre la estructura del proyecto en lugar de la estructura del paquete
Steve Chambers

Respuestas:

29

Sugeriría no hacer nada.

Intentar imponer una estratificación técnica con una estructura de paquete genera muchos enredos en su aplicación. Sin mencionar el hecho de que nos esforzamos por ocultar todo detrás de una interfaz de servicio y lo primero que hacemos (principalmente debido al empaque) es hacer que todo sea una public class. Esto se convierte en doloroso cuando hay una separación entre un técnico x.y.z.servicey el x.y.z.repositorypaquete, ahora todo puede acceder al repositorio. Boom allí va su encapsulación dentro de la capa de servicio.

En su lugar, debe seguir un enfoque más funcional y basado en la cebolla ( arquitectura limpia , arquitectura hexagonal ). Esto también está muy en línea con el Principio de responsabilidad única (cuando se aplica a un paquete) y también de acuerdo con los principios de empaque

  1. Las cosas que cambian juntas se empaquetan juntas
  2. Las cosas que se usan juntas se empaquetan juntas

Oliver Gierke ha escrito una buena publicación sobre componentes de empaque juntos en Java. Simon Brown ha escrito una historia más general sobre el tema.

Me esforzaría por una estructura de paquete central como la siguiente para mantener el núcleo de su aplicación:

x.y.z.area1
x.y.z.area2

Ahora, si tiene una interfaz web, agregue, por ejemplo, un websubpaquete, para que un servicio web wso un restpaquete contengan solo eso. Básicamente se conecta al núcleo.

x.y.z.area1.web
x.y.z.area1.ws
x.y.z.area2.rest

Ahora podría considerar reutilizar los objetos del interior de su núcleo en las otras capas, pero en mi humilde opinión, es mejor usar un dominio específico para esa capa. Como, al igual que con el mapeo de objetos a SQL, (a menudo) hay una falta de coincidencia en lo que queremos mostrar en la pantalla o usar como XML en el servicio web y cómo se implementa la lógica de negocios. Dependiendo de la complejidad del negocio y los dominios web, podría considerarlos como dominios de problemas separados para resolver los que necesitan estar conectados, básicamente 2 contextos limitados diferentes .

Para usar una cotización de un recurso CQRS

No es posible crear una solución óptima para buscar, informar y procesar transacciones utilizando un solo modelo.

No intente poner todo en un solo modelo (dominio), separe las responsabilidades. Probablemente termines con más clases (más pequeñas) pero una separación más limpia entre las capas de tu aplicación.

Nota final

Recuerde que crear una arquitectura es decidir las compensaciones de una solución a la otra. Depende en gran medida de la complejidad del dominio y se debe principalmente a los requisitos funcionales de su aplicación. Sin embargo, está influenciado por las restricciones no funcionales (rendimiento, seguridad) y ambientales (lenguaje de uso, plataforma, experiencia). Y la arquitectura, como la codificación, nunca se termina, cada nuevo requisito puede (y tal vez debería) conducir a un rediseño de la aplicación.

Descargo de responsabilidad

Sí, también intenté poner todo en un solo modelo, y sí, también intenté usar una separación técnica en mis aplicaciones. Sin embargo, después de un par de años de experiencia en la creación de capas de aplicaciones enredadas (al principio parece una buena idea, luego la aplicación comienza a crecer ...) pensé que debía haber otra forma.

Enlaces

  1. Arquitectura limpia, tío Bob Martin
  2. Arquitectura Hexagonal (también conocida como Puertos y Adaptadores), Alistair Cockburn
  3. Vaya, ¿a dónde fue mi arquitectura, Oliver Gierke?
  4. Principios de OOD, tío Bob Martin
  5. Errores al aplicar DDD, Udi Dahan
  6. Contextos delimitados, Martin Fowler
  7. Estilo de codificación arquitectónicamente evidente, Simon Brown

Libros

  1. Creciente software orientado a objetos, guiado por pruebas
  2. Arquitectura de aplicaciones Java: patrones de modularidad con ejemplos utilizando OSGi (serie Robert C. Martin)
  3. Diseño basado en dominios: abordar la complejidad en el corazón del software
  4. Arquitectura de software para desarrolladores
  5. Implementación de diseño dirigido por dominio
M. Deinum
fuente
1
Buena respuesta :) Añadiría una lectura obligada para abordar este tema: amazon.com/Growing-Object-Oriented-Software-Guided-Tests/dp/…
Mik378
1
Buena, agregó un par más a mi respuesta original.
1
Es, con mucho, el mejor libro sobre diseño que he leído;) Puede mencionar el libro de Vaughn Vernon, muy bueno también: amazon.com/Implementing-Domain-Driven-Design-Vaughn-Vernon/dp/…
Mik378
@ M.Deinum +1 ¡Excelente para referencia!
1
@ Mik378 Tengo ambos libros en mi biblioteca digital, entre muchos otros.