Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions content/primers/agile-development.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
title: Agile development
---

# Agile development

Agile development is a family of ways of working built on short cycles, working software and frequent feedback. Rather than planning everything up front, an agile team delivers a small, usable piece, learns from it, and adjusts. The term comes from the *Manifesto for Agile Software Development*, written in 2001 by seventeen practitioners who had each been developing lighter alternatives to heavyweight processes.

## The values

The manifesto states four preferences. Its authors value the items on the left more, while still valuing those on the right:

- Individuals and interactions over processes and tools.
- Working software over comprehensive documentation.
- Customer collaboration over contract negotiation.
- Responding to change over following a plan.

Twelve principles follow, including delivering working software frequently, welcoming changing requirements, keeping a sustainable pace, and reflecting regularly on how to become more effective. The full text is short and worth reading at [agilemanifesto.org](https://agilemanifesto.org/).

## The cycle

```mermaid
flowchart LR
P[Plan a small increment] --> B[Build and test]
B --> R[Review with users and stakeholders]
R --> L[Reflect and improve]
L --> P
```

[[CAPTION:Figure]] The feedback loop at the heart of agile work.

## Common practices

- **A prioritised backlog**: one ordered list of work, with the most valuable items at the top, refined continuously.
- **User stories**: small descriptions of value from a user's point of view ("As a field engineer, I want to see a device's last contact time, so that I can tell if it is offline"), each with acceptance criteria.

Check warning on line 35 in content/primers/agile-development.md

View workflow job for this annotation

GitHub Actions / build

PyDoc.SentenceLength

Sentence is 40 words long. Try to keep it under 30.
- **Short iterations** of one to four weeks, or a continuous flow of small items.
- **Definitions of ready and done**: shared checklists for when work can start and when it is truly finished.
- **Daily coordination**: a short meeting on progress towards the goal and anything blocking it.
- **Reviews and retrospectives**: show the work to stakeholders; then discuss how the team itself can improve.
- **Technical practices**: [continuous integration](cicd-pipelines.md), automated [testing](testing-strategies.md), [code review](code-review.md) and refactoring. Without them, short cycles slowly fill with [technical debt](technical-debt.md).

## Frameworks

- **[Scrum and Kanban](scrum-vs-kanban.md)** are the two most common team-level approaches.
- **Extreme Programming (XP)** focuses on engineering practices: pair programming, test-driven development, continuous integration and simple design.
- **Lean software development** applies ideas from Toyota's production system: remove waste, limit work in progress, optimise the whole flow.
- **Scaling frameworks** such as SAFe, LeSS and Nexus coordinate many teams. They add structure and overhead, so use the lightest that works.

## Pitfalls

- **Ceremony without the point**: stand-ups, sprints and story points with no real feedback from users is "agile" in name only. See cargo cult programming in [anti-patterns](anti-patterns.md).
- **No architecture**: agile does not mean no design. Make the decisions that are hard to change early and record them as [ADRs](architecture-decision-records.md).
- **Hardware reality**: physical products have lead times and certification. Iterate on firmware, software and prototypes, and plan hardware milestones explicitly.

## Where next

- [Scrum and Kanban](scrum-vs-kanban.md) compares the two common frameworks.
- The [Templates](../templates/index.md) section has definition of ready and definition of done checklists.
51 changes: 51 additions & 0 deletions content/primers/anti-patterns.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
title: Anti-patterns
---

# Anti-patterns

An anti-pattern is a common response to a problem that looks reasonable at the time and turns out badly. Like a design pattern, it has a name, which makes it easier to spot and talk about in a review. Most anti-patterns are not caused by bad engineers; they are what happens to good code under deadline pressure when nobody steps back.

## Structural anti-patterns

| Anti-pattern | What it looks like | The way out |
| --- | --- | --- |
| Big ball of mud | No visible structure; everything calls everything | Find seams, draw module boundaries, enforce them with tooling |
| God object | One class or module that knows and does far too much | Split by responsibility; move behaviour to the data it uses |
| Spaghetti code | Control flow that jumps around with no clear structure | Extract functions, add tests, then restructure |
| Lava flow | Dead or half-finished code that nobody dares remove | Find out what it does, test the behaviour you need, delete the rest |
| Lava layer | Several generations of technology for the same job (three ways to access the database) | Pick one, migrate the others deliberately, finish the migration |
| Shotgun surgery | One logical change needs edits in many places | Bring the scattered knowledge into one module |

[[CAPTION:Table]] Anti-patterns in the structure of code.

## Behavioural anti-patterns

These are about how teams make decisions rather than the shape of the code.

- **Golden hammer**: using a familiar tool for everything, whether or not it fits. The cure is to state the problem before naming the tool.
- **Cargo cult programming**: copying code or practices without understanding why they work. Daily stand-ups with no shared goal, or configuration pasted from a forum, are typical. Ask what each part is for.
- **Premature optimisation**: making code faster, more complex or harder to read before measuring whether speed matters there. Measure first; optimise the hot path; keep the rest simple.
- **Not invented here**: rebuilding something that a well-maintained library already does.

## Spotting them early

Anti-patterns grow slowly, so look for the trends:

- Files or classes that appear in most changes, or that keep growing.
- Changes that need edits in many unrelated places.
- Areas that people avoid or that have no tests.
- Code that nobody can explain in a review.

Static analysis can measure some of this (size, complexity, coupling, duplication). See [static code analysis](static-code-analysis.md).

## Fixing them

Rewrites rarely work. Improve the code in small, tested steps, with each step leaving it working. Michael Feathers' *Working Effectively with Legacy Code* is the standard guide. The strangler fig approach, where new code slowly replaces old code behind a stable interface, works well for larger areas.

Record the decision to tolerate or remove an anti-pattern as [technical debt](technical-debt.md), so it is visible and scheduled rather than forgotten.

## Where next

- [Design principles](design-principles.md) and [design patterns](design-patterns.md) describe what good looks like.
- The [Guides](../guides/index.md) section covers code review and refactoring in more depth.
14 changes: 14 additions & 0 deletions content/primers/apis-and-data.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
title: APIs and data primers
---

# APIs and data primers

Systems talk to each other through interfaces, and the interface is a contract: once other teams or devices depend on it, it is expensive to change. These primers cover the common styles and formats.

- [REST APIs](rest-apis.md): resources, HTTP methods and status codes.
- [OpenAPI and AsyncAPI](openapi-and-asyncapi.md): describing request-response and event-driven interfaces.
- [Data formats](data-formats.md): JSON, YAML and Protocol Buffers.
- [CBOR and compact binary formats](cbor.md): encoding data for constrained devices and networks.

The [Guidelines](../guidelines/index.md) and [Standards](../standards/index.md) sections set the rules for API design here; these primers explain the ideas behind them.
62 changes: 62 additions & 0 deletions content/primers/architecture-decision-records.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
title: Architecture decision records
---

# Architecture decision records

An architecture decision record (ADR) is a short document that captures one significant decision, why it was made and what follows from it. A set of ADRs, kept in order next to the code, becomes the history of how a system got to be the shape it is.

## Why bother

Code shows what was built, but not why. Six months later nobody remembers why the team picked PostgreSQL over a document store, or why the gateway buffers messages rather than dropping them. Without that context, people either repeat old arguments or undo a decision without knowing what it protected. An ADR takes ten minutes to write and saves that.

ADRs also help new joiners: reading the decision log is one of the quickest ways to understand a system.

## What goes in one

Michael Nygard's original format is still the most common, and it is deliberately small:

| Section | What it says |
| --- | --- |
| Title | A short noun phrase, numbered: "ADR 7: Use MQTT for device telemetry" |
| Status | Proposed, accepted, deprecated or superseded (by which ADR) |
| Context | The forces at play: requirements, constraints, what has been tried |
| Decision | What we will do, in active voice: "We will..." |
| Consequences | What becomes easier, what becomes harder, what we now have to do |

[[CAPTION:Table]] The sections of a Nygard-style ADR.

Longer templates such as MADR add the options considered and the pros and cons of each. That is worth doing for a contested decision, and overkill for most.

## Lifecycle

An ADR is never edited once it is accepted, apart from its status. When a decision changes, write a new ADR that supersedes the old one and link the two. The log is append-only, so the reasoning at each point stays visible.

```mermaid
stateDiagram-v2
[*] --> Proposed
Proposed --> Accepted: agreed
Proposed --> Rejected: not agreed
Accepted --> Deprecated: no longer relevant
Accepted --> Superseded: replaced by a newer ADR
```

[[CAPTION:Figure]] The states an ADR moves through.

## What deserves an ADR

Write one when a decision is hard to reverse, affects more than one team or component, or was argued about. Typical examples are the choice of a database, a messaging protocol, an authentication scheme, a deployment platform, or a rule such as "all services publish events in CloudEvents format". Do not write one for every library upgrade.

## Practical tips

- Keep ADRs in the repository they describe, in a folder such as `docs/adr/`, numbered in order. Review them in pull requests like code.
- Write them when the decision is made, not afterwards. A proposed ADR is a good way to start the discussion.
- Keep each one to a page. If the context needs more, link to a design document or RFC.
- Tools such as `adr-tools` or `log4brains` help, but a text editor and a template are enough.

## Where next

- The [Templates](../templates/index.md) section has an ADR template ready to copy.
- The [Handbook](../handbook/index.md) covers how ADRs fit into architecture governance and review.
- Michael Nygard's 2011 post, [Documenting architecture decisions](https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions), started the practice.
- [adr.github.io](https://adr.github.io/) collects templates and tools.
20 changes: 20 additions & 0 deletions content/primers/architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
title: Architecture primers
---

# Architecture primers

Software architecture is the set of decisions about a system that are expensive to change later. They cover how it is split into parts, how those parts talk, where data lives, and which qualities (performance, security, availability, cost) win when they conflict. These primers introduce the vocabulary and the common styles.

- [Architecture decision records](architecture-decision-records.md): writing down why, not only what.
- [The C4 model](c4-model.md): diagrams at four levels of zoom.
- [Design principles](design-principles.md): SOLID, DRY, KISS and YAGNI.
- [Design patterns](design-patterns.md): the Gang of Four catalogue and how to use it.
- [Anti-patterns](anti-patterns.md): the shapes that code drifts into when nobody is looking.
- [Hexagonal architecture](hexagonal-architecture.md): ports, adapters and keeping the domain clean.
- [Domain-driven design](domain-driven-design.md): modelling the business and drawing boundaries.
- [Event-driven architecture](event-driven-architecture.md): components that react to things that happened.
- [Modular monolith or microservices](modular-monolith-vs-microservices.md): choosing how to deploy the parts.
- [Digital twins and device shadows](digital-twins-and-device-shadows.md): keeping a cloud copy of a device's state.

The [Handbook](../handbook/index.md) goes deeper into each of these, with the trade-offs and the review process. The [Glossary](../glossary/index.md) defines the terms.
60 changes: 60 additions & 0 deletions content/primers/bootloaders.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---
title: Bootloaders
---

# Bootloaders

A bootloader is the first code that runs when a microcontroller starts. Its job is to check that the application firmware is present and trustworthy, start it, and, when asked, install a new version. Because the bootloader itself is rarely or never updated, it must be small, simple and correct the first time.

## What happens at power-on

```mermaid
flowchart TD
R[Reset] --> ROM[ROM boot code in the chip]
ROM --> BL[Bootloader in flash]
BL --> U{Update waiting?}
U -- yes --> I[Verify and install new image]
U -- no --> V{Current image valid and signed?}
I --> V
V -- yes --> APP[Jump to the application]
V -- no --> F[Fall back to previous image or recovery mode]
```

[[CAPTION:Figure]] A typical boot sequence.

Many microcontrollers have a ROM bootloader from the vendor that can load firmware over UART or USB in the factory. The bootloader discussed here is your own, in flash, which runs on every start.

## Memory layouts for updates

| Layout | How it works | Trade-off |
| --- | --- | --- |
| Single slot | The bootloader receives the new image and overwrites the old one | Least flash; a failed write leaves the device without an application, so it needs a recovery path |
| Dual slot (A/B) with swap | The new image is written to a second slot; the bootloader swaps the slots and can swap back if the new image fails | Needs twice the space, or external flash for the second slot; safest |
| Dual slot, execute in place | Both slots can run; the bootloader picks the newer valid one | No copying; images must be built for their slot address |

[[CAPTION:Table]] Common flash layouts.

## Secure boot

Secure boot means the device runs only firmware signed by the manufacturer:

- The image is signed with a private key held securely by the build system (an HSM or a signing service).
- The bootloader holds the matching public key, or a hash of it, in memory that cannot be changed (one-time-programmable fuses or protected flash).
- At every start, the bootloader checks the signature (ECDSA P-256 and Ed25519 are common) before running the image.
- The bootloader itself is protected by the chip's own root of trust where the hardware supports it, giving a chain of trust from silicon to application.

Add **anti-rollback** protection with a security counter in the image, so an attacker cannot install an older version with a known vulnerability.

## Good habits

- Keep the bootloader small and its features few. Every feature is code you cannot easily fix.
- Mark a new image as "pending" and confirm it only after the application has started and connected successfully. If it never confirms, revert. This test-then-confirm step turns a bad update into a short outage instead of a dead device.
- Protect against power loss at every step of an update; assume the battery can fail mid-write.
- Enable the [watchdog](watchdog-timers.md) in the bootloader too.
- Use an established open-source bootloader rather than writing your own: MCUboot (used by Zephyr, Mbed and others) supports signing, encryption, A/B slots and rollback protection.

## Where next

- [Firmware over the air](firmware-over-the-air.md) covers getting the image to the device.
- [PKI and certificates](pki-and-certificates.md) and [cryptography basics](cryptography-basics.md) explain the signatures.
- The [MCUboot documentation](https://docs.mcuboot.com/) describes a well-tested design.
62 changes: 62 additions & 0 deletions content/primers/c4-model.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
title: The C4 model
---

# The C4 model

The C4 model, created by Simon Brown, is a way of drawing software architecture as a set of maps at different levels of zoom. Each level answers a different question for a different reader, and each one is drawn with plain boxes and labelled arrows rather than a special notation.

## The four levels

| Level | Shows | Typical reader |
| --- | --- | --- |
| 1. System context | The system as one box, the people who use it and the other systems it talks to | Everyone, including non-technical stakeholders |
| 2. Container | The separately deployable or runnable parts: web app, API, database, message broker, device firmware | Architects, developers, operations |
| 3. Component | The main building blocks inside one container and how they interact | Developers working on that container |
| 4. Code | Classes, functions or tables inside one component | Rarely drawn by hand; generate it if you need it |

[[CAPTION:Table]] The four levels of the C4 model.

"Container" here means anything that runs or holds data on its own. It has nothing to do with Docker, which confuses people at first.

Most teams find the first two levels give most of the value. Component diagrams are useful for a complex container. Code diagrams go out of date as soon as they are drawn.

## A context diagram

```plantuml
@startuml
!include <C4/C4_Context>
Person(user, "Field engineer", "Installs and checks devices")
System(platform, "Device platform", "Collects telemetry and manages devices")
System_Ext(idp, "Identity provider", "Signs users in")
System_Ext(devices, "Devices", "Sensors in the field")
Rel(user, platform, "Uses", "HTTPS")
Rel(devices, platform, "Sends telemetry", "MQTT over TLS")
Rel(platform, idp, "Authenticates users with", "OpenID Connect")
@enduml
```

[[CAPTION:Figure]] A level 1 system context diagram drawn with C4-PlantUML.

## Rules that make the diagrams work

- Every box has a name, a type and a one-line description of what it does.
- Every arrow is one-way and labelled with what flows and, at container level, how (protocol or technology).
- Every diagram has a title and a key if it uses colour or shape to mean something.
- One diagram per question. If a diagram needs a scroll bar, split it.

## Supporting diagrams

C4 also allows a few extra views when they help. A system landscape shows all the systems in an organisation; a dynamic diagram shows the sequence for one use case; a deployment diagram shows which containers run on which infrastructure.

## Tools

- **C4-PlantUML** adds C4 shapes to PlantUML. PlantUML's standard library includes it, so `!include <C4/C4_Container>` works without downloading anything.
- **Structurizr** keeps one model in a text file (the Structurizr DSL) and draws every view from it, so the levels never disagree.
- **Mermaid** has experimental C4 support, good enough for simple context diagrams.

## Where next

- [PlantUML and Mermaid](plantuml-and-mermaid.md) introduces diagrams as code.
- The [Handbook](../handbook/index.md) shows how C4 views fit into an architecture description, and the [Templates](../templates/index.md) section has starter diagrams.
- [c4model.com](https://c4model.com/) is the official guide.
Loading
Loading