Encapsulamiento e interfaces
Encapsular es ocultar decisiones que pueden cambiar y proteger invariantes. Una interfaz pequeña expone capacidades sin filtrar la representación interna.
Para este tema conviene tener claro:Clases, objetos y estado
Poner campos en private no alcanza para encapsular. Si cada detalle interno se refleja en la
interfaz pública, cualquier cambio obliga a modificar a todos los consumidores.
Esconder una decisión, no unos campos
Encapsular es esconder una decisión de diseño detrás de operaciones estables. Una cola expone encolar y desencolar; no obliga a saber si usa nodos, un buffer circular o bloques.
Esa separación permite cambiar representación sin cambiar el significado. También concentra las validaciones: ninguna ruta externa debería poder crear un estado que las operaciones públicas consideran imposible.
La interfaz de la cola: tres operaciones y nada más. Es lo único que ve quien la usa.
Antes de seguir, predecí
Qué puede hacer, no cómo lo hace
Una interfaz describe qué puede hacer un componente, no cómo lo hace. Cuanto más pequeña sea, menos conocimiento comparten productor y consumidor.
type UserReader = {
findNameById(id: string): Promise<string | null>;
};Quien sólo necesita un nombre no debería depender de métodos de escritura, detalles SQL ni del registro completo de usuario.
Las fugas de representación
Devolver una colección interna mutable filtra representación: el llamador puede modificarla sin pasar por las reglas del objeto. Exponer códigos propios de una base de datos desde todo el dominio también acopla capas que deberían cambiar por separado.
Las copias, vistas de sólo lectura y tipos de resultado propios de la frontera evitan esas fugas. No se trata de ocultar por ocultar, sino de limitar qué cambios pueden propagarse.
Un contrato incluye errores y efectos
Una interfaz debe documentar resultados, errores relevantes y efectos. Dividir interfaces por necesidad del consumidor evita que una implementación deba inventar métodos que no puede cumplir.
Pero demasiadas capas sin una decisión escondida agregan navegación sin desacoplar nada. Una abstracción se justifica cuando estabiliza un concepto o permite variación real.
Qué esconder y qué exponer
| Señal | Qué indica | Qué hacer |
|---|---|---|
| Un getter y un setter por cada campo | no hay encapsulamiento, hay ceremonia | exponer operaciones, no campos |
| Quien llama junta datos de varios métodos para decidir | la decisión pertenece a la clase | mover la decisión adentro |
| La interfaz tiene quince métodos | son varios roles en uno | partirla por quién la usa |
| Cambiar la implementación rompe a los que llaman | se filtró un detalle interno | revisar qué de la interfaz lo expone |
| Los tests necesitan tocar lo privado | falta una operación pública, o el diseño está al revés | agregar la operación que el test quiere |
La pregunta que ordena el diseño no es «qué atributos tiene» sino «qué se le puede pedir». Una
cuenta no expone su saldo para que otro le reste: expone extraer, y el saldo es un detalle. Esa
diferencia es la que permite después cambiar cómo se guarda el saldo sin tocar a nadie.
Cierre
Encapsular protege invariantes y esconde decisiones cambiantes. Una interfaz ofrece la capacidad mínima que el consumidor necesita. El objetivo no es maximizar archivos ni modificadores privados, sino reducir cuánto debe conocer cada parte.
Autoevaluación
¿Lo entendiste?
Práctica