Estructura del Proyecto
Elegir una estructura de proyecto es como elegir el plano de una casa. Dicta dónde "vive" tu código y cómo socializa con los vecinos.
Veamos cómo podemos agrupar clases relacionadas en Java y cuáles son los enfoques recomendados.
A lo largo de este documento, todos los ejemplos están basados en Java. Sin embargo, los conceptos discutidos se pueden aplicar a proyectos Kotlin y Groovy.
Paquetes & la Regla de la Clase Main
Los paquetes son la forma de Java de agrupar clases (como carpetas).
Regla Crítica: Tu clase main (anotada con @SpringBootApplication) define el paquete raíz.
- Todos los demás paquetes que crees deben ser subpaquetes de esta raíz (ej., si tu clase main está en
dev.pollito.spring_java, creádev.pollito.spring_java.domain, nodev.pollito.domain). - ¿Por qué? Spring Boot escanea automáticamente clases en el paquete raíz y sus subpaquetes. Las clases afuera no serán detectadas a menos que se configuren explícitamente.
- Evitá pelear contra este default a menos que sea necesario: Spring Boot depende de esta jerarquía.
Estructura de Proyecto Default
Cuando generás un proyecto Spring Boot (más sobre cómo generar un proyecto en la sección de Spring Initializr), obtenés una estructura de carpetas y archivos estandarizada.
SpringJavaApplication.java: El punto de entrada de tu app. Anotado con@SpringBootApplicationpara habilitar autoconfiguración.application.properties(oapplication.yml): Archivo de configuración central para URLs de base de datos, puertos del servidor, logging, etc.static/ytemplates/, vacíos por defecto. Usados para assets web:pom.xml(Maven) obuild.gradle(Gradle): Define dependencias y plugins.test/: Preconfigurado para tests JUnit (Más sobre esto en la sección de Unit Testing). Tiene una clase de test esqueletoSpringJavaApplication.javaque verifica que el contexto de la app carga.
Elegiendo una Arquitectura
Imaginemos una aplicación simple que:
- Expone un endpoint REST API GET
/api/films/{filmId}. - Obtiene la información de películas de una base de datos Sakila H2.
- Complementa esos datos con información de una API externa vía FeignClient.
Toda la lógica de "Sakila" va a existir dentro del paquete sakila, representando un contexto acotado.
- En sistemas más grandes, cada dominio puede vivir en su propio paquete de nivel superior siguiendo cualquier regla arquitectónica.
Seguir Clean Architecture
- Las dependencias siempre apuntan hacia adentro.
- El dominio es la capa más independiente, y cada capa externa depende de las internas.
src/test folder se omite por simplicidad.
Seguir Hexagonal Architecture
- Actores externos interactuando con la aplicación (lado driver).
- Core de dominio implementando lógica de negocio.
- Servicios externos usados por la aplicación (lado driven).
- Los puertos (interfaces) aseguran acoplamiento flexible entre estas capas, haciendo la aplicación más mantenible y testeable.
src/test folder se omite por simplicidad.
¿Es Obligatorio Seguir una Arquitectura?
No. Spring no impone nombres ni capas. Podrías escribir todo en una sola clase. Pero estas convenciones resuelven el problema de legibilidad: los desarrolladores entienden instantáneamente una clase por su nombre.
Recomendaciones Personales
Siento que Hexagonal Architecture hace que el código sea más fácil de entender (o al menos es la que rápidamente me hizo clic). Dicho esto, no la sigo al pie de la letra, y está bien.
- Nadie realmente sigue una arquitectura al detalle: En todos lados donde trabajé intentaron seguir Clean Architecture pero se desviaron en algún punto a mitad de desarrollo y ahora es un mix sin nombre claro.
- Está bien doblar las reglas: Los proyectos pequeños pueden combinar capas.
- Consistencia > perfección: Ponganse de acuerdo con tu equipo en una estructura y mantenela. Refactorizá después si es necesario.
- Si tu equipo usa términos diferentes (ej.
DataManageren lugar deRepository), la consistencia importa más que el nombre en sí.
- Si tu equipo usa términos diferentes (ej.