Alejandría

Busca en Alejandría

Técnicas

Mapping code smells to refactoring techniques

Relaciona problemas concretos de diseño con refactorizaciones acordadas para orientar a agentes y desarrolladores.

01

En pocas palabras

Relaciona problemas concretos de diseño con refactorizaciones acordadas para orientar a agentes y desarrolladores.

Qué problema resuelve

Cambios genéricos que ignoran estándares del equipo o restricciones de sistemas heredados.

Cuándo utilizarlo

Mantenimiento y modernización. Ejemplo: asociar condicionales duplicados con una estrategia compatible con Java 8.

02

De la idea a la práctica

Funcionamiento, ejemplos y decisiones para pasar al siguiente nivel.

En el Radar compartido: Trial (valoración de la edición aportada).

Cómo funciona

Un catálogo explica síntoma, contexto, técnica recomendada y comprobación. Puede distribuirse mediante AGENTS.md, skills o reglas conectadas a linters.

Ejemplo de uso

Para una función que mezcla cálculo y persistencia, indicar «extraer el cálculo puro» y proporcionar un ejemplo del repositorio. Conservar la transacción y verificar casos de negocio antes y después.

Catálogo base de olores y refactorizaciones

Olor Síntoma Refactorización habitual
Función larga Hay que leer mucho para entender qué hace Extract Function, Decompose Conditional
Clase grande Muchas responsabilidades y campos Extract Class
Lista larga de parámetros Llamadas con 6 argumentos posicionales Introduce Parameter Object, Preserve Whole Object
Obsesión por primitivos String para documento, double para dinero Replace Primitive with Object
Agrupaciones de datos Los mismos tres campos viajan juntos siempre Extract Class, Introduce Parameter Object
Envidia de funcionalidad Un método usa más datos de otra clase que de la suya Move Function
Switch repetidos El mismo switch (tipoProducto) en varios sitios Replace Conditional with Polymorphism
Cirugía de escopeta Un cambio exige tocar muchos archivos Move Function, Combine Functions into Class
Cambio divergente Una clase cambia por motivos distintos Split Phase, Extract Class
Código duplicado Mismo fragmento en varios lugares Extract Function, Pull Up Method
Cadenas de mensajes a.getB().getC().getD() Hide Delegate
Generalidad especulativa Abstracciones sin un segundo uso Inline Function, Collapse Hierarchy
Datos mutables globales Cualquier parte puede cambiar el estado Encapsulate Variable

Ejemplo: obsesión por primitivos

// Antes: el dinero es un double y la moneda un String suelto
double calcularCuota(double monto, String moneda, double tasaMensual, int plazo) { … }

// Después: un value object con invariantes y aritmética exacta
public record Dinero(BigDecimal valor, Currency moneda) {
    public Dinero {
        if (valor.scale() > moneda.getDefaultFractionDigits())
            throw new IllegalArgumentException("Demasiados decimales para " + moneda);
    }
    public Dinero por(BigDecimal factor) {
        return new Dinero(valor.multiply(factor).setScale(moneda.getDefaultFractionDigits(), RoundingMode.HALF_EVEN), moneda);
    }
}
Dinero calcularCuota(Dinero monto, TasaMensual tasa, Plazo plazo) { … }

Además de eliminar errores de redondeo, el compilador impide pasar un plazo donde se esperaba una tasa.

Formato del catálogo para agentes

## Obsesión por primitivos en importes

- **Detectar**: parámetros o campos `double`/`float` con nombres como monto, saldo, cuota.
- **Aplicar**: usar `Dinero` (`com.krediya.core.Dinero`). Ver ejemplo en `CuotaService`.
- **No aplicar**: DTOs de entrada/salida JSON (se convierten en el borde).
- **Verificar**: pruebas de `CalculoCuotaTest` con importes de 2 decimales y redondeo HALF_EVEN.
- **Tamaño máximo**: un agregado por PR.

Este formato (detectar, aplicar, excepciones, verificación, límite) funciona igual para personas y agentes. Puede vivir en AGENTS.md, en una skill o en reglas de linters.

Detección automática

Herramienta Qué aporta
SonarQube, PMD, ESLint, Ruff Reglas de complejidad, tamaño, duplicación
CodeScene Hotspots: olores en código que cambia mucho
ArchUnit y similares Dependencias entre módulos (fitness functions)
OpenRewrite Algunas refactorizaciones automáticas y seguras

Prioriza los olores en código que cambia a menudo (gestión de deuda técnica): refactorizar código estable rara vez compensa.

Disciplina de refactorización

  • Refactorizar es cambiar la estructura sin cambiar el comportamiento: separa los commits de refactorización de los de funcionalidad.
  • Pasos pequeños con las pruebas en verde después de cada uno; TCR lleva esta disciplina al extremo.
  • Usa las refactorizaciones automáticas del IDE siempre que existan: son más seguras que editar a mano.

Criterios de implementación

Precisar excepciones, versiones del lenguaje y límites de tamaño del cambio. Usar pruebas de caracterización cuando el comportamiento existente no está documentado.

Continúa en las fuentes

Documentación oficial para verificar detalles y explorar más.