Skip to main content

Inicia sesión en CleanKata

Sigue tu progreso, gana XP y desbloquea todas las lecciones.

Al iniciar sesión aceptas nuestros Términos de uso y Política de privacidad.

Código Limpio60 XP6 min

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.

La Diferencia Fundamental

Los objetos ocultan sus datos y exponen comportamiento (métodos). Las estructuras de datos exponen sus datos y no tienen comportamiento significativo. Esto no es estético — determina cómo tu código maneja el cambio. Añadir una nueva operación en un mundo de estructuras es fácil (añade una función). Añadir un nuevo tipo en un mundo de objetos es fácil (añade una subclase). Cada uno es difícil para el otro caso.

// Data Structure — expose data, no behavior
struct Point:
    x
    y

// Operates on data structures (procedural)
function distance(p):
    return sqrt(p.x * p.x + p.y * p.y)

// ─────────────────────────────────────────────

// Object — hides data, exposes behavior
class Point:
    _x = 0
    _y = 0

    function distanceToOrigin():
        return sqrt(_x * _x + _y * _y)

    function translate(dx, dy):
        return new Point(_x + dx, _y + dy)

La Ley de Deméter

Un método solo debe llamar a métodos de: sí mismo, sus argumentos, objetos que creó, o sus componentes directos. Nunca atravieses un objeto para obtener otro objeto y llamar a ese. Los choques de trenes — a.getB().getC().doSomething() — exponen detalles de implementación a lo largo de toda la cadena y hacen que el refactoring sea una pesadilla.

Choque de trenes — viola la Ley de Deméter

amount = order.getCustomer()
    .getWallet().getBalance()

if order.getCustomer()
    .getWallet().getBalance()
    > order.total:
    order.getCustomer()
        .getWallet().deduct(order.total)

Dile, no preguntes — delega al propietario correcto

order.chargeCustomer()

// Inside Order:
function chargeCustomer():
    customer.charge(total)

// Inside Customer:
function charge(amount):
    wallet.deduct(amount)

DTOs y Registros Activos

Los Objetos de Transferencia de Datos (DTOs) son estructuras de datos puras: sin lógica de negocio. Úsalos para mover datos entre capas: respuesta HTTP → servicio, fila de base de datos → dominio. Los Registros Activos añaden save()/find() a los DTOs. La trampa: nunca añadas lógica de negocio a un Registro Activo — crea un objeto de dominio separado para eso.

// ✓ DTO — pure data, no behavior
struct UserDTO:
    id
    name
    email
    createdAt

// ✓ Active Record — data + persistence only
class UserRecord:
    id
    name
    email

    function save(): ...
    function find(id): ...

// ✗ Hybrid — Active Record with business logic (don't do this)
class UserRecord:
    ...
    function canAccessAdmin(): ...           // ← business logic here
    function calculateSubscriptionPrice(): ... // ← wrong layer

Desafío de Código

Rompe el Choque de Trenes — las llamadas encadenadas exponen tres objetos internos. Delega al propietario correcto en cada nivel.

💡Conclusión clave

Los objetos no son mejores que las estructuras de datos — son herramientas diferentes. Elige una y comprométete. Los híbridos te dan lo peor de ambas.

🔧 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: Pregunta: ¿quién *posee* cada dato en la cadena? El pedido no debería saber sobre ciudad. Pídele al pedido getShippingCity() y que él delegue internamente — el llamador se mantiene ignorante de la estructura interna.

✗ Tu versión

Objetos vs Estructuras de Datos — CleanKata — CleanKata