Skip to main content

New Page

---
title: "Ch. 2 — Software Architecture Fundamentals"
clipping: "[[Clippings/software-architecture-fundamentals/02-software-architecture-fundamentals.pdf]]"
status: studied
date_started: 2026-07-08
date_studied: 2026-07-20
tags: [software-architecture, isaqb, cpsa-f]
---

## Summary
The terminology backbone of the CPSA-F curriculum (iSAQB learning goals
LG 1-1 … 1-10). Defines software-intensive systems, argues that every system
inherently has an architecture ("a framework for change"), builds the core
vocabulary — building blocks, interfaces, views, architectural levels — and
closes with a bird's-eye view of the design process (Twin Peaks) and the
architect's role.

## Key points

### Why every system has an architecture
- **The magic rectangle**: functionality, quality, effort, time — the four
  axes every project is judged on. Requirements engineering and architecture
  design are the highest-leverage disciplines because both force far-reaching
  decisions at the moment of least knowledge.
- **Software-intensive system**: a system whose essential tasks are carried
  out by software building blocks. Three categories, each with a typical
  instinct: *information systems* (data-heavy, many users → layered
  architectures, data/transaction problems), *embedded systems* (physical,
  resource-constrained, safety-critical → loosely coupled processes over
  buses, scheduling/comms problems), *mobile systems* (autonomous, personal,
  intermittently connected → shared-memory processes, UI-vs-hardware
  tension). Real systems blur categories, but each points to a toolbox.
- **Every system has an architecture** — inherent, not optional; the only
  choice is explicit design vs. accident. Rausch: *"Software architecture is
  a framework for change."* Load-bearing wall analogy: architecture decides
  which parts are load-bearing (expensive to change) and which are
  decorative (cheap to change) — and that split is **relative to which
  future changes actually happen**, not a fixed property of the code.
- **Definition (ISO/IEC/IEEE 42010:2011)**: "fundamental concepts or
  properties of a system in its environment embodied in its elements,
  relationships, and in the principles of its design and evolution."
  Architecture objectives are **long-term**, often amortizing only after the
  project ends — unlike short-term project objectives (LG 1-7). Implicit
  assumptions and constraints must be made explicit (LG 1-8).

### Building blocks & interfaces
- **Building block** (deliberately not "component"): any abstraction of
  code, from function to subsystem. Three defining characteristics:
  1. *Provided and required interfaces* — provided interfaces are a
     contract to the outside world, but only honored when the block's own
     required interfaces are satisfied.
  2. *Encapsulation and interchangeability* — implementation is hidden
     behind interfaces; anything offering the same provided/required
     interfaces should be swappable without callers noticing.
  3. *Configuration and hierarchical (de)composition* — a building block
     can itself be a configuration of smaller building blocks wired
     together.
- **Interface**: a well-defined access point (syntax, behavior, errors,
  non-functional characteristics, protocols, semantics…). Interfaces can
  **never be fully specified** — Java's `Collection` documents everything
  except insert performance, which is exactly what decides `ArrayList` vs
  `LinkedList`. The architect decides which unstated aspects matter enough
  to pin down.
