Skip to content

Software Design Patterns in Rust

Glossary

129 terms from Software Design Patterns in Rust, in plain words, each with the chapter that teaches it.

#

#[cfg(test)]
An attribute that compiles the code after it only when building tests. It is used on the `mod tests` block so test code never ships in the real program.
#[test]
An attribute marking a function that the test runner calls for you. A test passes if it doesn't panic.

A

Abstract factory
A trait with several make methods that builds a family of matching parts together, such as a carrier and its label printer. Callers get a consistent set without naming concrete types.
Adapter
A wrapper that holds a library value with an awkward shape and implements your trait, translating each call. Kettle & Crane's UpsCarrier adapts UpsApi, which wants line counts and answers in cents.
Anti-pattern
A common answer to a design problem that looks reasonable but causes more trouble than it solves. Examples are the god object and magic numbers.
API (application programming interface)
The set of functions or calls a library or service offers to other code. UpsApi stands in for the UPS rate service's API.
assert_eq!
A macro used in tests that panics if two values are not equal, which makes the test fail. It is how the tests check that totals like 467.5 stay the same.
Axum
A Rust web framework built on the tokio async runtime. It shows dependency injection through `State`, a registry of routes mapping paths to handler functions, and middleware added as layers.

B

Behavioral pattern
A pattern about how objects share work and decisions and talk to each other. Strategy, Observer and Command are examples.
Borrow checker
The part of the Rust compiler that checks every reference follows the ownership and borrowing rules. Adding `.clone()` just to make its errors go away is a bad habit, because it hides the real ownership problem and copies data for nothing.
Box
An owning pointer that puts a value on the heap. `Box<dyn Rule>` lets values of different types, whose sizes differ, sit together in one Vec.
Builder
A pattern that collects the parts of a complicated value one method call at a time, then checks and creates it in `build()`. Each step takes and returns `self`, so calls chain.

C

Cache
Saved answers kept so the same work isn't repeated. The CachedCarrier proxy remembers a quote per line count and skips the real carrier the second time.
cargo
Rust's build tool and package manager. `cargo test` runs tests, `cargo run` builds and runs, and Cargo.toml describes the project (such as the `shop` crate).
Chain of responsibility
A pattern where a request passes along a line of handlers, each of which rejects it or passes it on. Kettle & Crane's order checks (known carrier, under limit) work this way.
Characterization test
A test that records what existing code does today, right or wrong, so you can refactor safely. For example, the old `place_order` totals of 467.5, 42.6 and 31.25 become expected values that the redesigned code must still produce.
Clone
A trait whose `clone()` makes an independent copy of a value, field by field. The prototype pattern uses it, and it should be used for a real second owner, not to silence the borrow checker.
Closure
A small inline function that can use values from the code around it, such as `|s| s * 0.9`. Closures can be stored in variables and passed to other functions.
Cohesion
How closely the things inside one piece of code belong together. A function that only works out shipping has high cohesion, which is good.
Command
A pattern that turns an action into an object with `execute` and `undo`, so actions can be stored, queued and reversed. The cart's AddItem is an example.
Composite
A pattern where an item and a group of items answer the same method, so a group can hold other groups. A gift Bundle's price is the sum of its parts' prices.
Composition
Building a struct from other values it holds and hands work to ("has-a"), instead of inheriting from a parent. A Product holds a pricing part and a wrapping part.
Composition root
The one place, usually `main`, where the real parts are built and handed to the code that needs them. Everything else just receives its dependencies.
const
A named value fixed at compile time, such as `const FREE_SHIPPING_AT: f64 = 75.0;`. It is the fix for magic numbers.
Constructor injection
Passing a struct the dependencies it needs through its `new` function, so it keeps them instead of creating them. OrderLog::new takes a repo, clock and notifier.
Copy-paste programming
An anti-pattern of repeating the same code in several places instead of sharing one function, so one bug fix is always missed somewhere.
Coupling
How much one piece of code depends on the details of another. Loose coupling is good: changing the discount code shouldn't break shipping code.
Crate
Rust's unit of packaged code, either a program or a library. Examples are the `shop` crate and the external axum and tokio crates.
Creational pattern
A pattern about how objects get built, putting the "which type, which settings?" decision in one place. Factory, Builder and Singleton are examples.
CSV (comma-separated values)
A plain-text table format with one row per line and columns separated by commas. Jo's report uses lines like `KC-1001,467.50`.

