programacion - interfaz grafica java swing pdf
¿Cómo debería estructurar una aplicación Java? ¿Dónde pongo mis clases? (10)
Antes que nada, sé cómo construir una aplicación Java. Pero siempre me ha intrigado sobre dónde ubicar mis clases. Hay proponentes para organizar los paquetes de una manera estrictamente orientada al dominio, otros por separado.
Yo mismo siempre he tenido problemas con
- nombrar,
- colocación
Asi que,
- ¿Dónde colocas las constantes específicas de tu dominio (y cuál es el mejor nombre para dicha clase)?
- ¿Dónde colocas las clases para cosas que son tanto de infraestructura como de dominio específico (por ejemplo, tengo una clase FileStorageStrategy, que almacena los archivos en la base de datos, o alternativamente en la base de datos)?
- Dónde poner excepciones?
- ¿Hay algún estándar al que pueda referirme?
Los nombres de clase siempre deben ser descriptivos y autoexplicativos. Si tiene múltiples dominios de responsabilidad para sus clases, entonces probablemente deberían ser refactorizados.
Del mismo modo para ti paquetes. Deben agruparse por dominio de responsabilidad. Cada dominio tiene sus propias excepciones.
Por lo general, no te preocupes hasta que llegues a un punto en que se esté abrumando e hinchando. Luego siéntese y no codifique, simplemente refactorice las clases, compilando regularmente para asegurarse de que todo funcione. Luego continúa como lo hiciste antes.
Una cosa que hice en el pasado: si amplío una clase, trataré de seguir sus convenciones. Por ejemplo, cuando trabaje con Spring Framework, tendré mis clases de MVC Controller en un paquete llamado com.mydomain.myapp.web.servlet.mvc. Si no estoy ampliando algo, simplemente sigo con lo que es más simple. com.mydomain.domain para objetos de dominio (aunque si tiene un montón de objetos de dominio, este paquete podría ser un poco difícil de manejar). Para constantes específicas de dominio, las pongo como constantes públicas en la clase más relacionada. Por ejemplo, si tengo una clase "Miembro" y tengo una constante de longitud de nombre de miembro máxima, la pongo en la clase Miembro. Algunas tiendas hacen una clase de constantes separada, pero no veo el valor de agrupar números y cadenas sin relación en una sola clase. He visto otras tiendas intentar solucionar este problema creando clases SEPARATE Constants, pero eso parece una pérdida de tiempo y el resultado es demasiado confuso. Usando esta configuración, un proyecto grande con múltiples desarrolladores duplicará constantes por todas partes.
Use paquetes para agrupar la funcionalidad relacionada entre sí.
Por lo general, la parte superior de su árbol de paquetes es su nombre de dominio revertido ( com.domain.subdomain
) para garantizar la exclusividad, y generalmente habrá un paquete para su aplicación. Luego subdividir eso por área relacionada, para que su FileStorageStrategy
pueda ir, por ejemplo, com.domain.subdomain.myapp.storage
, y luego puede haber implementaciones / subclases específicas / lo que sea en com.domain.subdomain.myapp.storage.file
y com.domain.subdomain.myapp.storage.database
. Estos nombres pueden ser bastante largos, pero la import
mantiene a todos en la parte superior de los archivos y los IDE también pueden ayudar a administrarlos.
Las excepciones suelen ir en el mismo paquete que las clases que las arrojan, por lo que si tuviera, por ejemplo, FileStorageException
, iría en el mismo paquete que FileStorageStrategy
. Del mismo modo, una interfaz que define constantes estaría en el mismo paquete.
En realidad, no existe ningún estándar como tal, solo use el sentido común, y si todo se vuelve demasiado desordenado, ¡refactorícese!
Creo que es sencillo y no lo pienses más. No te abstraigas demasiado y capas demasiado. Solo mantenlo ordenado, y a medida que crece, refactorizarlo es trivial. Una de las mejores características de los IDE es la refactorización, así que, ¿por qué no utilizarla y ahorrarle capacidad mental para resolver problemas relacionados con su aplicación, en lugar de problemas meta como la organización de códigos?
Me gusta dividir mis clases en paquetes que están relacionados entre sí.
Por ejemplo: Modelo Para llamadas relacionadas con la base de datos
Ver clases que tratan con lo que ves
Clases de funcionalidad de Control Core
Util Cualquier misc. clases que se usan (típicamente funciones estáticas)
etc.
Soy un gran admirador de las fuentes organizadas, por lo que siempre creo la siguiente estructura de directorios:
/src - for your packages & classes
/test - for unit tests
/docs - for documentation, generated and manually edited
/lib - 3rd party libraries
/etc - unrelated stuff
/bin (or /classes) - compiled classes, output of your compile
/dist - for distribution packages, hopefully auto generated by a build system
In / src estoy usando los patrones predeterminados de Java: nombres de paquetes que comienzan con su dominio (org.yourdomain.yourprojectname) y nombres de clase que reflejan el aspecto OOP que está creando con la clase (vea los otros comentaristas). Los nombres comunes de paquetes como util , model , view , events también son útiles.
Tiendo a poner constantes para un tema específico en una clase propia, como SessionConstants o ServiceConstants en el mismo paquete de las clases de dominio.
Una cosa que encontré muy útil para las pruebas unitarias fue tener un directorio myApp / src / y myApp / test_src /. De esta forma, puedo colocar pruebas unitarias en los mismos paquetes que las clases que prueban, y aún puedo excluir fácilmente los casos de prueba cuando preparo mi instalación de producción.
Respuesta corta: dibuje la arquitectura de su sistema en términos de módulos, dibujados uno al lado del otro, con cada módulo dividido verticalmente en capas (por ejemplo, vista, modelo, persistencia). A continuación, utilice una estructura como com.mycompany.myapp.somemodule.somelayer , por ejemplo, com.mycompany.myapp.client.view o com.mycompany.myapp.server.model .
Usar el nivel superior de paquetes para módulos de aplicaciones, en el sentido de programación informática modular de la vieja escuela, debería ser obvio. Sin embargo, en la mayoría de los proyectos en los que he trabajado terminamos olvidándonos de hacer eso, y terminamos con un lío de paquetes sin esa estructura de primer nivel. Este antipatrón suele mostrarse como un paquete para algo así como ''oyentes'' o ''acciones'' que agrupan clases que de otro modo no estarían relacionadas simplemente porque implementan la misma interfaz.
Dentro de un módulo, o en una aplicación pequeña, use paquetes para las capas de la aplicación. Los paquetes probables incluyen cosas como las siguientes, según la arquitectura:
- com.mycompany.myapp.view
- com.mycompany.myapp.model
- com.mycompany.myapp.services
- com.mycompany.myapp.rules
- com.mycompany.myapp.persistence (o ''dao'' para la capa de acceso a datos)
- com.mycompany.myapp.util (tenga cuidado de que esto se use como si fuera ''misc'')
Dentro de cada una de estas capas, es natural agrupar clases por tipo si hay muchas. Un anti-patrón común aquí es introducir innecesariamente demasiados paquetes y niveles de subpaquetes, de modo que solo haya unas pocas clases en cada paquete.
Donde estoy trabajando, estamos usando Maven 2 y tenemos un arquetipo bastante bueno para nuestros proyectos. El objetivo era obtener una buena separación de preocupaciones, por lo que definimos una estructura de proyecto que utiliza múltiples módulos (uno para cada aplicación ''capa''): - común: código común utilizado por las otras capas (p. Ej., I18n) - entidades: el dominio entidades - repositorios: este módulo contiene las interfaces daos e implementaciones - services-intf: interfaces para los servicios (p. ej., UserService, ...) - services-impl: implementaciones de los servicios (p. ej., UserServiceImpl) - web: todo lo relacionado con el contenido web (p. ej., css, jsps, páginas jsf, ...) - ws: servicios web
Cada módulo tiene sus propias dependencias (por ejemplo, los repositorios pueden tener jpa) y algunos son de todo el proyecto (por lo tanto, pertenecen al módulo común). Las dependencias entre los diferentes módulos de proyecto separan claramente las cosas (por ejemplo, la capa web depende de la capa de servicio pero no conoce la capa de repositorio).
Cada módulo tiene su propio paquete base, por ejemplo, si el paquete de la aplicación es "com.foo.bar", entonces tenemos:
com.foo.bar.common
com.foo.bar.entities
com.foo.bar.repositories
com.foo.bar.services
com.foo.bar.services.impl
...
Cada módulo respeta la estructura del proyecto estándar maven:
src/
..main/java
.../resources
..test/java
.../resources
Las pruebas unitarias para una capa dada encuentran fácilmente su lugar bajo / src / test ... Todo lo que es específico del dominio tiene su lugar en el módulo de entidades. Ahora, algo así como una FileStorageStrategy debería entrar en el módulo de repositorios, ya que no necesitamos saber exactamente cuál es la implementación. En la capa de servicios, solo conocemos la interfaz del repositorio, no nos importa cuál es la implementación específica (separación de preocupaciones).
Existen múltiples ventajas para este enfoque:
- clara separación de preocupaciones
- cada módulo se puede empaquetar como un contenedor (o una guerra en el caso del módulo web) y, por lo tanto, permite una reutilización más sencilla del código (por ejemplo, podríamos instalar el módulo en el repositorio maven y reutilizarlo en otro proyecto)
- máxima independencia de cada parte del proyecto
Sé que esto no responde a todas sus preguntas, pero creo que esto podría ponerlo en el camino correcto y podría ser útil para otros.
Realmente me ha gustado el diseño de directorio estándar de Maven.
Una de las ideas clave para mí es tener dos raíces de origen: una para el código de producción y otra para el código de prueba, como por ejemplo:
MyProject/src/main/java/com/acme/Widget.java
MyProject/src/test/java/com/acme/WidgetTest.ava
(Aquí, src / main / java y src / test / java son raíces de origen).
Ventajas:
- Sus pruebas tienen acceso de nivel de paquete (o "predeterminado") a sus clases bajo prueba.
- Puede empaquetar fácilmente solo sus fuentes de producción en un JAR al colocar src / test / java como raíz de origen.
Una regla general sobre la ubicación de la clase y los paquetes:
En términos generales, los proyectos bien estructurados estarán libres de dependencias circulares . Aprende cuándo son malos (y cuándo no ) y considera una herramienta como JDepend o SonarJ que te ayudará a eliminarlos.