2012-07-31 11 views
33

Recientemente me encontré con esta publicación javalobby http://java.dzone.com/articles/how-changing-java-package en el código de embalaje de Java por función.¿Es bueno el enfoque paquete por función?

Me gusta la idea, pero tengo algunas preguntas sobre este enfoque. Hice mi pregunta pero no obtuve una respuesta satisfactoria. Espero que alguien en StackOverflow pueda aclarar mis preguntas.

Me gusta la idea de paquete por característica que reduce enormemente el tiempo de desplazamiento entre los paquetes mientras se codifica y todo lo relacionado estará en un solo lugar (paquete). Pero, ¿qué ocurre con las interacciones entre los servicios en diferentes paquetes?

Supongamos que estamos construyendo una aplicación de blog y estamos poniendo todas las operaciones relacionadas con el usuario (controladores/servicios/repositorios) en el paquete com.mycompany.myblog.users. Y todas las operaciones relacionadas con publicaciones de blog (controladores/servicios/repositorios) en el paquete com.mycompany.myblog.posts.

Ahora quiero mostrar el perfil de usuario junto con todas las publicaciones que publicó. ¿Debo llamar al myblog.posts.PostsService.getPostsByUser(userId) desde myblog.users.UserController.showUserProfile()?

¿Qué pasa con el acoplamiento entre paquetes?

También cada vez que leo sobre el paquete por característica, todos dicen que es una buena práctica. Entonces, ¿por qué muchos autores de libros e incluso marcos animan a agrupar por capas? Sólo por curiosidad para saber :-)

Respuesta

16

Respondido alguna parte: Tome un vistazo a tío Bob

Package Design Principles

Explica las razones y motivaciones detrás de esos principios.

EDIT: Tuve la respuesta original de writtern más de 2 años atrás. Pero no cambió ya que fue aceptado. Pero cambiándolo para que cualquier nuevo visitante se beneficie y evite la podredumbre del enlace como lo sugiere @bPraktik.

Las clases que se reutilizan juntas deben empaquetarse juntas para que el paquete se pueda tratar como una especie de producto completo disponible para usted. Y aquellos que se reutilizan juntos deben separarse de aquellos con los que no se reutilizan. Por ejemplo, sus clases de utilidad de registro no se usan necesariamente junto con sus clases de archivo io. Así que empaquete todo registrándolos por separado. Pero las clases de registro podrían estar relacionadas entre sí. Por lo tanto, cree un tipo de producto completo para registrar, por ejemplo, para la necesidad de un mejor nombre commons-logging, empaquételo en un jar (reutilizable) y otro producto completo separado para utilidades io, nuevamente para la falta de un mejor nombre, digamos commons- io.jar. Si actualiza la biblioteca say commons-io para decir que es compatible con java nio, es posible que no desee necesariamente realizar ningún cambio en la biblioteca de registro. Entonces, separarlos es mejor.

Ahora, digamos que quería que sus clases de utilidad de registro admitan el registro estructurado para decir algún tipo de análisis de registro por herramientas como splunk. Es posible que algunos clientes de su herramienta de registro quieran actualizar a su versión más nueva; algunos otros pueden no. Entonces, cuando publique una nueva versión, empaquete todas las clases que sean necesarias y reutilizadas juntas para la migración. Por lo tanto, algunos clientes de sus clases de utilidad pueden eliminar de forma segura su antiguo contenedor de registro de recursos comunes y pasar a commons-logging-new jar. Algunos otros clientes todavía están bien con el jar más antiguo. Sin embargo, no se necesitan clientes para tener estos dos jarrones (nuevos y viejos) solo porque los obligó a usar algunas clases para el jar empaquetado anterior.

Evite las dependencias cíclicas. a depender de b; b en c; c en d; pero d depende de a. El escenario es obviamente disuasivo, ya que será muy difícil definir capas o módulos, etc. y no se puede variar de forma independiente entre sí.

Además, podría empaquetar sus clases de tal manera que si una capa o módulo cambia, otros módulos o capas no tienen que cambiar necesariamente. Entonces, por ejemplo, si decide pasar de una antigua estructura de MVC a una actualización de API de descanso, entonces solo la vista y el controlador pueden necesitar cambios; tu modelo no.

+2

Buen artículo vinculado, pero actualice esta respuesta para evitar la rotura del enlace. – bPratik

+0

@bPratik actualizado. – Atul

10

Hay muchos otros aspectos distintos de acoplamiento para el diseño de envase que sugeriría que mirar OOAD priciples de, sobre todo paquete priciples de diseño como

REP El lanzamiento reutilización de Equivalencia Principio El gránulo de la la reutilización es el gránulo de lanzamiento.

CCP El principio de cierre común Las clases que cambian juntas se empaquetan juntas.

CRP El principio de reutilización común Las clases que se utilizan juntas se empaquetan juntas.

ADP Principio Dependencias Acíclicas El gráfico de dependencia de los paquetes no debe tener ciclos.

SDP El principio de las dependencias estables Dependen de la estabilidad.

SAP The Stable Abstractions Principio La abstracción aumenta con la estabilidad.

para más información se puede leer book "desarrollo ágil de software, principios, patrones y prácticas"

10

personalmente me gusta el enfoque de "paquete de función", aunque sí es necesario aplicar un buen montón de juicio sobre dónde dibujar los límites del paquete. Sin duda es un enfoque factible y sensato en muchas circunstancias.

Probablemente debería lograr el acoplamiento entre paquetes y módulos utilizando interfaces públicas, esto mantiene el acoplamiento limpio y manejable.

Está perfectamente bien para el paquete "publicaciones de blog" llamar al paquete "usuarios" siempre que utilice interfaces públicas bien diseñadas para hacerlo.

Sin embargo, un consejo importante si se analiza este enfoque: tenga muy en cuenta sus dependencias y, en particular, evite las dependencias circulares entre paquetes. Un buen diseño debe parecerse a un árbol de dependencias, con áreas de funcionalidad de nivel superior que dependen de un conjunto de servicios comunes que dependen de bibliotecas de funciones de utilidad, etc. En cierta medida, esto comenzará a parecerse a "capas" arquitectónicas con frente paquetes finales que llaman a servicios de back-end.

Cuestiones relacionadas