A2.07 · Workshop · dive 2
Split and test
The web vision is too big for one rung. It is cut into nine vertical slices — then one rung is laid out as its four artifacts and proven by its Given/When/Then.
Serve the Portal to people splits into nine rungs, f6.1–f6.9,
each shipping one capability over the unchanged Portal facade. Zoom
into F6.6 (LiveView): every rung is carried by exactly four artifacts — a roadmap line, a
spec, Given/When/Then stories, an agent brief. Switch the artifact on the right to read what each one
contributes and the question it answers.
F6.6 · its four artifacts · select one
One vision, nine vertical rungs
The vision for the Portal’s web surface is one line: serve the Portal to people. That is too
big for one rung — it is a store, an authenticated learning area, real-time updates, and an operations
dashboard at once. So it is cut into nine vertical slices, f6.1 through
f6.9, each a capability a real role can use, each shipping over the system already
running: F6.1 boot, F6.2 routing, F6.3 Ecto, F6.4 contexts, F6.5 HEEx views, F6.6 LiveView, F6.7 PubSub,
F6.8 auth, F6.9 dashboard.
What keeps the cut vertical — a slice of value, not a layer of work — is a single rule every rung
obeys. Each rung adds web surface and calls only the unchanged Portal facade, so
nothing under the F5 engine ever changes. That is the master invariant, quoted from the
roadmap:
The web layer calls only thePortalfacade and renders only the closed%Portal.Error{}set. No controller, LiveView, plug, or template namesPortal.Engine, a repo, orGenServer.call.
The rungs depend only downward: F6.5 renders what F6.3 and F6.4 make queryable, and F6.6 makes F6.5’s pages live. Splitting yields the slices; the rest of this dive shows how one of them — F6.6 (LiveView) — is laid out and proven.
The nine rungs are the same ladder the A2.07 workshop hub walks rung by rung. Each is specified, built, and proven in the companion course at /elixir/phoenix/liveview and its siblings. Here the work is the split and the test, not the build.
One rung, four artifacts — F6.6 (LiveView)
A rung is not one document. Every rung is carried by exactly four artifacts, and each answers one question.
F6.6 delivers F6.5’s catalog made interactive without reloads — CatalogLive
streams from the facade, a two-stage mount, a live search box via Portal.search_courses/1,
and a live create form. Those four artifacts, written out, are below; the inspector in the hero highlights one
at a time.
# F6.6 · LiveView — the four artifacts that carry one rung. phoenix.roadmap.md # the roadmap line — how it ships F6.6 | interactivity (live search, live create, streams) | search as you type; create without a reload | LiveViewTest (render_change/render_submit) | does the interaction feel right? f6.6.md # the spec — what & prove (Goal · Scope · Deliverables · Invariants · Done) Goal: After F6.6, the catalog is interactive without a page reload. CatalogLive (use PortalWeb, :live_view) streams the … f6.6.stories.md # the stories — acceptance (US0–US5, Connextra + Given/When/Then) As a learner, I want the course list to filter as I type, so that I find a course without submitting or reloading. # F6.6-US1 f6.6.llms.md # the agent brief — references, topology, paste-ready prompt the instructions an agent runs to build and self-check the rung.
- roadmap
- One line in
phoenix.roadmap.md— place in the delivery order, the demo, the test harness, the feedback asked. Answers how it ships. - spec
f6.6.md— Goal, Rationale (5W), Scope, Deliverables, Invariants, Definition of Done. Answers what & prove.- stories
f6.6.stories.md— six Connextra stories (US0–US5), each with Given/When/Then and tagged INVEST, priority, size. Answers acceptance.- brief
f6.6.llms.md— the references, requirements, execution topology, and the paste-ready prompt. Answers agent instructions.
The four are not redundant: the roadmap orders the rung, the spec bounds it, the stories make it acceptable, and the brief makes it buildable by an agent. The next section runs the acceptance — the third artifact — for F6.6’s first story.
Proven, not asserted — F6.6-US1
A slice is ready not when it is small but when its acceptance can be run. F6.6’s first story carries its
proof as Given/When/Then — quoted verbatim from f6.6.stories.md:
# F6.6-US1 · Search as I type As a learner, I want the course list to filter as I type, so that I find a course without submitting or reloading. Given the search box, when I type, then phx-change="search" fires handle_event("search", params, socket). Given the event, when it runs, then it filters through the Portal.search_courses/1 facade function and re-streams :courses with reset: true (the list is @streams.courses, never an assign — INV4). Given each keystroke, when handled, then the rendered list narrows without a reload, and the view names only Portal.
Each line is a step that either runs or does not. Step the scenario below: each Given/When/Then reports PASS against a fixed model of the search box, the fired event, and the re-stream. That is the difference between a slice that asserts it works and one that proves it — the proof is executable.
F6.6-US1 acceptance · step Given → When → Then
A slice converges when its acceptance can be run — on the Portal that proof is the verbatim Given/When/Then of the rung, not a claim that it works.
The contract is the spec. A slice is ready when its acceptance is written as Given/When/Then — so it is proven, not asserted. Splitting yields slices; the test is whether each can be run.
Typing fires phx-change="search" → handle_event("search", params, socket)
→ Portal.search_courses/1 → re-streams :courses with
reset: true. The view names only Portal.
The four artifacts make the rung; the Given/When/Then makes it acceptable — the proof runs.
Recap — split into rungs, one rung proven
The web vision split into nine vertical rungs, each shipping one capability over the unchanged
Portal facade. One rung, F6.6 (LiveView), was laid out as its four artifacts —
roadmap line, spec, stories, brief — and its first story was proven by running its Given/When/Then:
typing fires phx-change="search", the event filters through
Portal.search_courses/1, and the list re-streams without a reload. A slice is ready
when its acceptance can be run. The rungs are still in one heap — the last dive orders them into
milestones.
Next in A2.07: A2.07.3 · Order the backlog — order the nine rungs by dependency into three milestones, a value ladder that stays runnable at every rung, and read the git history of how the specs evolved: specified, shipped, reconciled.
References
Primary sources for vertical slicing and executable acceptance, and the chapter moves this dive applies.
Sources
- Cohn, M. — User Stories Applied — splitting a large vision into thin vertical slices that each deliver value a role can use.
- Adzic, G. — Specification by Example — each slice carries its own concrete, runnable Given/When/Then acceptance.
- Humble & Farley — Continuous Delivery — thin, demoable increments that keep the system releasable at every rung.
Related in this course
- A2.07 · Workshop: decomposing Portal — the module hub; the nine-rung roadmap, rung by rung.
- A2.07.1 · Vision to stories — the previous dive: the vision read into its rung ladder.
- A2.07.3 · Order the backlog — the next dive: the rungs ordered into milestones.
- A2.03 · INVEST — the readiness lens each vertical slice satisfies.
- A2 · Decomposition — the chapter the workshop applies.
- Companion · /elixir/phoenix/liveview — where F6.6 (LiveView) is specified, built, and proven.
- Companion · Functional Programming in Elixir — the Portal’s internals.