Learn how a small public namespace can give Clojure callers a cleaner entry point to a complex subsystem without exposing every internal helper and workflow detail.
Facade pattern: A structural pattern that offers a small, simpler entry point to a more complex subsystem.
Facade is one of the most natural structural patterns in Clojure because namespaces already give you a way to define a clean public API. Instead of exposing every low-level helper, parser, validator, repository call, and transport detail, a facade namespace can present a small set of higher-level operations that match what the caller actually needs.
Imagine a reporting subsystem with separate pieces for:
The caller often does not want five separate functions and several data contracts. It wants one operation like generate-report!.
1(ns myapp.reporting.facade
2 (:require [myapp.reporting.validate :as validate]
3 [myapp.reporting.plan :as plan]
4 [myapp.reporting.fetch :as fetch]
5 [myapp.reporting.render :as render]))
6
7(defn generate-report [request]
8 (-> request
9 validate/valid-request!
10 plan/build-plan
11 fetch/run-plan
12 render/render-report))
That namespace is acting as a facade. It exposes the operation the caller cares about while shielding the internal workflow structure.
The subsystem internals still exist and may still be used directly in tests, tooling, or specialist code. Facade simply prevents ordinary callers from needing to learn the whole internal graph.
That is why a facade should usually:
Clojure’s namespace design makes facade especially straightforward:
This is cleaner than exporting a pile of low-level functions and telling callers to compose them “correctly.”
The common failure mode is a facade that keeps absorbing more and more unrelated responsibilities until it becomes the whole subsystem in disguise.
That usually happens when:
A good facade is small because it represents a stable public surface, not because it owns all implementation logic directly.
Those patterns can appear near each other, but the intent is different.
The most valuable facades often do more than shorten imports. They stabilize a workflow the rest of the codebase depends on:
That gives callers one stable entry point while the subsystem behind it can still evolve internally.
If every internal namespace is effectively public and recommended for routine use, the facade adds little value.
The facade should orchestrate and simplify, not become the only place where domain behavior lives.
If callers cannot rely on facade operations staying stable, they will bypass it and couple themselves to internals instead.
Use a facade when a subsystem has more moving parts than most callers should need to learn. In Clojure, a facade is often just a carefully designed namespace with a few high-level operations. Keep it narrow, stable, and business-oriented, and let deeper namespaces carry the lower-level detail.