A1.06 · dive 1
One core, many surfaces
Portal is a learning platform with five surfaces — and they all reach the core through one facade.
The running project of this course is Portal: a branded store, an event-sourced engine behind a single facade, a Phoenix web app, a Telegram bot, and a student dashboard. The five surfaces differ in shape, but each one calls the core only through the facade — never a private of the engine. Switch the surface on the right to follow one call down to the facade.
Five surfaces, one facade · pick a surface
What Portal is
Portal is the learning platform this course carries from an empty repository to a deployed system. It is one product with five surfaces: a branded store for typed records, an event-sourced engine that holds the history, a Phoenix web app, a Telegram bot, and a student dashboard. The surfaces differ in shape — a web request, a chat message, a query — but they share one rule.
The rule is the facade. The engine has a history and rules that are nobody else's business; those internals are private. Every surface that needs the core calls it through one published facade — never a private of the engine. The facade is the single door, so the core can change its internals freely as long as the door stays the same. The surfaces, in turn, depend on the door, not on what is behind it.
- Portal
- The running project: one learning platform built end to end across the course. The companion /elixir course teaches its OTP internals; this course uses it as the worked domain.
- surface
- One of the five faces a caller uses: the store, the engine, the web app, the bot, the dashboard. Each is a separate place a change can land.
- core
- The engine's state and rules — the event history and the logic over it. Private. Nothing outside reaches it directly.
- facade
- The one published surface of the core. Every other surface calls it; only it calls the core. The single door that keeps the core's internals private.
The OTP machinery behind the engine — processes, supervision, the event log — is taught by the companion /elixir course. Here Portal is the domain the workflow runs on, not the thing being re-explained.
Add a surface, and the blast radius stays at the surface
The facade is not decoration; it pays off the first time the platform grows. A sixth surface — say a weekly digest, or a public read-only API — is added over the facade. It calls the same door every other surface calls. Because it only depends on the door, adding it touches its own surface and nothing else: the core does not change, and no other surface changes.
That bounded reach is orthogonality (A1.02.3) at platform scale. A change whose blast radius is one surface is a reviewable change: a human reading the diff sees a self-contained addition, not a thread pulled through the whole system. Toggle the new surface on below and watch where the change lands — the count of touched components, and whether the core is among them.
Add a surface over the facade · watch the blast radius
A surface added over the facade has a blast radius of one — itself; reach past the facade and the core is in the diff too.
The id rung on the Portal
Take the smallest piece the platform needs: a typed identifier. The id authority lives in the
store, and the contract is one rung — a 14-character TSK…
id that decodes to its type and its timestamp. Every surface that needs a typed id calls the facade for it:
Portal.ID.generate/1 to mint one, Portal.ID.decode/1 to read
it back. None of them reaches a private of the engine.
The web app minting a session id, the bot tagging a message, the dashboard decoding a record's type — all of them go through the same two functions. One authority, one contract, one door. When the id format changes, it changes once, behind the facade; the surfaces keep calling the same two functions and keep working.
# Every surface mints and reads typed ids through the facade — never a private of the engine. id = Portal.ID.generate(:session) # => "SES0NbAb1xcFCy" (14-char TSK… id) decoded = Portal.ID.decode(id) decoded.type # => :session decoded.timestamp # => the mint time, recovered from the id # the web app, the bot, and the dashboard all call exactly these two functions — # one id authority, one contract, one door.
The principle
Put the core behind one published facade. Every caller depends on the door, not on the internals — so the internals stay free to change and a new caller is a bounded addition.
On the Portal
The id authority is in the store; every surface mints and reads typed ids through
Portal.ID.generate/1 and Portal.ID.decode/1 — the
facade — never a private of the engine.
Portal is many surfaces over one facade — the door that lets the platform grow a surface at a time without reopening the core.
Recap — one core, many surfaces
Portal is a learning platform with five surfaces — a branded store, an event-sourced engine, a Phoenix web app, a Telegram bot, and a student dashboard — and they all reach the core through one facade. That single door keeps the core's internals private and makes growth cheap: a sixth surface is added over the facade, its blast radius is itself, and the core is untouched. The id rung shows the discipline in the small, with every surface minting and decoding typed ids through the facade. The next dive takes the same platform the other way — from this empty repository to a running deployment.
Next in A1.06: A1.06.2 · Zero to production — the path that carries Portal from an empty repository to a deployed, multi-surface system, one thin slice at a time.
References
Primary sources for the facade and the bounded blast radius, and where Portal connects in the course.
Sources
- Hunt, A. & Thomas, D. — The Pragmatic Programmer — orthogonality and decoupling: a change whose reach is bounded is a change you can reason about.
- Beck, K. — Extreme Programming Explained — growing a system in small, integrated increments rather than one large design.
- Humble, J. & Farley, D. — Continuous Delivery — carrying one product to production through thin slices, each delivered end to end.
Related in this course
- A1.06 · Meet the project: Portal — the module hub.
- A1.06.2 · Zero to production — the next dive.
- A1.02.3 · Orthogonality — the bounded blast radius this page applies at platform scale.
- A1.04 · Two layers: roadmap and specs — where the id rung's contract lives.
- A1 · Why an Agile Agent Workflow — the chapter.