Tot sistema acumula, amb el temps, decisions de disseny que en el seu moment van ser ràpides o convenients però que dificulten el canvi futur. A aquesta escletxa entre l'estat ideal del codi i el seu estat real se l'anomena deute tècnic, una metàfora financera encunyada per Ward Cunningham: igual que un deute monetari, genera "interessos" en forma de més esforç en cada modificació. El deute no és intrínsecament dolent —de vegades és una decisió estratègica assenyada— però ignorar-lo porta a la paràlisi. En aquesta lliçó estudiarem què és exactament, com classificar-lo amb el quadrant de Fowler, com mesurar-lo i quines estratègies existeixen per pagar-lo, amb la refactorització contínua com a pràctica central.
Contingut
- Què és el deute tècnic i la metàfora financera
- El quadrant de deute tècnic de Fowler
- Tipus i causes de deute tècnic
- Com mesurar el deute tècnic
- Estratègies de pagament del deute
- Refactorització contínua
- Errors comuns i consells
- Exercicis
- Conclusió
- Què és el deute tècnic i la metàfora financera
El deute tècnic és el cost implícit futur de refer feina causat per triar una solució limitada o ràpida ara en lloc d'un enfocament millor que portaria més temps.
La metàfora financera té tres conceptes clau:
- Principal: l'esforç necessari per corregir el problema (refactoritzar, redissenyar).
- Interès: el cost extra que pagues en cada canvi mentre el deute existeixi (més lentitud, més bugs).
- Palanquejament: de vegades endeutar-se permet lliurar valor abans i "tornar-lo" després; pot ser una decisió racional.
graph LR
A[Decisió ràpida] --> B[Deute tècnic]
B --> C[Interès: cada canvi costa més]
C --> D{Es paga?}
D -->|Sí| E[Principal saldat: codi sa]
D -->|No| F[Interès compost: paràlisi]Explicació del diagrama: una decisió ràpida crea deute; mentre no se salda el principal, s'acumula interès en cada modificació. Si no es gestiona, l'interès es compon fins a fer el sistema gairebé immodificable.
- El quadrant de deute tècnic de Fowler
Martin Fowler va proposar un quadrant que classifica el deute segons dos eixos: si es va contreure de manera deliberada o inadvertida, i si va ser prudent o imprudent. Això matisa el judici moral sobre el deute.
| Imprudent | Prudent | |
|---|---|---|
| Deliberat | "No tenim temps per al disseny" | "Lliurem ja i n'assumim les conseqüències" |
| Inadvertit | "Què és una capa?" | "Ara sabem com ho hauríem d'haver fet" |
Interpretació de cada quadrant:
- Deliberat i imprudent: se sap com fer-ho bé però es decideix no fer-ho per deixadesa. El més perillós.
- Deliberat i prudent: decisió conscient i justificada (llançar abans per validar mercat), amb pla de pagament. Acceptable.
- Inadvertit i imprudent: manca de coneixement o disciplina; l'equip ni tan sols sap que està generant deute. Es combat amb formació.
- Inadvertit i prudent: el deute de l'aprenentatge natural; només en acabar entens el domini. Inevitable i sa.
La lliçó del quadrant és que el deute prudent i gestionat pot ser una eina estratègica; l'imprudent és un problema de disciplina o coneixement.
- Tipus i causes de deute tècnic
| Tipus de deute | Exemple |
|---|---|
| De codi | Codi duplicat, mètodes enormes, noms confusos |
| De disseny/arquitectura | Acoblament alt, absència de capes, dependències circulars |
| De proves | Cobertura insuficient, tests fràgils |
| De documentació | Documentació obsoleta o inexistent |
| D'infraestructura | Versions de llibreries sense actualitzar, entorns manuals |
| De dependències | Biblioteques obsoletes amb vulnerabilitats |
Causes habituals:
- Pressió de terminis i lliuraments precipitats.
- Manca de coneixement o experiència de l'equip.
- Canvis de requisits que invaliden decisions prèvies.
- Absència de temps dedicat a manteniment.
- Rotació de personal i pèrdua de context.
- Com mesurar el deute tècnic
El deute és en part intangible, però existeixen indicadors quantificables. Les eines d'anàlisi estàtica (com SonarQube) calculen mètriques i un ràtio de deute tècnic.
Mètriques habituals:
- Code smells i issues de mantenibilitat detectats automàticament.
- Complexitat ciclomàtica: nombre de camins independents d'un mètode; com més gran, més difícil de provar i mantenir.
- Duplicació de codi (percentatge).
- Cobertura de proves.
- Technical Debt Ratio (TDR): cost estimat de remediació dividit pel cost de desenvolupament.
# Exemple de configuració de quality gate a SonarQube
sonar.qualitygate:
conditions:
- metric: new_coverage # cobertura del codi nou
op: LESS_THAN
error: 80 # falla si <80%
- metric: new_duplicated_lines_density
op: GREATER_THAN
error: 3 # falla si >3% de línies duplicades
- metric: new_technical_debt # deute introduït per aquest canvi
op: GREATER_THAN
error: 60 # falla si afegeix més de 60 min de deuteExplicació: aquest quality gate impedeix que el codi nou degradi la salut del projecte. En lloc d'exigir netejar tot el deute històric de cop (inviable), aplica l'enfocament "Clean as You Code": el codi nou ha de complir l'estàndard, tot contenint el deute en el seu origen.
Indicadors indirectes valuosos:
- Velocitat de l'equip decreixent sense causa aparent.
- Taxa de defectes creixent.
- Lead time (temps des del commit fins a producció) en augment.
- Estratègies de pagament del deute
No tot el deute s'ha de pagar, ni de la mateixa manera. Estratègies principals:
| Estratègia | En què consisteix | Quan fer-la servir |
|---|---|---|
| Pagament incremental | Millorar una mica amb cada canvi (Boy Scout Rule) | Per defecte, sempre |
| Refactorització dedicada | Reservar capacitat del sprint a saldar deute | Deute localitzat i conegut |
| Reescriptura parcial | Reescriure un mòdul concret | Mòdul crític inmanejable |
| Reescriptura total | Refer el sistema | Últim recurs, molt arriscat |
| Tolerar el deute | No fer res conscientment | Codi estable que no es toca |
Priorització: paga primer el deute que és en zones d'alt canvi i alt impacte. El deute en codi que mai no es modifica genera poc interès; no val la pena saldar-lo. Una matriu útil creua "freqüència de canvi" amb "dolor que causa".
Recomanacions de gestió:
- Fer el deute visible (backlog, etiquetes, registre de deute tècnic).
- Assignar una capacitat fixa (p. ex. 15-20% de cada iteració) al manteniment.
- Acompanyar cada pagament de proves que protegeixin el comportament.
- Refactorització contínua
La refactorització és millorar l'estructura interna del codi sense canviar-ne el comportament extern. Contínua significa fer-la en petits passos constants, no en grans projectes esporàdics.
Regla d'or: refactoritzar sempre sota la xarxa de seguretat de les proves. Sense tests, no és refactorització, és risc.
// ABANS: mètode llarg, amb diverses responsabilitats i difícil de seguir
public double procesarPedido(Pedido p) {
double total = 0;
for (Linea l : p.getLineas()) {
total += l.getPrecio() * l.getCantidad();
}
if (p.getCliente().esVip()) {
total = total * 0.9;
}
if (total > 100) {
total = total; // enviament gratis
} else {
total = total + 5;
}
return total;
}// DESPRÉS: extracció de mètodes amb noms expressius
public double procesarPedido(Pedido p) {
double subtotal = calcularSubtotal(p);
double conDescuento = aplicarDescuentoVip(p, subtotal);
return aplicarEnvio(conDescuento);
}
private double calcularSubtotal(Pedido p) {
return p.getLineas().stream()
.mapToDouble(l -> l.getPrecio() * l.getCantidad())
.sum();
}
private double aplicarDescuentoVip(Pedido p, double subtotal) {
return p.getCliente().esVip() ? subtotal * 0.9 : subtotal;
}
private double aplicarEnvio(double total) {
return total > 100 ? total : total + 5;
}Explicació de la refactorització: apliquem Extract Method per separar cada responsabilitat (subtotal, descompte, enviament) en un mètode amb nom clar. El comportament extern no canvia —per això és segur si hi ha tests—, però el mètode principal ara es llegeix com una descripció del procés. Això redueix el deute de codi i la complexitat ciclomàtica.
Refactoritzacions freqüents: extreure mètode, reanomenar, extreure classe, reemplaçar condicionals per polimorfisme, introduir paràmetre objecte. Els IDE moderns les automatitzen de manera segura.
Errors Comuns i Consells
- Refactoritzar sense proves. És la causa més comuna d'introduir bugs en "millorar" el codi. Primer la xarxa de seguretat.
- Barrejar refactorització amb canvis funcionals en el mateix commit. Separa'ls: si alguna cosa falla, no sabràs si va ser la millora o la nova funció.
- Esperar al "gran refactor" o la reescriptura total. Gairebé sempre fracassa o mai no arriba. El deute es gestiona de manera contínua i incremental.
- Tractar tot el deute per igual. Prioritza per impacte i freqüència de canvi; ignorar això malgasta esforç en codi mort.
- No fer visible el deute. El que no es mesura ni es registra, no es gestiona. Fes servir el backlog i mètriques.
- Confondre refactoritzar amb reescriure. Refactoritzar preserva el comportament en passos petits; reescriure parteix de zero i és molt més arriscat.
- Consell: adopta "Clean as You Code" per no degradar el que és nou i la Boy Scout Rule per millorar el que toques.
Exercicis
Exercici 1. Classifica en el quadrant de Fowler les situacions següents: a) "Llancem l'MVP amb persistència en fitxers per validar el negoci i migrarem a BD si funciona." b) "Vaig copiar i enganxar el mòdul perquè no sabia que existien les interfícies."
Exercici 2. Tens deute tècnic en dos mòduls: un que es modifica gairebé cada setmana i un altre que no es toca des de fa dos anys. Amb recursos limitats, quin prioritzes i per què?
Exercici 3. Refactoritza aquest mètode extraient responsabilitats (suposant que existeixen proves):
public String generarSaludo(Usuario u) {
String s = "";
if (u.getEdad() < 18) s = "Hola joven "; else s = "Estimado/a ";
s = s + u.getNombre();
if (u.isPremium()) s = s + " (cliente premium)";
return s;
}Solucions
Solució 1. a) Deliberat i prudent: decisió conscient i justificada, amb pla de pagament (migrar si el negoci funciona). És un deute estratègic acceptable. b) Inadvertit i imprudent: es genera per desconeixement del disseny. Es combat amb formació i revisió de codi.
Solució 2. Prioritzes el mòdul que es modifica cada setmana. El deute genera "interès" en cada canvi; en un mòdul d'alt canvi aquest interès es paga constantment, així que saldar-lo té un retorn alt. El mòdul congelat des de fa dos anys genera poc o gens d'interès: tolerar-ne el deute és el correcte mentre no s'hagi de tocar.
Solució 3. Extraiem cada decisió a un mètode amb nom expressiu:
public String generarSaludo(Usuario u) {
return tratamiento(u) + u.getNombre() + distintivoPremium(u);
}
private String tratamiento(Usuario u) {
return u.getEdad() < 18 ? "Hola joven " : "Estimado/a ";
}
private String distintivoPremium(Usuario u) {
return u.isPremium() ? " (cliente premium)" : "";
}El comportament es preserva, però el mètode principal expressa la intenció i cada regla queda aïllada i testejable.
Conclusió
El deute tècnic és inevitable, però gestionar-lo és una decisió. Hem vist que la metàfora financera (principal i interès) explica per què el deute ignorat es torna paralitzant, i que el quadrant de Fowler ens ajuda a distingir el deute estratègic del negligent. Hem après a mesurar-lo amb mètriques i quality gates sota l'enfocament "Clean as You Code", a prioritzar-ne el pagament segons impacte i freqüència de canvi, i a saldar-lo mitjançant refactorització contínua sota la protecció de les proves. Amb aquesta lliçó tanquem el Mòdul 2 de principis i tàctiques de disseny: disposes ara d'un marc complet —des de l'acoblament i la cohesió fins a la gestió del deute— per prendre decisions de disseny conscients. El mòdul següent farà el salt als estils i patrons arquitectònics que estructuren sistemes complets.
Curs d'Arquitectura d'Aplicacions
Mòdul 1: Fonaments de l'Arquitectura d'Aplicacions
- Què és l'Arquitectura d'Aplicacions?
- El Rol de l'Arquitecte de Programari
- Atributs de Qualitat i Requisits No Funcionals
- Decisions Arquitectòniques i Compromisos (Trade-offs)
- Documentació d'Arquitectura: Vistes i el Model C4
Mòdul 2: Principis i Tàctiques de Disseny
- Acoblament, Cohesió i Separació de Responsabilitats
- Principis SOLID Aplicats a l'Arquitectura
- DRY, KISS, YAGNI i Altres Principis de Disseny
- Tàctiques Arquitectòniques per als Atributs de Qualitat
- Gestió del Deute Tècnic
Mòdul 3: Estils i Patrons Arquitectònics
- Arquitectura Monolítica
- Arquitectura en Capes (N-Tier)
- Arquitectura Client-Servidor
- Arquitectura Hexagonal (Ports i Adaptadors)
- Arquitectura Neta i Ceba (Clean & Onion)
Mòdul 4: Arquitectures Distribuïdes i Microserveis
- Introducció als Sistemes Distribuïts
- Arquitectura de Microserveis
- Descomposició de Serveis i Bounded Contexts
- API Gateway, Service Discovery i Comunicació entre Serveis
- Patrons de Resiliència: Circuit Breaker, Retry i Bulkhead
- El Teorema CAP i la Consistència de Dades
Mòdul 5: Arquitectures Dirigides per Esdeveniments i Missatgeria
- Fonaments de l'Arquitectura Orientada a Esdeveniments
- Missatgeria Asíncrona: Cues i Brokers
- Patrons d'Esdeveniments: Event Sourcing i CQRS
- Gestió de Transaccions Distribuïdes: Patró Saga
- Streaming de Dades en Temps Real
Mòdul 6: Disseny Dirigit pel Domini (DDD)
- Conceptes Fonamentals del DDD
- Disseny Estratègic: Bounded Contexts i Llenguatge Ubic
- Disseny Tàctic: Entitats, Agregats i Repositoris
- Mapatge de Contextos (Context Mapping)
Mòdul 7: Dades i Persistència
- Estratègies de Persistència: SQL vs NoSQL
- Patrons d'Accés a Dades: Repository, Unit of Work i DAO
- Base de Dades per Servei i Gestió de Dades Distribuïdes
- Cau i Estratègies d'Invalidació
Mòdul 8: Arquitectura al Núvol i Desplegament
- Fonaments del Cloud Computing (IaaS, PaaS, SaaS)
- Contenidors i Orquestració amb Docker i Kubernetes
- Arquitectura Serverless
- Patrons de Disseny Cloud-Native
- Infraestructura com a Codi (IaC)
Mòdul 9: Qualitat, Seguretat i Observabilitat
- Escalabilitat: Horitzontal vs Vertical i Balanceig de Càrrega
- Alta Disponibilitat i Tolerància a Fallades
- Seguretat per Disseny i Autenticació/Autorització
- Observabilitat: Logging, Mètriques i Traçabilitat
- Rendiment i Proves de Càrrega