D

Data race
A bug where two threads access the same data at once and at least one changes it, giving unpredictable results. It is why Rust makes changeable globals awkward.
Decorator
A wrapper with the same interface as the value it wraps that does a little extra work and passes the call on. Priya's LoggedCarrier logs each quote.
Default (trait)
A standard trait that gives a type a ready-made starting value. It works with `..Default::default()` to fill unnamed fields.
Default method
A trait method with a body that implementing types get for free and may override. The template method pattern uses one to run the fixed steps.
Default-method surprise
Rust's version of the fragile base class: changing a trait's default method affects only the types that didn't copy or override it. Adding tax to the default `total` would tax only Retail.
Delegation
Handing a job to a value you hold instead of doing it yourself. Product::total asks its pricing part, then its wrapping part, and adds the answers.
Dependency
Anything a piece of code needs to do its job, such as a database, a notifier or the clock.
Dependency injection
Giving code its dependencies from outside instead of letting it create or find them. That lets tests pass in fakes, so OrderLog can run without disk or the real clock.
Dependency inversion principle (DIP)
The SOLID rule that high-level code shouldn't depend on low-level details. Both depend on a trait, and the detail is passed in.
derive
An attribute that asks the compiler to write standard trait code for a struct or enum, such as Clone, Debug, PartialEq or Default.
Design pattern
A named, reusable solution to a common design problem. It's a shape for your code, not a library to copy.
DI container
A library that builds and connects an application's objects automatically from rules. Rust programs usually wire parts by hand in main.
Drop
The trait whose `drop` method Rust runs automatically when a value goes out of scope. It is how Rust does cleanup (RAII).
Dynamic dispatch
Calling a method through `dyn Trait`, where the exact method is looked up while the program runs. This lets different types share a Vec, at the cost of a pointer and an indirect call.

E

enum
A Rust type whose value is exactly one of several named variants. Enums suit things like a customer `Kind` or an order `Status`, because no invalid value can exist.
Event bus
The subject in the Observer example: a struct that stores listeners by event name and calls them when an event is emitted.

F

Facade
One simple function or struct in front of several parts, so only it knows the steps. checkout prices, quotes shipping and saves an order for every caller.
Factory
A function that makes values, such as create_carrier turning a name into the right carrier, so callers never need an if chain.
Factory method
A pattern where a trait has a required method (like make_carrier) that each implementer uses to choose what to build, while default methods use the result.
Fake
A simple working stand-in for a real part, such as an in-memory repository or a notifier that keeps messages in a list. Tests use fakes to avoid disk, network or real email.
Fixture
Test setup code that builds fresh inputs for each test. Rust has no built-in fixtures, so a helper function like make_log does the job.
Flyweight / Bridge / Mediator / Memento / Visitor / Interpreter
Six further Gang of Four design patterns. Flyweight shares objects to save memory, Bridge splits a concept from its implementation, Mediator has one object manage how others talk, Memento saves state to restore later, Visitor adds operations without editing types, and Interpreter models a small language's grammar as types.
Fragile base class
A problem where a change to a parent's code quietly breaks its children.
Framework
Code that runs your program and calls your code at the right moments, like the Rust test runner or Axum. A library, by contrast, is called by you.
Function pointer
A value of type `fn(...) -> ...` that refers to a plain function. It can't capture values, unlike a closure.

G

Gang of Four
The nickname of the four authors of the 1994 book *Design Patterns*, which lists 23 patterns in three families.
Generic
Code written for any type that meets a trait bound, like `R: Repo`. The compiler builds a separate copy for each type used, which is fast but fixed at compile time.
Global mutable state
A `static` that any code can change, like the old ORDERS list. It hides dependencies and makes parallel tests interfere with each other.
God object
One struct or module that does far too much, like a Shop with 40 methods. The fix is to split it by reason to change.
Golden hammer
Using one favorite tool, such as a trait, builder or factory, for every problem whether or not it fits.

H

Handler
A link in a chain of responsibility that handles a request or passes it on. In Axum it is also a route's function.
Has-a / is-a
The test for choosing composition or inheritance: a product *has a* pricing rule (compose), while an error *is a* kind of Error (trait). Rust has no inheritance.
HashMap
A standard collection that maps keys to values. It is a natural fit for an event bus's listeners, a registry, or a cache.
Hook
The step a template method leaves open for the caller to fill in, such as a closure that formats a report row.

