Project studio: the system comes together
420-302-VA · WEEK 12 · FALL 2026

Stage 3 of 6 · Theory · how pieces meet

Joining the pieces

The skeleton said what to build first; integration discipline says how pieces meet from now on. The rule fits in a sentence: join one interface at a time, verify it, then the next. The hour's job is to show why the obvious alternative quietly costs a week, and to hand you the two command-line stubs that make the rule practical for a pair.

Big bang versus one join at a time

Big-bang integration builds every component separately, then connects them all at once near the deadline. Incremental integration connects two pieces, verifies the join, and only then adds the third. Software engineering has preferred the second for fifty years, and the reason is fault localization, not neatness. When a big-bang system fails its first combined run, the fault could be at any of the k freshly exercised interfaces, or in several at once, masking each other; with six contracts you start the worst week of the project with six suspects and no alibis. When an incremental join fails, one interface changed since the last green check, so the suspect list has length one.

Two timelines across four project weeks. Top, big bang: four separate component bars grow in isolation for three weeks, then meet at a junction marked first combined run, followed by a red region labelled six suspects, unknown fixing time, overlapping deliverable D4. Bottom, incremental: a single bar grows stepwise, with small green check marks at week boundaries labelled join plus verify, one suspect each, and the deliverables D2, D3, D4 sit on green. Big bang node rule bridge page first combined run 6 suspects at once fixing time unknown, D4 under it One join at a time ✓✓✓✓ each ✓ = join + verify · one suspect if it fails D2D3D4 Same total build time. The difference is when the interface faults surface, and how many at once.
Where the week goes. Big bang defers every interface fault to one run and stacks them; incremental spends the same discovery cost in one-suspect instalments. Your milestones sit on the green track by construction, because every rung ends demonstrable.

Your course already made the first move for you: the skeleton is the first full incremental pass, so from today integration means something gentler, re-verifying the chain each time a rung thickens one piece. The habit is mechanical: before changing a component, run the end-to-end check; after changing it, run it again. Two minutes, and any new fault has a one-line suspect list, your diff.

The bench's natural order

When a join does need building or rebuilding, order matters, and the bench has a natural one: follow the data, and never join to an unverified neighbour. Each step below assumes the previous one is green, which is exactly what makes a failure at step k a statement about join k alone.

  1. Node ↔ broker. The node publishes; the Week 9 firehose listens: mosquitto_sub -t "#" -v. Green means Wi-Fi, topic and payload all hold.
  2. Broker ↔ rule. Your monitor or controller subscribes and logs what it parses. Green means the subscription and the payload reading hold, bytes decoded, numbers converted.
  3. Rule ↔ actuator path. The rule publishes its command; the node's check_msg loop obeys. Green means the command grammar holds in both directions.
  4. Bridge ↔ broker, then page ↔ bridge. curl the API route before any browser touches it; only then load the page and let fetch take over.

The verifier at each step is a tool, not a teammate

Notice that every green check above uses a neutral instrument, the firehose, a log line, curl, never "my partner's program seemed happy". Instruments do not share your assumptions; that is their whole value, and it is why the same four instruments return on the next page as probes.

Stubs: never wait for your partner

Pair work has a scheduling trap: if the dashboard can only be tested against the live node, then the dashboard's author idles whenever the node's author is mid-surgery, and both work converges on the one shared bench. The escape is the stub, a stand-in that honours the contract while the real piece is away, and the bench's protocols make stubs nearly free. MQTT does not care who publishes, and HTTP does not care who asks:

# A fake node: publish by hand what the real node would say
you@lastname-pi:~ $ mosquitto_pub -t "bench/s07/light" -m "42"

# A fake browser: ask the bridge what the page would ask
you@lastname-pi:~ $ curl http://localhost:5000/api/light
Two half benches. Left, dashboard work without the node: mosquitto underscore pub stands where the node box would be, drawn dashed, feeding the broker, and the real rule, bridge, page and browser run. Right, node work without the dashboard: the real node, broker and rule run, while the browser end is replaced by a dashed curl box reading the API, and a dashed mosquitto underscore sub box watches the command topic. Dashboard day: stub the node mosquitto_pubthe fake node broker rule · bridge page · browser every contract below the node still real Node day: stub the browser node, real broker · rule curl /api/lightthe fake browser mosquitto_sub cmdwatch the commands node, Wi-Fi, topics and commands exercised, no page needed A stub honours the written contract, which is why docs/topics.md must stay exact: the stub reads it too.
Two half benches, zero waiting. Each partner tests their layers against stubs of the other's, and the written contracts in docs/topics.md are what keep the halves honest; when the real pieces meet, only reality is new.

A stub is also a demo insurance policy

Keep your stub commands in the repo, in a docs/stubs.md or a small script. If a sensor dies ten minutes before a milestone demo, publishing honest fake data while saying so is a professional recovery; markers grade method, and a pair that can degrade gracefully is demonstrating it.

Checklist for this stage

Check yourself

A pair split the work by layer, and the node author is reflashing all afternoon. What can the dashboard author verify meanwhile, concretely?
Everything except the first contract. With mosquitto_pub -t "bench/s07/light" -m "42" (their project's topic) as the fake node, they can verify the rule parses and reacts, the bridge's latest updates, curl of the API returns the right JSON keys, the page renders and polls, and the setpoint POST publishes on the command topic, watched with mosquitto_sub. That is five of six contracts, and when the real node returns, only contract 1 is news.
The first combined run after a big bang fails with a frozen dashboard. Why is "the bug is probably in the newest code" unreliable here, in terms of suspects?
Because a big-bang failure is conditioned on all interfaces being exercised for the first time together, so the prior spreads across every contract, not the newest code: the node might publish a string where the rule expects bytes to decode, the bridge might poll a misspelled topic, the page might fetch the wrong route, and two faults can mask or mimic each other, a frozen dashboard is Week 11's null-bridge symptom but also Week 9's wrong-topic symptom. Recency is informative only when exactly one thing changed since a green state, which is the incremental habit's whole point.
Why must the stub read docs/topics.md rather than the stub author's memory, when both authors sit at the same bench?
Because the failure mode being defended against is precisely a divergence between two memories of the contract. If the dashboard author stubs from memory and remembers bench/s07/Light, their whole stack verifies green against a topic the real node never uses, and the error survives until the pieces meet, disguised as a mysterious integration bug. A stub built from the written contract turns the file into the single source both halves are tested against, so a wrong file fails loudly on both sides instead of silently on one.