¿Existen mejores prácticas para la organización de paquetes (Java)? [cerrado]

201

Hace un momento, vi una pregunta respondida aquí con respecto a la organización detallada de los paquetes de Java. Por ejemplo, my.project.util, my.project.factory, my.project.service, etc.

No puedo encontrarlo ahora, así que también puedo hacer la pregunta.

¿Existen mejores prácticas con respecto a la organización de paquetes en Java y qué incluye?

¿Cómo organizas tus clases en tu proyecto Java?

Por ejemplo, un proyecto en el que estoy trabajando con algunas personas tiene un paquete llamado beans. Comenzó siendo un proyecto que contenía beans simples, pero terminó (a través de poca experiencia y falta de tiempo) conteniendo todo (casi). Los he limpiado un poco, colocando algunas clases de fábrica en un paquete de fábrica (clases con métodos estáticos que crean beans) pero tenemos otras clases que hacen lógica de negocios y otras que hacen un procesamiento simple (no con lógica de negocios) como recuperar Un mensaje para un código de un archivo de propiedades.

Sus pensamientos y comentarios son apreciados.

Cyntech
fuente
74
No estoy de acuerdo con el cierre de esta pregunta. No estoy en desacuerdo con que las preguntas sobre mejores prácticas casi siempre se basan en la experiencia y la opinión, sin embargo, no estoy de acuerdo con que estas preguntas se cierren en Stack Overflow. Este es el quid de la buena programación, usar las mejores prácticas y encontrar la mejor solución utiliza estas opiniones y experiencias. Vuelve a abrir esta pregunta.
Cyntech
Le sugiero que lea esto: satisfice.com/blog/archives/5164 . TL; DR ... toda la idea de "mejores prácticas" está rota. En el mejor de los casos, es un nombre equivocado atroz, en el peor de los casos es francamente perjudicial.
Stephen C

Respuestas:

174

La organización de paquetes o la estructuración de paquetes suele ser una discusión acalorada. A continuación se presentan algunas pautas simples para nombrar y estructurar paquetes:

  • Siga las convenciones de nomenclatura de paquetes java
  • Estructura tus paquetes de acuerdo con su función funcional y su función empresarial
    • Descomponga sus paquetes según su funcionalidad o módulos. p.ej com.company.product.modulea
    • Un mayor desglose podría basarse en capas en su software. Pero no se exceda si solo tiene pocas clases en el paquete, entonces tiene sentido tener todo en el paquete. por ejemplo com.company.product.module.webo com.company.product.module.utiletc.
    • Evite exagerar con la estructuración, IMO evite empaques separados para excepciones, fábricas, etc. a menos que haya una necesidad apremiante.
  • Si su proyecto es pequeño, manténgalo simple con pocos paquetes. por ejemplo , com.company.product.modely com.company.product.util, etc.
  • Eche un vistazo a algunos de los proyectos populares de código abierto que existen en los proyectos de Apache . Vea cómo usan la estructuración para proyectos de varios tamaños.
  • También considere construir y distribuir al nombrar (lo que le permite distribuir su api o SDK en un paquete diferente, consulte la api del servlet)

Después de algunos experimentos y pruebas, deberías poder llegar a una estructura con la que te sientas cómodo. No se obsesione con una convención, esté abierto a los cambios.

naikus
fuente
Gracias por su respuesta. Esto es en gran medida lo que hemos tratado de abarcar, pero una gran cantidad de código no relacionado entró en nuestro paquete de beans, que es de donde vino mi pregunta.
Cyntech
2
Estoy de acuerdo paquete por característica tiene más sentido. Escuché una gran analogía relacionada con la estructura de la oficina de una empresa. En un enfoque por capas, cada uno de los individuos por nivel en una empresa se sentaría uno con el otro, es decir, los ejecutivos, gerentes, administradores, empleados / trabajadores se sientan en secciones separadas en un edificio. Es probable que esta estructura no sea tan efectiva como un enfoque organizado de "características". Es decir, si el ejecutivo de ventas se sienta con el gerente de ventas que se sienta con los empleados de ventas que se sientan con un administrador de ventas. Esto proporciona una mejor cohesión entre el departamento cuando se organiza de esta manera.
alex
De acuerdo con tus puntos. Solo un punto a destacar sobre el nombre de la compañía en el paquete, algunas veces la compañía obtiene un producto adquirido y se vende. La gerencia quiere eliminar el nombre de la empresa. Eso podría estar por encima.
Tushar D
183

Organizo paquetes por características , no por patrones o roles de implementación. Creo que paquetes como:

  • beans
  • factories
  • collections