I

Inheritance
A feature of class-based languages where a child class reuses its parent's code. Rust has none and uses traits and composition instead.
Injected clock
A function passed in that returns the current unix time, so tests can supply a fixed time instead of the real one.
Interface
The methods code expects a value to have. In Rust a trait writes the interface down and the compiler checks it.
Interface segregation principle (ISP)
The SOLID rule that code shouldn't depend on methods it doesn't use, so keep traits small. USPS only needs a Quoter, not a Tracker.
Inversion of control
A framework calling your code instead of your code calling it: "don't call us, we'll call you". The test runner calling your `#[test]` functions is an example.
Iterator
Something that steps through a collection one item at a time without exposing how it's stored. Every `for` loop uses one, and you can implement the `Iterator` trait yourself.

J

JSON (JavaScript Object Notation)
A text format for structured data using braces, brackets and quoted keys. The old place_order writes orders to `orders.json`.

K

KISS (Keep it simple)
A design rule: of two working designs, choose the one that's easier to read.

L

Library
Tools your code calls, like `sort_by`. Compare a framework, which calls your code.
Liskov substitution principle (LSP)
The SOLID rule that a stand-in must work wherever the original works. In Rust, every type implementing a trait must keep the trait's promises, as a LockedCard that panics in `top_up` does not.
Listener
A function or closure that wants to hear about an event and is called when it's emitted. send_email and log_sale are listeners.

M

Magic number
A number written in code with no name, like `75.0` or `0.85` in the old place_order. Give it a name with a `const`.
Middleware
Code that every web request passes through, such as logging or login checks, and which can stop the request. It is a chain of responsibility.
Mock
A test stand-in that also records how it was called, so a test can check those calls. It differs from a fake, which is a simple working version, and from a stub, which returns fixed answers.
mod
The keyword that declares a module. In a multi-file crate, `main.rs` needs a line such as `mod discounts;` for the file `discounts.rs` to count as part of the program.
monkeypatching
Replacing parts of running code, usually in tests, to fake a dependency. Rust has none, and injection replaces it.
move (closure)
A keyword that makes a closure take ownership of the values it uses. It is needed when a boxed closure outlives the function that made it, like percent_off's `pct`.
Mutex
A lock that lets one thread or piece of code at a time use the value inside. It is how Rust allows a changeable `static`, via `lock().unwrap()`.
MVC / hexagonal architecture / CQRS / microservices
Larger-scale architecture patterns that apply design ideas such as separation of responsibilities and loose coupling to whole applications. Examples are MVC's split into model, view and controller, and splitting a system into many small independent services.

O

Observer
A pattern where the code where something happens (the subject) keeps listeners and calls each without knowing what they do. A new reaction, like Alex's packing slip, is one more `on` line.
OnceLock
A standard-library slot that is filled once by the first `get_or_init` call and then hands out the same shared reference. It is Rust's safe way to build a read-only singleton.
Open/closed principle (OCP)
The SOLID rule that code should be open for extension but closed for modification: add behavior with new code, such as a new `impl Rule`, instead of editing working code.
Over-engineering
Building more structure than the problem needs, like a factory, registry and builder for a single discount.
Ownership
Rust's rule that each value has one owner, and passing it by value moves it. A consuming builder takes `self` by value, and `Rc` gives a value several owners.

P

panic!
A macro that stops the program with an error message. The old place_order panics on an unknown carrier.
Plugin
Code, usually a crate, that adds a feature to a framework without changing the framework. It is open/closed applied to a whole tool.
Premature abstraction
Adding a trait, builder or factory before two or three real cases exist.
Prototype
A pattern that copies a ready-made value and changes a little, like Bloom Café's weekly order template. In Rust it is `Clone` plus `..base.clone()`.
Proxy
A same-interface wrapper that controls access to the real value. It might create it late, check permissions, or cache answers like CachedCarrier.
Publish/subscribe
Another name for the observer pattern, usually with a message system between the publisher and the subscribers.

R

