Cambias una condición y la revisión acaba mostrando veinte líneas de sangrías, saltos y paréntesis. Otra persona abre el archivo con su configuración y lo deja distinto. La condición sigue esperando su turno mientras discutimos dónde poner una llave.
Un estándar compartido reduce ese ruido: acordamos cómo presentar el código y reunimos las reglas en un perfil que guardamos en el proyecto. Una comprobación automática avisa al desarrollador antes de guardar el cambio en Git; el servidor vuelve a comprobarlo cuando lo recibe. Así, todo el equipo trabaja con el mismo criterio, aunque utilice editores diferentes.
Vamos a recorrer esa solución en Job Application Tracker modular, un taller Java para gestionar candidaturas de empleo. La cuestión es concreta: cómo convertir un acuerdo de estilo en una comprobación reproducible, desde el equipo del desarrollador hasta la revisión del cambio en GitHub.
Qué comprueba el análisis estático
El análisis estático inspecciona el código sin ejecutar las operaciones de la aplicación. Para detectar una llave mal colocada no hace falta arrancar el gestor ni registrar una candidatura. Una prueba funcional, en cambio, ejecuta una operación y contrasta su resultado.
Aquí nos centramos en el estilo. Utilizamos tres piezas:
| Pieza | Responsabilidad en el taller |
|---|---|
| Spotless con Eclipse JDT | Aplica el formato acordado o comprueba si el código necesita reformatearse. |
| Checkstyle | Señala infracciones de reglas concretas, como la posición de las llaves o los imports con comodines. |
| Maven | Ejecuta ambas comprobaciones con la configuración y las versiones guardadas en el proyecto. |
El formateador puede corregir la presentación del código. El linter, aquí Checkstyle, informa de incumplimientos de las reglas configuradas. Maven reúne sus resultados: si una comprobación falla, el comando termina con error. No necesitamos que cada desarrollador reproduzca estas decisiones en su IDE, el editor o entorno con el que programa.
De una regla a un resultado concreto
El taller guarda cuántas candidaturas hay en cada estado. Imaginemos dos enviadas y cuatro rechazadas. El método of recibe un estado y consulta su cantidad en el mapa byStatus: para APPLIED, que representa las enviadas, devuelve 2.
Este fragmento muestra la disposición anterior, que incumple la nueva regla del proyecto sobre las llaves de los métodos:
public long of(Status status) {
return byStatus.get(status);
}
El equipo ha acordado que esa llave empiece en la línea siguiente. Al comprobar el archivo, Spotless muestra las diferencias de formato y Maven termina con error. El perfil de Checkstyle recoge también esa regla sobre la posición de la llave.
Aplicamos el formateador y el método queda así:
public long of(Status status)
{
return byStatus.get(status);
}
La nueva comprobación acepta esa disposición. La consulta sigue devolviendo dos candidaturas enviadas: hemos cambiado el formato, conservando las operaciones del método. Las pruebas funcionales siguen siendo las encargadas de comprobar su comportamiento.
Este es el mecanismo que queremos repetir con el resto del perfil: regla explícita, comprobación, aviso concreto y corrección verificable.
Elegir un estándar y concretar el acuerdo
Cada lenguaje tiene convenciones propias. En Java encontramos la Google Java Style Guide; en Python, PEP 8; en PHP, PER Coding Style. Adoptar una guía conocida reduce decisiones y facilita que otros desarrolladores reconozcan la organización del código.
También conviene comprobar su vigencia. Las convenciones históricas de Sun conservadas por Oracle están archivadas y su última revisión es de 1999. Sirven como referencia histórica, pero no cubren todo el Java actual.
Clean Code, de Robert C. Martin, aporta criterios sobre nombres, funciones, comentarios y formato. Para automatizar los que afectan al estilo tenemos que traducirlos a reglas precisas. El libro no proporciona un perfil universal que certifique toda la calidad del código.
En este taller hemos creado Clean Code - Project Style 1.0, un perfil propio inspirado en esos criterios. La llave de los métodos en la línea siguiente es una decisión del proyecto. Sus reglas difieren de Google Java Style y están documentadas para que el equipo pueda aplicarlas y revisarlas.
| Acuerdo del perfil | Comprobación |
|---|---|
| Cuatro espacios por nivel y para las continuaciones | Formateador y Spotless |
Hasta 120 columnas, salvo package e imports |
Formateador y Checkstyle |
| Llaves de métodos y constructores en la línea siguiente | Formateador y Checkstyle |
| Llaves de clases y estructuras de control junto a su cabecera | Formateador y Checkstyle |
| Una llamada por línea cuando una cadena necesita varias líneas; cierres separados en llamadas multilínea | Formateador y Spotless |
| Imports explícitos, sin comodines ni imports sin usar | Spotless y Checkstyle |
| Separación entre miembros, espaciado y convenciones de nombres | Formateador y Checkstyle |
La claridad de un nombre sigue requiriendo lectura humana. Una herramienta puede comprobar que empieza en minúscula; decidir si processData explica su intención exige conocer la operación. También corresponde al autor separar con líneas en blanco las fases lógicas de un método. El formateador conserva esa separación.
Dónde viven las reglas
El proyecto guarda el formato en config/eclipse-formatter.xml y las reglas de Checkstyle en config/checkstyle-clean-code.xml. El pom.xml, donde Maven configura la construcción del proyecto, fija las versiones y ordena ejecutar las comprobaciones en la fase validate, incluyendo fuentes y pruebas Java de todos los módulos.
Esta regla nativa de Checkstyle concreta el ejemplo anterior:
<module name="LeftCurly">
<property name="id" value="methodAndConstructorBraces"/>
<property name="option" value="nl"/>
<property name="tokens" value="METHOD_DEF,CTOR_DEF,COMPACT_CTOR_DEF"/>
</module>
LeftCurly comprueba la posición de la llave; nl exige una línea nueva. Los tipos de elemento indicados limitan esa regla a métodos y constructores. Otra instancia comprueba la disposición elegida para clases y estructuras de control.
Utilizamos reglas existentes de Checkstyle y la integración de Spotless con Eclipse JDT. Aunque el motor de formato proceda de Eclipse, Maven lo ejecuta sin abrir ese IDE.
La indentación exacta tiene una única autoridad: el formateador. Así evitamos superponer otro algoritmo que pueda rechazar la distribución que el propio perfil exige.
La misma comprobación durante el trabajo
El recorrido tiene dos controles automáticos. El precommit es el hook, o acción automática de Git, que comprueba el cambio antes de crear el commit: el registro del cambio en el repositorio. El código preparado es la parte que hemos seleccionado para guardar en ese commit. Después, GitHub Actions vuelve a comprobarlo en CI, la integración continua, al recibir el código.
En GitHub, una pull request propone integrar un cambio y reúne su revisión y los resultados de las comprobaciones. El control de estilo aparece allí como Verify / Code style. Si falla, el desarrollador corrige el código y lo vuelve a enviar.