estan equivocados.

Prefiero, por ejemplo:

  • orders
  • store
  • reports

para poder ocultar detalles de implementación a través de la visibilidad del paquete . La fábrica de pedidos debe estar en el orderspaquete para que los detalles sobre cómo crear un pedido estén ocultos.

onof
fuente
10
Esta publicación hace un buen punto sobre la visibilidad del paquete. Nunca he visto el alcance del paquete Java en uso, pero la estructura correcta del paquete podría permitir a los desarrolladores aprovecharlo mejor.
Jpnh
23
Esto es exactamente correcto, pero pocos desarrolladores hacen esto. Los paquetes deben ser colecciones cohesivas de clases, algunas de las cuales solo son visibles dentro del paquete. Eso minimizaría el acoplamiento entre clases que no deberían acoplarse porque pertenecen a diferentes características. El enfoque de paquete por capa no aprovecha los modificadores de visibilidad del paquete, y los paquetes en dicho proyecto tienen baja cohesión y un alto grado de acoplamiento entre paquetes.
Nate Reed
¿Tienes un ejemplo de esto? Estoy usando Spring-MVC. Me resulta difícil organizarlo por función / módulo porque Spring usa config xml.
Eric Huang
2
@onof También organizo mi código por función, pero ¿cuáles son las mejores prácticas para las clases base compartidas por todas las funciones?
Marc
Estaba siguiendo el primer estilo. pero ahora tengo que saltar de un paquete a otro cuando trabajo con clases. Realmente hace una mala experiencia. Ahora estoy cambiando al segundo estilo porque creo que será más fácil seguir clases relacionadas juntas.
M.kazem Akhgary
40

Respuesta corta: un paquete por módulo / función, posiblemente con subpaquetes. Poner cosas estrechamente relacionadas juntas en el mismo paquete. Evitar dependencias circulares entre paquetes.

Respuesta larga: estoy de acuerdo con la mayoría de este artículo

Peter Tseng
fuente
2
los subpaquetes rompen la encapsulación. Un "subpaquete" es realmente un paquete completamente independiente en sí mismo
Ricardo Gamba
21

Prefiero la función antes que las capas, pero supongo que depende de tu proyecto. Considera tus fuerzas:

  • Dependencias
    Intente minimizar las dependencias del paquete, especialmente entre características. Extraer API si es necesario.
  • Organización del equipo
    En algunas organizaciones, los equipos trabajan en funciones y en otras en capas. Esto influye en cómo se organiza el código, úselo para formalizar API o aliente la cooperación.
  • Implementación y control de versiones
    Poner todo en un módulo simplifica la implementación y el control de versiones, pero la corrección de errores es más difícil. Dividir las cosas permite un mejor control, escalabilidad y disponibilidad.
  • Responder al cambio
    El código bien organizado es mucho más sencillo de cambiar que una gran bola de barro.
  • Tamaño (personas y líneas de código)
    Cuanto más grande, más formalizado / estandarizado debe ser.
  • Importancia / calidad
    Algunos códigos son más importantes que otros. Las API deberían ser más estables que la implementación. Por lo tanto, debe estar claramente separado.
  • Nivel de abstracción y punto de entrada
    Debe ser posible que un extraño sepa de qué se trata el código y dónde comenzar a leer mirando el árbol de paquetes.

Ejemplo:

com/company/module
  + feature1/
    - MainClass          // The entry point for exploring
    + api/               // Public interface, used by other features
    + domain/
      - AggregateRoot
      + api/             // Internal API, complements the public, used by web
      + impl/ 
    + persistence/       
    + web/               // presentation layer 
    + services/          // Rest or other remote API 
    + support/            
  + feature2/
  + support/             // Any support or utils used by more than on feature
    + io
    + config
    + persistence
    + web

Esto es solo un ejemplo. Es bastante formal. Por ejemplo, define 2 interfaces para feature1 . Normalmente, eso no es obligatorio, pero podría ser una buena idea si lo usan diferentes personas. Puede permitir que la API interna extienda al público.

No me gustan los nombres 'impl' o 'support', pero ayudan a separar lo menos importante de lo importante (dominio y API). Cuando se trata de nombrar me gusta ser lo más concreto posible. Si tiene un paquete llamado 'utils' con 20 clases, vaya StringUtilsa support / string, HttpUtila support / http y así sucesivamente.

ThomasGran
fuente
13

¿Existen mejores prácticas con respecto a la organización de paquetes en Java y lo que incluye?

No, realmente no. Hay muchas ideas y muchas opiniones, ¡pero la verdadera "mejor práctica" es usar su sentido común!

