El Objetivo de la Arquitectura y el Diseño
El diseño y la arquitectura son lo mismo: su verdadera medida es el esfuerzo necesario para satisfacer al cliente minimizando el costo a largo plazo.
Por qué importa
Robert C. Martin no traza ninguna línea entre "diseño" y "arquitectura" — son la misma actividad a diferentes niveles de zoom. Los detalles de bajo nivel soportan la estructura de alto nivel; sepáralos y pierdes coherencia. La única medida de una buena arquitectura es simple: ¿cuánto esfuerzo se necesita para cumplir los requisitos actuales, y cómo crece ese esfuerzo con el tiempo? Si cada nueva funcionalidad cuesta más que la anterior, la arquitectura está fallando — independientemente de si el sistema funciona hoy.
Muchos equipos caen en la trampa de escribir software funcional primero y preocuparse por la estructura después. Pero el código desordenado crea una trampa de productividad: la velocidad cae casi a cero, los desarrolladores pasan más tiempo peleando con el código que escribiéndolo, y el negocio paga perpetuamente. Una buena arquitectura mantiene el costo del cambio constante, incluso a medida que el sistema crece.
✗El problema
A god class that handles reporting, persistence, and formatting has no architectural separation. Every new requirement touches the same class, making every change risky and expensive.
Bad
class ReportManager:
def __init__(self, db_conn):
self.db_conn = db_conn
def run(self, user_id):
row = self.db_conn.execute(
"SELECT * FROM reports WHERE user_id = ?", (user_id,)
).fetchone()
html = f"<h1>{row['title']}</h1><p>{row['body']}</p>"
self.db_conn.execute(
"UPDATE reports SET html = ? WHERE user_id = ?", (html, user_id)
)
self.db_conn.commit()
return html
class ReportManager {
constructor(private db: Database) {}
run(userId: number): string {
const row = this.db.query(
"SELECT * FROM reports WHERE user_id = ?", [userId]
);
const html = `<h1>${row.title}</h1><p>${row.body}</p>`;
this.db.execute(
"UPDATE reports SET html = ? WHERE user_id = ?", [html, userId]
);
return html;
}
}
✓La solución
Three focused classes — each with a single purpose — means each future change touches only one class. The architecture keeps the cost of change low.
Good
class ReportRepository:
def get(self, user_id: int) -> dict: ...
def save_html(self, user_id: int, html: str) -> None: ...
class ReportFormatter:
def to_html(self, row: dict) -> str:
return f"<h1>{row['title']}</h1><p>{row['body']}</p>"
class ReportService:
def __init__(self, repo: ReportRepository, fmt: ReportFormatter):
self.repo = repo
self.fmt = fmt
def generate(self, user_id: int) -> str:
row = self.repo.get(user_id)
html = self.fmt.to_html(row)
self.repo.save_html(user_id, html)
return html
class ReportRepository {
get(userId: number): ReportRow { ... }
saveHtml(userId: number, html: string): void { ... }
}
class ReportFormatter {
toHtml(row: ReportRow): string {
return `<h1>${row.title}</h1><p>${row.body}</p>`;
}
}
class ReportService {
constructor(
private repo: ReportRepository,
private fmt: ReportFormatter,
) {}
generate(userId: number): string {
const row = this.repo.get(userId);
const html = this.fmt.toHtml(row);
this.repo.saveHtml(userId, html);
return html;
}
}
💡Conclusión clave
La buena arquitectura no se trata de patrones ni palabras de moda — se trata de mantener bajo el costo del cambio durante toda la vida útil del sistema.
🔧 Algunos ejercicios pueden tener errores. Si algo parece incorrecto, usa el botón Feedback (abajo a la derecha) para reportarlo — nos ayuda a corregirlo rápido.
Pista: Cuando una clase hace demasiado, cada cambio se propaga por todas partes, aumentando el costo de cada funcionalidad.
✗ Tu versión