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

Límites del Sistema

El código de terceros pertenece al borde — envuélvelo para que nunca contamine tu lógica de negocio.

La Frontera Limpia

Cuando usas una API de terceros (un Map, una librería de logging, un cliente HTTP) directamente en toda tu base de código, cada cambio en esa API afecta a todo tu sistema. En cambio, envuélvela en una clase que tú controles. El wrapper habla tu lenguaje, y puedes reemplazar la librería subyacente en un solo lugar.

Dict crudo filtrándose por todas partes

sensors = {}
sensors["t1"] = new Sensor("t1")
temp = sensors["t1"].read()
sensors.clear()   // intentional?
remove sensors["t1"]  // scattered 40+ files

Envuélvelo — tú controlas la interfaz

class SensorRegistry:
    sensors = {}

    function register(sensor):
        sensors[sensor.id] = sensor

    function reading(sensorId):
        return sensors[sensorId].read()

    function remove(sensorId):
        remove sensors[sensorId]

Tests de Aprendizaje

Cuando adoptas una librería de terceros, escribe tests enfocados que exploren su comportamiento — no para testear la librería (tiene sus propios tests), sino para documentar tu comprensión de ella. Estos tests se convierten en una red de seguridad: si la librería se actualiza con un cambio de ruptura, tus learning tests fallan primero, antes de que tu código de producción se rompa.

// Learning tests for a fictional cache library
function test_cache_returns_null_for_missing_key():
    cache = new Cache(maxSize: 10)
    assert cache.get("missing") == null

function test_cache_evicts_oldest_when_full():
    cache = new Cache(maxSize: 2)
    cache.set("a", 1)
    cache.set("b", 2)
    cache.set("c", 3)    // "a" should be evicted
    assert cache.get("a") == null
    assert cache.get("c") == 3

function test_cache_ttl_expires_entries():
    cache = new Cache(maxSize: 10, ttlSeconds: 1)
    cache.set("key", "value")
    wait(1.1 seconds)
    assert cache.get("key") == null

Usar Lo Que Aún No Existe

A veces necesitas integrar con un componente que aún no se ha construido. Define la interfaz que desearías tener, escribe tu código contra ella, luego construye un adaptador cuando llegue la implementación real. Esto permite que ambos equipos trabajen en paralelo y mantiene tu código limpio independientemente del diseño de la API externa.

// ✓ Step 1: Define the interface you wish existed
interface Transmitter:
    function transmit(frequency, stream): void

// ✓ Step 2: Build against your ideal interface
class CommunicationController:
    transmitter = null

    function send(data):
        transmitter.transmit(COMM_FREQUENCY, data)

// ✓ Step 3: When the real API ships, write one adapter
class RealTransmitterAdapter implements Transmitter:
    realApi = null

    function transmit(frequency, stream):
        realApi.sendOnFreq(frequency, stream.toBytes())

Desafío de Código

Envuelve el Map de Terceros — el Map crudo se está extendiendo por todas partes. Envuélvelo con nombres de métodos que revelen la intención.

💡Conclusión clave

No posees el código de terceros. Envuélvelo en la frontera — tu dominio habla tu lenguaje, no el de ellos.

🔧 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: Empieza con los consumidores: ¿qué necesitan los llamadores del mapa? Lista esas operaciones (agregar sensor, buscar por id, eliminar) — esas son tus nombres de método. Nunca expongas el mapa crudo al exterior.

✗ Tu versión