Las flechas muestran el recorrido del cambio. El bloque de CI representa el check de estilo; la revisión humana evalúa después la intención y las responsabilidades del código. El diagrama no representa las pruebas funcionales, que tienen su propia ejecución.
Comprobar y corregir en local
Desde la raíz del taller, con Docker en ejecución:
docker compose -f compose.style.yaml run --rm --no-deps check
Este servicio ejecuta mvn validate en una imagen fijada por etiqueta y digest. Docker proporciona el entorno compartido; no arranca la aplicación ni su base de datos. La primera ejecución puede descargar dependencias.
Para aplicar el formato:
docker compose -f compose.style.yaml run --rm --no-deps format
Después revisamos las diferencias y repetimos check. Mantener la migración de formato separada de los cambios de comportamiento facilita esa revisión.
Instalar el precommit en cada clon
El archivo .pre-commit-config.yaml conecta el hook con el mismo servicio check. Lo activa al preparar Java, POM o configuraciones de estilo, y Maven comprueba todos los módulos. El hook informa y puede rechazar el commit; la corrección del formato se ejecuta de forma explícita.
La configuración versionada necesita instalarse en cada copia local del repositorio. En PowerShell:
python -m venv .venv-style
.\.venv-style\Scripts\python.exe -m pip install -r requirements-style.txt
.\.venv-style\Scripts\python.exe -m pre_commit install
.\.venv-style\Scripts\python.exe -m pre_commit run --all-files
Python instala pre-commit, una herramienta de desarrollo; la aplicación sigue siendo Java. La guía del taller incluye los comandos para Linux y macOS y la alternativa con Maven Wrapper.
Pre-commit aparta temporalmente los cambios no preparados de archivos seguidos, comprueba el contenido preparado para el commit y los restaura después. Esto permite revisar también un cambio cuando solo queremos incorporar parte de un archivo.
Ver el resultado en la pull request
Un hook local puede omitirse. Por eso el workflow Verify, el conjunto de tareas automatizadas de GitHub Actions, incluye un job o tarea independiente llamado Code style:
jobs:
code-style:
name: Code style
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false
- name: Check Java style with Spotless and Checkstyle
run: docker compose -f compose.style.yaml run --rm --no-deps check
El job descarga el código y ejecuta el mismo comando de comprobación. En la pull request vemos Verify / Code style y Verify / tests por separado: podemos identificar una infracción de estilo sin confundir su resultado con el de las pruebas.
Los dos jobs pueden ejecutarse en paralelo porque no hay una dependencia entre ellos. El workflow completo se activa tanto en las subidas (push) como en las pull requests (pull_request), por lo que GitHub puede mostrar ambas ejecuciones.
Para exigir que el check pase antes de fusionar, el equipo debe seleccionarlo como obligatorio en las reglas de protección de la rama.
Comprobar que las reglas detectan infracciones
Pasar sobre código correcto es solo una parte de la comprobación del perfil. Introdujimos infracciones temporales en la posición de las llaves, la sangría, la distribución de cadenas de llamadas, la separación de miembros y los imports. El perfil las rechazó. También comprobamos que el hook distinguía el contenido preparado de un cambio incorrecto dejado sin preparar en el mismo archivo.
Al aplicar el formato al taller contrastamos la representación sintáctica del Java antes y después, incluidos los valores de los textos del código, como las consultas SQL. Esa comprobación revisa la migración de formato; las pruebas funcionales mantienen su responsabilidad sobre el comportamiento.
La implementación del taller reúne las reglas y su automatización. A partir de ahí, cada cambio de estilo se puede contrastar con un acuerdo concreto. La revisión de una condición puede centrarse en qué hace esa condición y en si expresa con claridad la regla del negocio.