Mejora la calidad
de tu código
Micro-lecciones de código limpio, patrones de diseño y arquitectura limpia — con ejemplos en Python y TypeScript.
Elige tu lenguaje. Una micro-lección a la vez — 5 a 12 minutos cada una.
Elige tu lenguaje
Los desarrolladores pasan 10 veces más tiempo leyendo código que escribiéndolo. — Robert C. Martin
Calistenia de Objetos
Nueve reglas para transformar cómo escribes código orientado a objetos.
9 leccionesCódigo Limpio
Escribe código legible y mantenible que otros desarrolladores amarán.
47 leccionesPatrones de Diseño
Soluciones reutilizables para problemas comunes de diseño de software.
23 leccionesArquitectura Limpia
Estructura sistemas para que la lógica de negocio sea independiente de frameworks.
50 leccionesTodas las lecciones
Calistenia de Objetos
Usa Colecciones de Primera Clase
Cualquier clase que contenga una colección no debe tener otras variables miembro — envolver las colecciones da a los filtros, ordenaciones y reglas un hogar semántico y cohesivo.
Mantén Todas las Entidades Pequeñas
Ninguna clase supera 50 líneas, ningún paquete supera 10 archivos — las clases pequeñas caben en una pantalla, fuerzan el enfoque y se organizan naturalmente en paquetes cohesivos.
No Abrevies
Las abreviaciones enmascaran problemas más profundos — si un nombre es demasiado largo para escribir completo, el método tiene demasiadas responsabilidades. Los nombres deben ser una o dos palabras claras.
No Uses la Palabra Clave Else
Reemplaza if/else con cláusulas de guarda y retornos tempranos — else es generalmente señal de un flujo poco claro que puede simplificarse en una secuencia directa.
No Uses Getters/Setters/Properties
Di, no preguntes — en lugar de obtener datos para tomar decisiones fuera del objeto, dile al objeto qué hacer y déjalo usar sus propios datos.
Un Punto por Línea
Basado en la Ley de Deméter — no atravieses las partes internas de un objeto. Pide al objeto que haga el trabajo en lugar de navegar sus partes.
Un Nivel de Indentación por Método
Cada método debe hacer una sola cosa a un nivel de abstracción — las estructuras de control anidadas son señal de extraer un método.
Sin Clases con Más de Dos Variables de Instancia
Limitar el estado a dos variables de instancia aumenta drásticamente la cohesión — si necesitas más, descompón en una jerarquía de objetos colaboradores.
Envuelve Todos los Primitivos y Cadenas
Un int o string primitivo no tiene significado de dominio — envolverlo en una clase como Money o Email permite al compilador hacer cumplir la intención y da un hogar natural al comportamiento.
Código Limpio
Organización de Clases
Las clases deben ser pequeñas, enfocadas y tener una única razón para cambiar.
La Mentalidad del Código Limpio
Por qué el código limpio es una disciplina profesional — y cómo el código sucio destruye silenciosamente equipos y empresas.
Estrategias de Concurrencia Limpia
Escribe código concurrente que sea correcto, legible y libre de sutiles errores de carrera de datos.
Manejo Limpio de Errores
El manejo de errores es una preocupación separada — mantenla aislada para que tu algoritmo principal sea legible.
Pruebas Unitarias Limpias
Las pruebas son código de primera clase — las pruebas sucias son tan costosas de mantener como el código de producción.
Heurísticas de Comentarios
Identifica y elimina los malos comentarios; escribe el raro bueno con precisión.
Concurrencia: Modelo Cliente-Servidor
Estructura sistemas concurrentes cliente-servidor para aislar el estado compartido y evitar sutiles errores de hilos.
Concurrencia: Deadlock y Inanición
Reconoce y elimina las cuatro condiciones que producen deadlock en sistemas concurrentes.
Interbloqueo: Las 4 Condiciones
Un interbloqueo requiere las cuatro condiciones de Coffman simultáneamente — rompe cualquiera y el interbloqueo se vuelve imposible.
Concurrencia: Pruebas con Jiggle
Las condiciones de carrera se esconden en brechas de tiempo — agitar el orden de ejecución con yields aleatorios y ejecuciones multiplataforma las expone.
No Te Repitas
🔒Cada pieza de conocimiento debe tener una única representación autorizada en el código.
Duplicación y Abstracción
🔒Reconoce la duplicación oculta y elige la abstracción correcta para eliminarla.
La Filosofía 5S en el Código
🔒Cómo la filosofía 5S de manufactura de Toyota se traduce en artesanía de software profesional.
Análisis de Frameworks
🔒Entiende lo que hace un framework antes de usarlo — lee el código fuente, no solo la documentación.
Heurísticas de Funciones
🔒Aplica las heurísticas F1–F4 para mantener las funciones mínimas, enfocadas y sin efectos secundarios.
Niveles de Abstracción y Dependencias
🔒Mantén la política de alto nivel separada del detalle de bajo nivel, y asegura que las clases base nunca dependan de las derivadas.
Coherencia y Claridad
🔒Aplica el mismo patrón en todas partes, evita el desorden conceptual y nunca acoplas preocupaciones no relacionadas.
Convenciones y Números Mágicos
🔒Sigue los estándares de codificación del equipo de forma religiosa y reemplaza cada literal mágico con una constante nombrada.
Entorno y Verdad
🔒Construye sistemas que compilen en un paso, ejecuten todas las pruebas en un paso, y nunca mientan a través de advertencias suprimidas.
Expresividad y Algoritmos
🔒Usa variables explicativas, nombres precisos y un profundo entendimiento del algoritmo para que el código hable por sí mismo.
Envidia de Características
🔒Un método que pasa la mayor parte de su tiempo leyendo los datos de otra clase pertenece a esa clase.
Lógica y Polimorfismo
🔒Haz explícitas todas las dependencias y reemplaza las cadenas if/switch con despacho polimórfico.
Ruido y Organización
🔒Elimina información excesiva, código muerto y distancia vertical para que cada archivo sea fácil de escanear.
Ubicación y Estáticos
🔒Pon cada función en la clase más interesada en ella, y mantén los métodos estáticos como utilidades verdaderamente sin estado.
Selectores e Intención
🔒Los argumentos selectores booleanos y de enumeración oscurecen la intención — divídelos en funciones enfocadas y bien nombradas.
Resumen del Catálogo de Heurísticas
🔒Un catálogo curado de malos olores de código y heurísticas de refactorización extraídas del capítulo 17 de Clean Code.
G16: La Intención Oscurecida
🔒El código que intenta ser inteligente es código que falla en comunicar — la densidad y brevedad a costa de la claridad no son virtudes.
G21: Comprender el Algoritmo
🔒Que las pruebas pasen no equivale a entender — el código limpio exige que comprendas completamente por qué funciona el algoritmo antes de confirmarlo.
G22: Dependencias Lógicas a Físicas
🔒Nunca permitas que un módulo asuma silenciosamente un valor de otro — haz que cada dependencia sea explícita y declarada en el código.
Heurísticas Específicas de Java (J1–J3)
🔒Tres heurísticas enfocadas en Java: evita importaciones con comodines, nunca heredes constantes, y prefiere enumeraciones sobre constantes enteras.
Refactorización de Código Legado
🔒Transforma código legado enredado de forma segura añadiendo pruebas primero y refactorizando en pequeños pasos.
El Arte de Nombrar
🔒Escribe nombres que revelen la intención, eviten la confusión y hagan el código buscable.
Heurísticas de Nombres
🔒Aplica las heurísticas N1–N7 para escribir nombres precisos, sin ambigüedad y fáciles de buscar.
El Mal Necesario de los Comentarios
🔒El código es la única fuente de verdad — los comentarios mienten a medida que el código evoluciona.
Objetos vs Estructuras de Datos
🔒Los objetos ocultan datos detrás del comportamiento. Las estructuras exponen datos. Mezclar ambos crea híbridos que nadie quiere.
Ética y Actitud del Programador
🔒La calidad es una responsabilidad profesional — no algo que entregas cuando el tiempo lo permite, sino el mínimo no negociable de tu oficio.
Funciones Puras
🔒Una función pura siempre devuelve el mismo resultado para la misma entrada y no cambia nada fuera de ella misma.
Selectores de Responsabilidad
🔒Usa las heurísticas de Responsabilidad Única para detectar y dividir clases y módulos sobrecargados.
SerialDate: Limpieza y Transformación
🔒Aplica el refinamiento sucesivo a la clase SerialDate — prueba, renombra, extrae y simplifica.
SerialDate: Diagnóstico
🔒Un caso de estudio para leer código legado de forma crítica — encuentra los malos olores antes de tocar nada.
Las 4 Reglas del Diseño Simple
🔒Las cuatro reglas de Kent Beck, en orden de prioridad, para un diseño siempre listo para evolucionar.
Funciones Pequeñas
🔒Las funciones deben hacer una sola cosa, hacerla bien y solo eso.
Estilo y Formato como Comunicación
🔒El formato del código es un acto de comunicación — estructura los archivos para que cualquier desarrollador pueda navegar en segundos.
Refinamiento Sucesivo
🔒Comienza con código que funciona y luego refactoriza de forma iterativa — nunca escribas código limpio en un solo paso.
Límites del Sistema
🔒El código de terceros pertenece al borde — envuélvelo para que nunca contamine tu lógica de negocio.
Las Tres Leyes del TDD
🔒Domina el micro-ciclo rojo-verde-refactorizar: escribe primero una prueba que falle, luego solo el código necesario para pasarla.
Heurísticas de Testing
🔒Aplica las heurísticas T1–T9 para escribir suites de pruebas completas, significativas y mantenibles.
Patrones de Diseño
Abstract Factory: Familias de Objetos
Crea familias de objetos relacionados sin especificar sus clases concretas — garantiza compatibilidad entre productos de la misma familia.
Adapter: El Traductor de Interfaces
Hace que interfaces incompatibles trabajen juntas — envuelve una clase antigua o externa detrás de la interfaz que tu sistema espera sin modificar ninguno de los lados.
Bridge: Desacoplando la Abstracción
Divide una clase grande en dos jerarquías independientes — abstracción e implementación — para que ambas evolucionen sin afectarse mutuamente.
Builder: Construcción Paso a Paso
Construye objetos complejos paso a paso — el mismo proceso de construcción puede producir diferentes representaciones usando una interfaz fluida.
Cadena de Responsabilidad
Pasa una solicitud a lo largo de una cadena de manejadores — cada uno decide procesarla o pasarla al siguiente, desacoplando emisor de receptor.
Command: Encapsulando Peticiones
Transforma una petición en un objeto autónomo — habilitando deshacer/rehacer, colas, registro y ejecución diferida de operaciones.
Composite: Estructuras en Árbol
Compone objetos en estructuras de árbol y trata objetos individuales y grupos de forma uniforme — itera un sistema de archivos igual sea un archivo o una carpeta.
Decorator: Añadiendo Superpoderes
Añade comportamiento a objetos dinámicamente envolviéndolos — compón capacidades en lugar de crear una explosión de subclases.
Facade: La Cara Amigable del Sistema
Proporciona una interfaz simplificada a un subsistema complejo — oculta el caos detrás de un único punto de entrada limpio sin eliminar la complejidad para quienes la necesitan.
Factory Method: El Constructor Virtual
Delega la creación de objetos a las subclases — desacopla al cliente de las clases concretas que instancia.
Flyweight: Compartir para Ahorrar Memoria
🔒Cabe más objetos en RAM compartiendo estado común — separa datos intrínsecos (compartidos) de extrínsecos (únicos) para evitar duplicar objetos pesados.
Iterator: Recorriendo Colecciones
🔒Recorre elementos de cualquier colección sin exponer su estructura interna — el cliente nunca necesita saber si es una lista, árbol o grafo.
Mediator: Comunicación Centralizada
🔒Restringe la comunicación directa entre objetos — fuerza la colaboración a través de un mediador para reducir dependencias caóticas muchos-a-muchos.
Memento: Deshacer con Instantáneas
🔒Captura y restaura el estado interno de un objeto sin violar la encapsulación — implementa Deshacer almacenando instantáneas de estados pasados.
Observer: El Sistema de Suscripciones
🔒Permite que los objetos se suscriban a eventos y sean notificados automáticamente — desacopla los productores de eventos de los consumidores sin que ninguno sepa del otro.
Prototype: Clonación de Objetos
🔒Copia objetos existentes sin depender de sus clases — clona configuraciones complejas en lugar de reconstruirlas desde cero.
Proxy: El Intermediario de Control
🔒Proporciona un sustituto que controla el acceso a otro objeto — úsalo para carga perezosa, control de acceso, registro o caché sin cambiar el objeto real.
Patrón Repository
🔒Abstrae el acceso a datos detrás de una interfaz para que la lógica de negocio nunca sepa si los datos vienen de una base de datos, caché o API — y las pruebas se convierten en un simple cambio.
Singleton: La Instancia Única
🔒Asegura que una clase tenga solo una instancia y proporciona un punto de acceso global — pero el abuso crea estado global oculto y dificulta las pruebas.
State: Comportamiento Basado en Estado
🔒Permite que un objeto altere su comportamiento cuando su estado interno cambia — reemplaza los condicionales de estado con objetos de estado polimórficos.
Strategy: Intercambio de Algoritmos
🔒Define una familia de algoritmos, encapsula cada uno en su propia clase y hazlos intercambiables en tiempo de ejecución — elimina los condicionales seleccionando el comportamiento mediante composición.
Template Method: Esqueleto del Algoritmo
🔒Define el esqueleto de un algoritmo en una superclase, pero permite a las subclases sobrescribir pasos específicos sin cambiar su estructura.
Visitor: Nuevas Operaciones Sin Cambiar Clases
🔒Añade nuevas operaciones a una jerarquía de objetos sin modificar las clases — el visitor porta la operación, los elementos simplemente la aceptan.
Arquitectura Limpia
ADP: El Principio de Dependencias Acíclicas
No se permiten ciclos en el grafo de dependencias de componentes — los ciclos causan el síndrome de la mañana siguiente e impiden compilaciones y pruebas aisladas.
Límites Arquitectónicos: Trazando Líneas
La arquitectura traza líneas entre lo que importa (reglas de negocio) y lo que no (detalles técnicos) — estas líneas protegen la lógica central del negocio de los cambios en herramientas externas.
¿Qué es la Arquitectura? Soporte del Ciclo de Vida
El propósito principal de la arquitectura es soportar el ciclo de vida del sistema — desarrollo, despliegue, operación y mantenimiento — para maximizar la productividad y minimizar el costo.
Anatomía de un Límite: Cruzando Límites
Al cruzar un límite arquitectónico, las dependencias del código fuente deben apuntar en sentido contrario al flujo de control — el polimorfismo hace esto posible independientemente de quién llama a quién.
Reglas de Negocio y Entidades
Las Reglas de Negocio Críticas existirían incluso sin un ordenador — las Entidades encapsulan estas reglas y datos, formando el núcleo más estable del sistema, independiente de la UI y la persistencia.
Arquitectura Embebida Limpia: Evitando el Firmware
El software no se desgasta, pero el hardware queda obsoleto — una Capa de Abstracción de Hardware evita que la lógica de negocio se convierta en firmware atrapado en un procesador específico.
El Diagrama de Tensión de Componentes
REP, CCP y CRP tiran en direcciones opuestas — los arquitectos deben equilibrar estas tensiones a medida que el proyecto evoluciona del desarrollo a la reutilización.
Componentes: La Unidad de Despliegue
Los componentes son las unidades desplegables más pequeñas — JARs, DLLs, Gemas — los bloques de construcción de una arquitectura de plugins conectados en tiempo de ejecución.
Cohesión de Componentes: El Principio de Reutilización Común
No obligues a los usuarios de un componente a depender de cosas que no necesitan — depender de un componente significa depender de todo lo que contiene.
Modos de Desacoplamiento: Fuente, Despliegue y Servicio
El desacoplamiento puede ocurrir a nivel de código fuente, despliegue o servicio — una buena arquitectura te permite empezar como monolito y evolucionar hacia servicios si los límites están bien definidos.
La Regla de Dependencia en Clean Architecture
🔒Las dependencias del código fuente solo pueden apuntar hacia adentro — nada en un círculo interior puede saber nada de un círculo exterior, manteniendo el núcleo de negocio estable y reutilizable.
Los Detalles: Base de Datos, Web y Frameworks
🔒La base de datos, la capa web y los frameworks son mecanismos de entrega — un buen arquitecto postpone estas decisiones y mantiene las reglas de negocio independientes para evitar un matrimonio tecnológico costoso.
Independencia del Dispositivo
🔒Atar la lógica de negocio a dispositivos de E/S específicos es un error costoso — la arquitectura debe ser agnóstica a si los datos vienen de tarjetas, terminales, archivos o APIs.
DIP: El Principio de Inversión de Dependencias
🔒Las dependencias del código fuente deben apuntar solo a abstracciones — las Fábricas Abstractas crean la frontera arquitectónica entre el código concreto volátil y la política estable.
Inversión de Dependencias: Control sobre las Dependencias
🔒Con interfaces, los arquitectos hacen que las dependencias del código apunten contra el flujo de control, dando control absoluto sobre el acoplamiento.
La Matriz de Eisenhower en el Desarrollo
🔒La arquitectura es importante pero rara vez urgente. Los desarrolladores deben defender la buena estructura frente a la presión del negocio.
Capas de Arquitectura: Entidades y Casos de Uso
🔒Las Entidades contienen reglas de negocio críticas que existen en toda la empresa; los Casos de Uso orquestan flujos específicos de la aplicación y están aislados de los cambios de UI y base de datos.
Programación Funcional: El Valor de la Inmutabilidad
🔒La programación funcional disciplina la asignación. La inmutabilidad elimina condiciones de carrera, deadlocks y problemas de actualización concurrente.
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.
El Patrón Humble Object
🔒Separa el comportamiento difícil de probar del fácil de probar — el Presentador prepara toda la lógica en un ViewModel testeable; la Vista es un humble object que solo muestra lo que recibe.
El Diablo Está en los Detalles de Implementación
🔒La mejor arquitectura fracasa sin un uso disciplinado de los modificadores de acceso — el compilador es tu aliado más fuerte para hacer cumplir las reglas de Clean Architecture en todo el equipo.
Adaptadores de Interfaz y Paso de Datos
🔒Los Adaptadores de Interfaz convierten datos entre el formato que entienden los casos de uso y el que necesitan los sistemas externos — los límites siempre se cruzan con DTOs simples, nunca con entidades crudas o filas de BD.
ISP: El Principio de Segregación de Interfaces
🔒No dependas de cosas que no usas — las interfaces gordas fuerzan recompilaciones innecesarias y acoplamiento a fallos en código no relacionado.
Mantener las Opciones Abiertas
🔒Un buen arquitecto maximiza el número de decisiones aún no tomadas — separando la política de los detalles para que las elecciones de base de datos y framework puedan postponerse hasta saber más.
Desacoplamiento por Capas
🔒Separa lo que cambia a diferentes ritmos — UI, reglas de negocio de aplicación, reglas de dominio y base de datos cambian por razones distintas y deben ser capas horizontales.
LSP: El Principio de Sustitución de Liskov
🔒Los subtipos deben ser sustituibles por sus tipos base — las violaciones del LSP fuerzan lógica costosa de casos especiales en el diseño.
El Componente Main: El Último Detalle
🔒Main es el componente más sucio y de más bajo nivel — el punto de entrada que conecta todas las dependencias y entrega el control a la arquitectura limpia que está sobre él.
La Secuencia Principal: El Equilibrio A/I
🔒Los componentes deben equilibrar Abstracción (A) e Inestabilidad (I) — la Zona de Dolor (estable+concreto) y la Zona de Inutilidad (abstracto+inestable) son antipatrones a evitar.
OCP: El Principio Abierto/Cerrado
🔒Los artefactos de software deben estar abiertos para extensión pero cerrados para modificación — añadir nuevo comportamiento debe añadir código, no cambiarlo.
POO: La Realidad de la Encapsulación
🔒La POO no inventó la encapsulación — C tenía encapsulación perfecta antes de que C++ y Java la debilitaran con los archivos de cabecera.
Paquete por Componente: El Enfoque Híbrido
🔒Agrupa toda la responsabilidad de un límite de funcionalidad limpio en un paquete — la persistencia interna y la lógica permanecen privadas, el compilador hace cumplir lo que es visible para el resto del sistema.
Estrategias de Organización: Paquete por Funcionalidad
🔒Agrupa el código por funcionalidad de dominio — los paquetes de nivel superior revelan el negocio, cada funcionalidad está co-ubicada y la búsqueda mejora drásticamente a medida que el sistema crece.
Estrategias de Organización: Paquete por Capa
🔒La organización de código más simple agrupa por capa técnica (web/servicio/repositorio) — fácil de comenzar pero oculta la intención del negocio y permite atajos peligrosos entre capas.
Límites Parciales: Estrategias de Anticipación
🔒Los límites arquitectónicos completos son costosos — los límites parciales usando patrones Strategy o Facade preservan puntos de separación futura sin el costo total inicial.
El Antipatrón Periférico
🔒El antipatrón periférico ocurre cuando el código de infraestructura habla directamente con otro código de infraestructura, saltándose el dominio — como el anillo de París, el tráfico fluye alrededor de la ciudad en lugar de a través de ella.
Política y Nivel
🔒El nivel es la distancia a las entradas y salidas — cuanto más lejos de la E/S, mayor el nivel. Las dependencias del código fuente siempre deben apuntar hacia las políticas de más alto nivel y más estables.
Polimorfismo: El Poder de los Plugins
🔒El polimorfismo permite tratar dependencias externas como plugins intercambiables, haciendo que la lógica central sea independiente del dispositivo.
Puertos y Adaptadores (Arquitectura Hexagonal)
🔒El interior es el dominio; el exterior es la infraestructura — el exterior depende del interior, los puertos hablan el lenguaje del dominio y los adaptadores traducen entre el dominio y los sistemas externos.
Programación como Ciencia: Falsificabilidad y Testing
🔒Las pruebas no demuestran corrección, demuestran ausencia de incorrecciones conocidas. La buena arquitectura produce módulos fácilmente falsificables.
Paradigmas de Programación: Disciplina, No Herramientas
🔒Los tres paradigmas imponen disciplina eliminando capacidades, no añadiéndolas.
Cohesión de Componentes: REP y CCP
🔒REP agrupa las clases que se liberan juntas; CCP agrupa las que cambian juntas por la misma razón — ambas reflejan el SRP a escala de componente.
SAP: El Principio de Abstracciones Estables
🔒Un componente debe ser tan abstracto como estable — los componentes más estables deben ser interfaces puras para poder extenderse sin modificarse.
Arquitectura que Grita
🔒La estructura de carpetas debe revelar qué hace el sistema, no qué framework usa — un sistema de salud grita 'Salud', no 'Rails'.
SDP: El Principio de Dependencias Estables
🔒Depende en la dirección de la estabilidad — un componente volátil nunca debe ser dependido por uno estable, o esa estabilidad queda comprometida permanentemente.
Servicios y Microservicios: ¿Son Arquitectura?
🔒Los servicios no definen la arquitectura — un servicio con estructura interna pobre es solo una llamada de función costosa. Los límites arquitectónicos reales pueden existir dentro de un monolito o entre servicios.
SRP: El Principio de Responsabilidad Única
🔒Un módulo debe ser responsable ante un solo actor, evitando que los cambios de un departamento rompan accidentalmente otro.
Programación Estructurada: Disciplina sobre el Control Directo
🔒Dijkstra demostró que el goto sin restricciones es perjudicial. La secuencia, selección e iteración son suficientes para módulos correctos y descomponibles.
El Límite de las Pruebas
🔒Los tests son el círculo arquitectónico más externo — los tests frágiles acoplados a detalles de implementación hacen el sistema rígido; una API de Test desacopla la estructura de tests de la estructura de la aplicación.
Los Dos Valores del Software: Comportamiento vs Estructura
🔒El software tiene valor por su comportamiento y su estructura. Un sistema rígido dejará de funcionar cuando los requisitos cambien.
Desacoplamiento de Casos de Uso
🔒Los casos de uso son cortes verticales que atraviesan todas las capas — desacoplarlos permite que cada uno evolucione independientemente sin que los cambios de un caso de uso colisionen con los de otro.