RAII (Resource Acquisition Is Initialization)
Tying cleanup to a value's life: Rust calls `drop` when the value goes out of scope, as with Receipt printing "closing".
Rc<RefCell<..>>
A pair of standard types for sharing changeable data: `Rc` gives several owners, and `RefCell` checks borrowing at run time instead of compile time. Overuse turns borrow errors into panics.
Registry
A table from names to types or functions that is looked up when needed, such as Axum's routes mapping paths to handlers or a table of carriers.
Repository
An interface that stores and finds things so nothing else knows how they're stored. MemoryRepo keeps orders in a private Vec, and a JsonRepo could use a file.
Result
Rust's way to report success or failure: `Result` is `Ok(value)` or `Err(message)`, and `Option` is `Some` or `None`. The `?` operator returns an error early, and `ok_or` turns a missing Option into an error.
Rule of three
Write it once, notice the repeat the second time, and extract a shared version on the third.
rustc
The Rust compiler, installed by rustup. Compiling a file with `rustc --edition 2021 -O file.rs` needs the edition flag, because plain `rustc` assumes the old 2015 edition.

S

serde
A Rust library for converting data to and from formats like JSON. It does the work of a hand-written JSON writer, and is what real programs use for this.
Service locator
A global registry that code asks for its dependencies. It hides what code needs and forces tests to change the global, the opposite of injection.
Simple factory
One function that knows every type and turns a name into the right value, such as create_carrier("ups"). A new carrier is a struct, an impl and a match arm.
Single responsibility principle (SRP)
The SOLID rule that a piece of code should have one reason to change. price_items changes only with line pricing, apply_discount only with offers.
Singleton
A single value that everyone shares. In Rust it is a `static`, using `OnceLock` for set-once data or `Mutex` for changeable data, and overuse leads to global state.
SKU (stock keeping unit)
A product's code used to identify an item, such as ESP-5LB or MUG-BLUE.
SOLID
Five design principles named by their first letters: single responsibility, open/closed, Liskov substitution, interface segregation and dependency inversion.
Spaghetti code
Code with ifs, globals and jumps so tangled that no path is easy to follow.
State
A pattern that allows only the moves an order may make. It can be a lightweight enum plus a `match`, or one type per state held in a `Box<dyn State>`.
State machine
Something that is always in exactly one of a fixed set of states, with rules for the allowed moves between them. An order goes placed, paid, shipped, delivered, and can be cancelled before shipping.
static
A global that lives for the whole program. Rust lets you change one only behind a `Mutex` (or via `unsafe` with `static mut`).
Static dispatch
Accepting "anything with this trait" via `&impl Rule` or generics, where the compiler builds one copy of the function per type. It suits one known type.
Strategy
One interchangeable way of doing a job, where all versions share a shape. In Rust it is a function or closure, like the discount functions taking a subtotal and returning a discounted one.
Struct update syntax
The `..base` form that fills fields you didn't name from another struct, as in `OrderTemplate { qty: 20, ..weekly.clone() }`.
Structural pattern
A pattern about how values fit together: connecting mismatched pieces or wrapping one value in another. Adapter and Decorator are examples.
Stub
A test stand-in that returns fixed answers, such as a clock that always says 4:00 p.m.
Subject
In the observer pattern, the object where events happen and whose listeners are notified, like the EventBus.

T

Template method
A pattern that fixes a job's steps in one place and leaves one step (a hook) for callers. It can be a closure argument or a trait default method calling required methods.
Trait
A named set of methods a type promises to have, written with `trait` and implemented with `impl`. It is Rust's interface and replaces inheritance for shared behavior.
Trait object
A value used through `dyn Trait`, usually in a `Box`, so different types can share one type. `Box<dyn Pricing>` holds any value implementing Pricing.
Transition
A move from one state to another in a state machine, such as Placed to Paid.
Tree
Pieces holding smaller pieces, down to single items, like a gift crate holding a box holding items. Composite builds a tree.
Type explosion
The growth of one new struct for every mix of choices: two choices make 4 types, three make 8, as with GiftWrappedWholesale.

U

Undo stack
A list of commands that have run, newest last, so Undo can pop and reverse the latest one.
Unix time
A time stored as the number of seconds since 1 January 1970 UTC. Orders store `placed` this way, and 1,792,771,200 is Oct 23, 2026, 16:00 UTC.
unsafe
A Rust keyword marking code the compiler can't fully check for safety. Changing a `static mut` needs it, so safer tools such as `OnceLock` or `Mutex` are used for shared global values instead.

W

Wrapper
A value that holds another and stands in front of it. Adapters, decorators and proxies are wrappers.

Y

YAGNI (You aren't gonna need it)
A design rule: don't build for a need until it's real, such as a factory "in case we ever sell tea".