Facade Pattern

Intención y problema

Facade ofrece una entrada coherente de mayor nivel a un subsistema complejo. Reduce lo que un consumidor necesita conocer para realizar ciertas operaciones, sin exigir reorganizar todos los componentes internos. Esta intención de simplificación corresponde a la formulación GoF recogida en Principles of Software Construction, CMU.

La presión aparece cuando varios consumidores repiten conversaciones de preparación, validación y ejecución, o dependen de detalles que deberían poder evolucionar juntos. El problema no es simplemente que existan muchas clases: es que el cliente debe comprender demasiada cooperación interna para expresar una necesidad reconocible.

Una Facade no tiene que ocultar todas las capacidades. Puede convivir con contratos especializados para consumidores avanzados. Tampoco necesita ser una única clase: un módulo con operaciones cohesionadas puede proporcionar la misma entrada deliberada.

Fuerzas y límite del contrato

Queremos reducir dependencias externas y preservar flexibilidad interna, pero una interfaz sencilla puede eliminar información necesaria. Simplificar nombres sin aclarar resultados, errores y efectos deja al cliente con una conversación corta y un contrato confuso.

La frontera debe agrupar capacidades que pertenecen a un propósito. Una API orientada a casos de uso ayuda cuando describe lo que el consumidor quiere lograr; un método genérico que recibe opciones para cualquier operación desplaza la complejidad a parámetros y documentación.

También hay tensión entre estabilidad y evolución. Si la Facade promete conservar un resultado, sus componentes pueden cambiar detrás de ella. Si expone sus estructuras internas como respuesta, la dependencia reaparece aunque el cliente solo invoque un objeto.

Estructura y colaboración

Client
    → PublicationFacade
        → Formatter
        → Validator
        → Archive

El cliente conoce la operación de publicación y su resultado. La Facade coordina las capacidades necesarias; cada participante conserva su responsabilidad. No es obligatorio que los componentes sepan que existe la Facade ni que deban acceder entre sí a través de ella.

En un ejemplo propio, publicar un reporte exige preparar el formato solicitado, validar el resultado y almacenarlo. Antes, cada consumidor decidía ese orden y traducía errores diferentes. PublicationFacade ofrece una operación explícita y devuelve un resultado que distingue rechazo de validación, publicación completada y fallo de almacenamiento.

Esta colaboración contiene conocimiento de coordinación, no todas las reglas del reporte. El validador sigue definiendo qué acepta; el archivo administra su almacenamiento. Que el flujo se vea como una sola llamada no lo convierte en una transacción ni garantiza deshacer pasos ya ejecutados.

Consecuencias y evolución

El consumidor depende de menos contratos. Cambiar cómo se prepara un reporte puede quedar contenido detrás de la entrada estable. También mejora la explicación de un caso de uso: una operación significativa evita repetir una secuencia accidental en cada cliente.

El costo es otro contrato que diseñar, mantener y probar. Si solo delega llamadas sin reducir conocimiento necesario, la capa puede añadir navegación sin beneficio. Si acumula demasiadas variantes, cualquier cambio del subsistema termina modificando la misma entrada.

Una Facade facilita pruebas del contrato externo, pero no reemplaza las pruebas de sus participantes. En el ejemplo, comprobar un resultado integrado no demuestra por sí solo que todas las reglas de validación sean correctas. Conviene observar la coordinación y sus fallos, además del comportamiento de cada capacidad.

La estabilidad tampoco significa congelar la interfaz para siempre. Una nueva necesidad puede justificar otra entrada cohesionada o acceso especializado. Forzar todo requerimiento futuro a pasar por una operación inicial favorece parámetros ambiguos y dependencias crecientes.

Evitar una God Facade

EverythingService puede reunir reglas de negocio, persistencia, autorización, infraestructura y todas las operaciones disponibles. Llamarlo Facade no vuelve coherente esa concentración. La señal de deterioro es que deja de coordinar capacidades y comienza a ser el subsistema.

La responsabilidad de alto nivel debe tener límites identificables: qué caso de uso organiza, qué decisiones delega y qué resultado promete. Incorporar una política particular puede ser correcto; absorber todas las políticas y todos sus mecanismos vuelve difícil evolucionarlas independientemente.

