Object Calisthenics: El entrenamiento extremo que transformará tu código para siempre
Descubre Object Calisthenics: 9 reglas extremas de programación que transformarán tu forma de escribir código. Aprende cuándo usarlas, cuáles aplicar en producción y por qué son el mejor ejercicio para mejorar tu diseño orientado a objetos.

¿Alguna vez has visto esos videos de personas haciendo flexiones con una mano mientras están parados de cabeza? Eso es calistenia física: ejercicios que parecen imposibles hasta que entrenas lo suficiente. Object Calisthenics es exactamente eso, pero para tu código.
Hoy vamos a hablar de 9 reglas que parecen una locura, que te harán odiarme al principio, pero que si las practicas (aunque sea temporalmente), cambiarán completamente tu forma de programar. Y no, no tienes que seguirlas todas en producción. Son ejercicios de entrenamiento, no reglas para el día a día.
¿Qué demonios es Object Calisthenics?
Object Calisthenics es un conjunto de 9 reglas propuestas por Jeff Bay en "The ThoughtWorks Anthology" (2008). Son restricciones extremas diseñadas para forzarte a escribir mejor código orientado a objetos.
El contexto importante: Bay diseñó esto como un ejercicio de 1000 líneas de código donde sigues TODAS las reglas para desarrollar "memoria muscular". Nunca fueron pensadas como reglas de producción. La filosofía era simple: "los conceptos de alto nivel de la buena programación orientada a objetos pueden destilarse en reglas de bajo nivel".
Las 9 reglas que te harán sufrir (y mejorar)
Regla 1: Un solo nivel de indentación por método
Lo que hacemos normalmente:
SWIFTfunc procesarPedidos(_ pedidos: [Pedido]) { for pedido in pedidos { if pedido.estaListo { if pedido.tienePagoConfirmado { if pedido.direccionEsValida { enviarPedido(pedido) } } } } }
Con Object Calisthenics:
SWIFTfunc procesarPedidos(_ pedidos: [Pedido]) { for pedido in pedidos { procesarPedidoIndividual(pedido) } } private func procesarPedidoIndividual(_ pedido: Pedido) { guard pedido.estaListoParaEnvio else { return } enviarPedido(pedido) }
¿Por qué es genial?
- Cada método hace UNA cosa
- Stack traces más claros cuando algo falla
- Imposible tener métodos de 200 líneas
- La complejidad se distribuye en lugar de acumularse
Regla 2: No uses ELSE
Lo que hacemos normalmente:
SWIFTfunc calcularPrecio(usuario: Usuario, precio: Double) -> Double { if usuario.esPremium { return precio * 0.8 } else { return precio } }
Con Object Calisthenics:
SWIFTfunc calcularPrecio(usuario: Usuario, precio: Double) -> Double { if usuario.esPremium { return precio * 0.8 } return precio }
¿Por qué es genial?
- Flujo lineal sin bifurcaciones mentales
- Reduce complejidad ciclomática
- Fomenta el patrón "fail-fast"
- Cada
if-else
duplica los caminos posibles de tu código
Regla 3: Envuelve todos los primitivos y strings
Lo que hacemos normalmente:
SWIFTfunc transferirDinero(desde: String, hacia: String, monto: Double) { if monto <= 0 { throw Error.montoInvalido } if desde.count != 20 { throw Error.cuentaInvalida } // transferir... }
Con Object Calisthenics:
SWIFTstruct NumeroCuenta { let valor: String init(_ valor: String) throws { guard valor.count == 20 else { throw Error.formatoInvalido } self.valor = valor } } struct Monto { let valor: Decimal init(_ valor: Decimal) throws { guard valor > 0 else { throw Error.montoDebeSerPositivo } self.valor = valor } } func transferirDinero(desde: NumeroCuenta, hacia: NumeroCuenta, monto: Monto) { // La validación ya ocurrió en la construcción }
¿Por qué es genial?
- Validación en un solo lugar
- Imposible pasar parámetros en orden incorrecto
- Los tipos documentan tu código
- Puedes agregar comportamiento:
monto.aplicarImpuesto()
Regla 4: Colecciones de primera clase
Lo que hacemos normalmente:
SWIFTclass Pedido { var productos: [Producto] = [] let cliente: Cliente func agregarProducto(_ producto: Producto) { if productos.count < 10 { productos.append(producto) } } }
Con Object Calisthenics:
SWIFTclass CarritoDeProductos { private var productos: [Producto] = [] private let limite = 10 func agregar(_ producto: Producto) throws { guard productos.count < limite else { throw Error.carritoLleno } productos.append(producto) } } class Pedido { let productos: CarritoDeProductos let cliente: Cliente }
¿Por qué es genial?
- La lógica de la colección está encapsulada
- Invariantes garantizadas (nunca más de 10 productos)
- Reutilizable en otros contextos
Regla 5: Un punto por línea
Lo que hacemos normalmente:
SWIFTlet ciudad = usuario.direccion.ciudad.nombre.uppercased()
Con Object Calisthenics:
SWIFTlet nombreCiudad = usuario.nombreCiudad() let ciudadMayusculas = nombreCiudad.uppercased()
¿Por qué es genial?
- Respetas la Ley de Demeter
- Cambios internos no propagan
- Cada objeto puede optimizar su implementación
Regla 6: No abrevies
usr
→ usuario
, mgr
→ gestor
, calc
→ calcular
¿Por qué es genial?
- Cero ambigüedad
- Búsquedas efectivas en el código
- Nuevos desarrolladores entienden inmediatamente
Regla 7: Mantén las entidades pequeñas
- Máximo 50 líneas por clase
- Máximo 5 líneas por método
Dato empírico: Estudios con ~785K métodos Java muestran que mantenerlos bajo 24 líneas mejora significativamente la mantenibilidad.
Regla 8: No más de 2 variables de instancia por clase
Lo que hacemos normalmente:
SWIFTclass Usuario { let id: UUID let nombre: String let email: String let telefono: String let direccion: String let ciudad: String // ... 10 propiedades más }
Con Object Calisthenics:
SWIFTclass Usuario { let identidad: IdentidadUsuario let contacto: InformacionContacto }
Regla 9: No uses getters/setters/properties
Lo que hacemos normalmente:
SWIFTif cuenta.saldo >= monto { cuenta.saldo -= monto }
Con Object Calisthenics:
SWIFTtry cuenta.retirar(monto)
¿Por qué es genial?
- Los objetos protegen sus invariantes
- La lógica de negocio vive donde debe
- "Tell, don't ask"
Las críticas importantes que debes conocer
"Too Object Oriented" (TOO)
Mike Kramlich acuñó este término para describir código "descompuesto en cientos de clases" que podría haberse hecho "mucho más simple". Es el riesgo real de aplicar estas reglas sin criterio.
El antipatrón del "Código Ravioli"
Cientos de clases pequeñas flotando sin conexión clara. Señales de alerta:
- Necesitas abrir 10 archivos para entender una operación simple
- Tu diagrama de clases parece un mapa del metro de Tokyo
La crítica de la Regla 9
Patrick Dubroy: "casi cada paso hacia 'OOP verdadero' es solo otra forma de oscurecar el significado del código". La prohibición de getters/setters conflictúa con:
- ORMs (CoreData, SwiftData)
- Serialización JSON
- Muchos frameworks modernos
Object Calisthenics en Swift
Ventajas de Swift:
- El sistema de tipos fuerte facilita envolver primitivos
- Los value types (structs) hacen natural la inmutabilidad
- Extensions permiten agregar comportamiento limpiamente
Adaptación pragmática:
- Usa
private(set)
en lugar de eliminar getters completamente - SwiftUI requiere properties públicas - no luches contra el framework
- Aprovecha property wrappers para encapsular comportamiento
Cuándo y cómo practicar
- Kata semanal: Resuelve FizzBuzz o Bowling siguiendo TODAS las reglas
- Una regla a la vez: Practica una regla por semana en tu código personal
- Refactoring experimental: Toma una clase problemática y refactorízala en un branch de prueba
Los efectos reales después de practicar
Los desarrolladores reportan cambios permanentes:
- 20 líneas te parecen un método largo (antes tolerabas 100)
- Ver 3 niveles de indentación te genera necesidad de refactorizar
- Nombras conceptos del dominio que antes ignorabas
- Tu código es más testeable por defecto
La verdad definitiva
Después de 15 años, el consenso es claro:
Como ejercicio de aprendizaje: EXCELENTE. Hazlo al menos una vez.
Como reglas de producción: IMPRACTICABLE. Demasiado rígido.
Como principios guía: VALIOSO. Aplica selectivamente.
Las reglas más útiles en la práctica:
- Regla 1 (un nivel de indentación)
- Regla 3 (envolver primitivos importantes)
- Regla 5 (un punto por línea)
- Regla 6 (no abreviar)
Un ejercicio para empezar
Intenta refactorizar esto siguiendo las 9 reglas:
SWIFTclass ShoppingCart { var items: [(product: String, price: Double, qty: Int)] = [] func addItem(name: String, price: Double, quantity: Int) { if name != "" && price > 0 && quantity > 0 { items.append((name, price, quantity)) } } func getTotal() -> Double { var total = 0.0 for item in items { total += item.price * Double(item.qty) } return total } }
Para cerrar
Object Calisthenics no es sobre escribir código así siempre. Es sobre expandir tus límites para que tu código "normal" sea naturalmente mejor.
Los desarrolladores pasan 58-70% del tiempo leyendo código y solo 5% escribiéndolo. Vale la pena invertir en que ese 58% sea menos doloroso.
¿Te animas a intentar la regla "No uses ELSE" por una semana? Es la que más rápido muestra resultados. Comparte tu experiencia en los comentarios.
El equipo de AprendeSwift.dev 💪
PD: Si sientes la necesidad de refactorizar todo tu código después de leer esto... respira. Empieza con un kata, no con producción. Roma no se construyó en un día 🏛️