(Lea No hay mejores prácticas para obtener una perspectiva sobre las "mejores prácticas" y las personas que las promueven).

Sin embargo, hay un principio que probablemente tenga una amplia aceptación. La estructura de su paquete debe reflejar la estructura del módulo (informal) de su aplicación, y debe tratar de minimizar (o idealmente evitar por completo) cualquier dependencia cíclica entre módulos.

(Las dependencias cíclicas entre clases en un paquete / módulo están bien, pero los ciclos entre paquetes tienden a dificultar la comprensión de la arquitectura de su aplicación, y pueden ser una barrera para la reutilización de código. En particular, si usa Maven encontrará que es cíclico Las dependencias entre paquetes / entre módulos significan que todo el desastre interconectado tiene que ser un artefacto de Maven).

También me gustaría añadir que no es una gran aceptación la mejor práctica para los nombres de paquetes. Y es que los nombres de sus paquetes deben comenzar con el nombre de dominio de su organización en orden inverso. Si sigue esta regla, reduce la probabilidad de problemas causados ​​por los nombres de clase (completos) que chocan con los de otras personas.

Stephen C
fuente
9

He visto a algunas personas promocionar 'paquete por característica' sobre 'paquete por capa', pero he usado bastantes enfoques durante muchos años y he encontrado 'paquete por capa' mucho mejor que 'paquete por característica'.

Además de eso, he descubierto que una estrategia híbrida: "paquete por módulo, capa y función" funciona extremadamente bien en la práctica, ya que tiene muchas ventajas de "paquete por función":

  • Promueve la creación de marcos reutilizables (bibliotecas con aspectos de modelo y de interfaz de usuario)
  • Permite implementaciones de capa plug and play, prácticamente imposible con 'paquete por característica' porque coloca las implementaciones de capa en el mismo paquete / directorio que el código del modelo.
  • Mucho mas...

Aquí explico en profundidad: Estructura y organización del nombre del paquete de Java, pero mi estructura de paquete estándar es:

revdomain.moduleType.moduleName.layer. [layerImpl] .feature.subfeatureN.subfeatureN + 1 ...

Dónde:

revdomain com.myCompany dominio inverso por ejemplo,

moduleType [aplicación * | framework | util]

moduleName, por ejemplo, myAppName si el tipo de módulo es una aplicación o 'finanzas' si es un marco contable

capa [modelo | ui | persistencia | seguridad etc.,]

layerImpl por ejemplo, wicket, jsp, jpa, jdo, hibernate (Nota: no se usa si la capa es modelo)

característica, por ejemplo, finanzas

subfunciónN por ejemplo, contabilidad

subfunción N + 1 por ejemplo, depreciación

* A veces, la 'aplicación' se omite si moduleType es una aplicación, pero ponerla allí hace que la estructura del paquete sea coherente en todos los tipos de módulos.

Volksman
fuente
5

No conozco las prácticas estándar para la organización de paquetes. Generalmente creo paquetes que cubren un espectro razonablemente amplio, pero puedo diferenciar dentro de un proyecto. Por ejemplo, un proyecto personal en el que estoy trabajando actualmente tiene un paquete dedicado a mis controles de IU personalizados (lleno de clases subclases de clases de swing). Tengo un paquete dedicado a la gestión de mi base de datos, tengo un paquete para un conjunto de oyentes / eventos que he creado, y así sucesivamente.

Por otro lado, un compañero de trabajo creó un nuevo paquete para casi todo lo que hizo. Cada MVC diferente que deseaba tenía su propio paquete, y parecía que un conjunto de MVC era la única agrupación de clases permitidas en el mismo paquete. Recuerdo que en un momento tenía 5 paquetes diferentes, cada uno con una sola clase. Creo que su método es un poco extremo (y el equipo lo obligó a reducir el conteo de paquetes cuando simplemente no podíamos manejarlo), pero para una aplicación no trivial, también lo pondría todo en el mismo paquete. Es un punto de equilibrio que usted y sus compañeros de equipo deben encontrar por sí mismos.

Una cosa que puede hacer es intentar dar un paso atrás y pensar: si fuera un nuevo miembro introducido en el proyecto, o si su proyecto fue lanzado como código abierto o API, ¿qué tan fácil / difícil sería encontrar lo que desea? Porque para mí, eso es lo que realmente quiero de los paquetes: organización. De manera similar a como almaceno archivos en una carpeta en mi computadora, espero poder encontrarlos nuevamente sin tener que buscar en todo mi disco. Espero poder encontrar la clase que quiero sin tener que buscar en la lista de todas las clases del paquete.

Brian S
fuente