Dividir una Facade enorme por nombres cosméticos tampoco resuelve el problema. Las entradas deben reflejar propósitos y consumidores reales. Revisar quién necesita cada operación y qué cambios deberían poder ocurrir separados ofrece mejor criterio que repartir métodos en clases de tamaño uniforme.

Facade frente a Adapter y Mediator

adapter-pattern responde a una incompatibilidad de interfaz o protocolo. Facade responde a la complejidad de acceder al subsistema. Una operación puede simplificar acceso aunque todas las interfaces existentes ya sean compatibles.

PublicationFacade podría usar Adapters para conectar un archivo legado y un validador externo con los contratos que necesita. La adaptación ocurre en esa frontera; la Facade organiza una conversación más amplia. Compartir delegación no convierte ambas intenciones en la misma.

mediator-pattern coordina interacciones entre participantes que colaboran. Facade suele organizar cómo un consumidor externo accede al conjunto; Mediator se concentra en las reglas de cooperación entre pares. Es una diferencia de intención, no una ley geométrica sobre dónde dibujar cada objeto.

Un subsistema puede tener un Mediator interno y una Facade externa. Si una entrada empieza a administrar toda comunicación entre participantes, conviene examinar qué responsabilidad nueva asumió. La combinación requiere explicarla, no escoger un nombre por la cantidad de flechas.

Facade frente a API Gateway

Un API Gateway ocupa un rol arquitectónico distribuido. Puede intervenir en routing, autenticación, autorización, rate limiting, agregación, traducción de protocolos, observabilidad, políticas e integración con descubrimiento de servicios. El Azure Architecture Center contextualiza routing, aggregation y offloading en esa frontera.

Algunos gateways ofrecen una interfaz parecida a una Facade, pero esa semejanza no equipara ambos conceptos. PublicationFacade puede existir dentro de un proceso sin red ni gateway; un gateway puede limitarse a enrutar solicitudes sin presentar una conversación de mayor nivel.

Elegir Facade no decide topología, exposición pública, aislamiento ni disponibilidad de un gateway. Esas consecuencias necesitan análisis arquitectónico propio. Tampoco una entrada simplificada constituye por sí sola un perímetro de seguridad.

Layering y acceso especializado

En layered-architecture, una capa puede ofrecer una Facade a la superior. Por ejemplo, presentación utiliza una entrada de aplicación que coordina capacidades internas. La Facade puede ayudar a expresar el contrato de esa capa, pero una frontera entre capas no demuestra automáticamente el patrón.

Permitir acceso directo a ciertas capacidades es compatible con Facade cuando esa alternativa tiene un contrato deliberado. Debe quedar claro qué garantías pertenecen a la entrada de alto nivel. Un consumidor que omite la validación coordinada no debería asumir que obtuvo el mismo resultado.

Mantener dos caminos exige atención a su evolución. Si una capacidad cambia, hay que revisar tanto consumidores especializados como la operación simplificada. Reducir dependencias en el camino común no elimina las dependencias de quienes eligieron acceso detallado.

Aplicabilidad, alternativas y mal uso

Facade es candidata cuando existen secuencias repetidas, conocimiento interno filtrado o una necesidad externa cohesionada. Conviene comparar la coordinación actual con una entrada explícita y comprobar qué dependencia desaparece. pattern-selection mantiene esa evaluación ligada a fuerzas y consecuencias.

No suele aportar cuando el subsistema ya expone una conversación pequeña y suficiente. Una función directa puede ser más clara. En lenguajes modernos, funciones, módulos o grupos de operaciones pueden expresar una entrada cohesionada sin reproducir una jerarquía de clases.

Los malos usos incluyen ocultar fallos parciales, agregar un wrapper por cada componente sin simplificar nada y concentrar toda decisión en EverythingService. Otro es bloquear capacidades legítimas solo para afirmar encapsulación, obligando a ampliar una entrada común con excepciones para cada consumidor.

La revisión útil pregunta qué conocimiento deja de necesitar el cliente, qué contrato sigue visible y qué cambios quedan contenidos. structural-patterns compara esta intención con compatibilidad, responsabilidades adicionales y representación de acceso. La forma del wrapper ofrece una pista; el problema que resuelve determina su identidad.