- **View depth**: black box (provided/required interfaces only — caller's
  view), gray box (+ technical/runtime interfaces), white box (internal
  configuration — implementer's view).
- **Who defines an interface**: standard (third party) / provided
  (exporter — most common) / required (importer — plugin style) /
  independent (neither side owns it + an adapter connects them).
  Independent maximizes decoupling but costs effort; if an adapter is used
  as a shortcut without ever generalizing the interface, "temporary"
  quietly becomes permanent.

### Describing architecture: views & levels
- **IEEE 42010 description model**: stakeholders → concerns → viewpoints
  (conventions) → views, plus documented **rationale**. Views are
  **projections** — the same 3D object casts a circle from below and a
  triangle from the side; neither view is wrong or complete on its own.
- **Four architectural levels, two dimensions** (abstraction × perspective):
  architectural style (high/functional, e.g. "3-layer web + MVC"),
  technical infrastructure (high/technical, e.g. "thin client + app
  container + relational DB"), functional **A-architecture** (domain
  building blocks), technical **T-architecture** (cross-cutting concerns:
  persistence, transactions, logging). Siedersleben: **"A and T are blood
  groups — don't mix them."**
- **Environment**: four surrounding areas, each a two-way street — project
  management, product management/requirements engineering, execution
  platform/operations (the most neglected interface), tools/dev
  environment.
- **Quality of an architecture** is relative to objectives and lifecycle —
  good architecture keeps the magic rectangle achievable. ISO 25010 gives a
  quality-attribute checklist to start from.

### Design process & the architect's role
- **Twin Peaks model**: requirements and architecture descend in parallel
  iterative spirals — effort estimates only become real once a draft
  architecture exists. Four equally weighted, **non-sequential** activities:
  analyze requirements/constraints; design views and technical concepts;
  evaluate architecture and decisions; support/review implementation.
- The architect is both a communication platform and the owner of the
  design/implementation blueprint, interfacing with nearly every other
  role on the project.

## One example, all the vocabulary — `DocumentStore`

One running scenario to hold the terms together, built from the two real
incidents discussed below: a `DocumentStore` building block that saves
files to a cloud provider.

| Concept | In `DocumentStore` |
|---|---|
| Building block | `DocumentStore` itself — an abstraction from "save a file" down to whatever actually implements it |
| Provided interface | `save(file) -> id`, `fetch(id) -> file` — the promise made to every caller |
| Required interface | A `CloudClient` (network + auth) — the promise only holds if this dependency is satisfied |
| Encapsulation & interchangeability | Swap `GoogleDriveClient` for `OneDriveClient` behind the same `DocumentStore` interface; callers shouldn't notice |
| Configuration & decomposition | `DocumentStore` = `RetryPolicy` + `Cache` + a `CloudClient` adapter, wired together internally |
| Interface incompleteness (the `Collection` lesson) | `save()` doesn't document max file size or latency — same kind of gap as `Collection` omitting insert performance; someone still has to decide if the gap matters |
| Interface definer type | Independent interface + adapter: `DocumentStore` belongs to neither Google nor Microsoft; `GoogleDriveAdapter` / `OneDriveAdapter` implement it |
| Black / gray / white box | Caller sees black box (`save`, `fetch`); ops sees gray box (retry/timeout config); adapter author sees white box (raw Drive API calls) |
| A/T blood groups | `DocumentStore` and its adapters are pure T-architecture; the mistake would be naming it `ClaimAttachmentStore` and hardcoding claim logic inside — A leaking into T |
| **The bug actually hit** | No independent interface existed — code called `SaveToGoogleDrive()` directly, a *provided* interface named after its *required* dependency. Migrating providers meant hunting every call site instead of writing one new adapter. |

**The one habit that would have prevented both real incidents below**: name
interfaces after what they *promise* (the capability), never after who
currently *provides* them or which domain concept happens to *call* them.

## Discussion notes
Three probes, all resolved with real examples from Mehdi's own work:

1. **Load-bearing walls / framework for change.** Worked through a 40-page
   static HTML site: nav duplication and content-in-markup are decorative
   under "keep the site current," but become load-bearing the moment a
   requirement like i18n arrives — because now every hardcoded string is
   something a translation process must touch. Mehdi's own framing: *"the
   whole HTML content became a load bearing [wall] that was not before."*
   Fix while cheap = separate content from structure (externalize strings)
   before the requirement lands, not after.
2. **A/T mixing, case 1 — ORM naming.** Mehdi had custom ORM functions
   named after domain concepts (`claim()`, `filing()`, `process()`) instead
   of technical ones. Domain vocabulary had leaked into the T-architecture's
   *provided interface names*, so a later business-vocabulary change forced
   a rename across every consuming service — a technical migration that
   should have been invisible to callers instead broke all of them. Fixed
   by renaming the technical side back to technical terms; the rename
   itself was costly precisely because the interface names had become a de
   facto contract.
3. **A/T mixing, case 2 — `SaveToGoogleDrive()`.** A different but related
   failure: the interface was named after a *required* dependency (Google
   Drive) rather than the *capability* it provides. No adapter layer
   existed, so when the provider needed to change to OneDrive, the fix was
   hunting down and manually verifying every call site — the cost an
   independent-interface-plus-adapter design would have avoided by
   confining the change to one new adapter.

**Cross-link**: LG 1-8 (implicit assumptions → explicit statements) is the
same phenomenon as the METR paper's "AI lacks tacit repo context"
([[digests/metr-early-2025-ai-developer-productivity-rct]]) — knowledge
that lives only in maintainers' heads, or in a function name nobody
questioned, is invisible to any newcomer, human or AI.

## Concepts
- [[concepts/software-architecture]] — architecture as inherent, framework
  for change, load-bearing walls relative to anticipated change
- [[concepts/building-blocks-and-interfaces]] — the three characteristics,
  interface completeness, interface definer types, the `DocumentStore`
  example
- [[concepts/architectural-views-and-levels]] — IEEE 42010 description
  model, four levels, A/T blood groups
- [[concepts/twin-peaks-model]] — requirements/architecture co-evolution,
  four non-sequential design activities (light for now — grows with ch. 3)

## Open questions
- "Test your knowledge" section (LG 1-1 … 1-10) not yet used — good
  material for a future review session.
- How do the four architectural levels map onto the Twin Peaks design
  activities? Revisit in ch. 3 (Designing Software Architectures).
- When is it worth paying for an independent interface + adapter *upfront*
  versus accepting the risk and refactoring later? (effort vs. risk
  tradeoff — ties into Twin Peaks' point that estimates only firm up once a
  draft architecture exists)