Concepts & practices

Once by the book.
Once in the choices you make.

Understand an idea once, then recognize it wherever it matters. Explore how languages run, how we model and store data, how we handle failure and coordinate work, and how we check that it all behaves as intended.

Moving in. 74 of 74 topics have lessons; they're moving over from the old site.

74 topics

Moving in 74 of 74 topics have lessons, which are moving over from the old site. Planned topics show where the catalog is going.

Design principles and language mechanisms

The ideas underneath the patterns and the tools each language gives you.

Concept moving

Composition over inheritance

Follow an invoicing API from a class tree to routes built from parts you can list

TypeScriptGo
Concept moving

Coupling & cohesion

What belongs together and what should be able to change independently

TypeScriptGo
Concept moving

Inversion of control

Who owns the flow of execution; distinguish it from dependency injection

TypeScriptGo
Concept moving

Dependency injection

Supply collaborators from outside; compare manual wiring and containers

TypeScriptGo
Concept moving

Dependency direction

Choose which code depends on which, and where an interface should live

TypeScriptGo
Concept moving

Currying & partial application

Build functions in stages or supply some of their arguments ahead of time

TypeScriptGo
Concept moving

Memoization

Remember a result so the same inputs do not repeat the work

TypeScriptGo
Concept moving

Idempotence

Repeat an operation without adding effects beyond its first successful application

TypeScriptGo
Concept moving

Module

Give a piece of code a small public surface and a private implementation

TypeScriptGo
Concept moving

Mixin

Compose reusable behavior across otherwise unrelated types

TypeScriptGo
Concept moving

Extension

Add behavior using the extension mechanisms a language permits

TypeScriptGo
Concept moving

Delegation

Pass a responsibility to another object or function

TypeScriptGo
Concept moving

Polymorphism

One interface, different implementations behind it

TypeScriptGo

Language and runtime models

What a value means, where state lives, and what happens when the code runs.

Concept moving

Values and references

Follow assignment and function arguments to see which state is shared

TypeScriptGo
Concept moving

Copying, identity, and equality

Follow a delivery-address draft to separate object identity, shared state, and equal fields

TypeScriptGo
Concept moving

Allocation and memory locality

Connect memory layout, allocation, and access order to the work a program does

TypeScriptGo
Concept moving

Ownership, aliasing, and lifetimes

Reason about who can change a value and who is responsible for releasing a resource

TypeScriptGoRust
Concept moving

Closures and captured state

See what a function keeps from its surrounding scope and how that state changes

TypeScriptGo
Concept moving

The call stack and execution

Trace function calls, stack frames, returns, and the state each call keeps

TypeScriptGo
Choice moving

Static types and runtime validation

Separate what TypeScript checks before execution from what must be checked at runtime

TypeScriptGo

Data modeling and type design

Make the shape of the data carry part of the argument.

Concept moving

Discriminated unions

Give each possible case a name and the data it needs, and let the compiler find every reader when a case is added

TypeScriptGo
Concept moving

Making illegal states unrepresentable

Use the shape of data to rule out invalid combinations

TypeScriptGo
Concept moving

Parse, don't validate

Turn untrusted input into a value with guarantees the rest of the code can use

TypeScriptGo
Concept moving

Branded / opaque types

Keep values with different meanings apart even when their representation is the same

TypeScriptGo
Choice moving

Absence: null vs undefined vs missing

Distinguish an empty value, an absent value, and a field that was never provided

TypeScriptGo
Choice moving

Wide constructors

Options, positional arguments, builders, or factories — choose how callers supply data

TypeScriptGo
Choice moving

Immutability

Compare read-only views, frozen values, copying, and structural sharing

TypeScriptGo
Concept moving

When a generic earns its place

Use a type parameter to preserve a useful relationship between values

TypeScriptGo
Choice moving

Domain model vs. DTO

Choose whether your application and its external contracts should share a shape

TypeScriptGo
Concept moving

Value objects

Represent a domain value with its meaning, equality, and rules intact

TypeScriptGo

Errors, results, and recovery

What failure looks like, how it travels, and what a caller can do next.

Choice moving

How a function reports failure

Choose a reporting channel that preserves the caller’s distinct next actions

TypeScriptGo
Choice moving

Expected vs. unrecoverable

Separate actionable corrections from broken assumptions and name the containing boundary

TypeScriptGo
Choice moving

Kinds and sentinels

Choose how callers recognize failures, carry recovery data, and cross boundaries

TypeScriptGo
Pattern moving

Class-based error hierarchies

Recognize a local capture error family, then validate recovery data across constructor and JSON boundaries

TypeScriptGo
Pattern moving

Discriminated union results

Return a specimen receipt or the first actionable refusal in a tagged result

TypeScriptGo
Concept moving

Go's error protocol

Preserve archive error categories and typed details, then validate a client reply

TypeScriptGo
Choice moving

Result types & combinators

Follow dependent reading-card lookups and decide when shared result composition earns its cost

TypeScriptGo
Pattern moving

Errors across a boundary

Preserve useful failure information as it crosses an application boundary

TypeScriptGo
Pattern moving

Aggregate & partial failure

Fail fast, accumulate failures, or return partial success

TypeScriptGo
Choice moving

Error boundaries in UI

Recover a part of the interface and decide which state should survive

TypeScript

Concurrency, scheduling, and delivery

Work happening over time, and the bugs each execution model lets through.

Choice moving

Promises vs. goroutines & channels

Compare ways to start, coordinate, and communicate between concurrent tasks

TypeScriptGo
Pattern moving

Event loop vs. scheduler

Understand what runs next and how an execution model divides the work

TypeScriptGo
Choice moving

Cancellation propagation

Stop work that is no longer needed and carry that decision to its child tasks

TypeScriptGo
Pattern moving

Structured concurrency

Keep child tasks connected to the lifetime and outcome of their parent

TypeScriptGo
Pattern moving

Bounded parallelism

Limit work in flight with concurrency bounds and worker pools

TypeScriptGo
Pattern moving

Timeouts, deadlines & races

Timeouts, end-to-end deadlines, and competing outcomes

TypeScriptGo
Concept moving

Backpressure & queues

Follow excess work through bounded queues that make the producer wait or drop and count what doesn’t fit

TypeScriptGo
Pattern moving

Async iteration & streams

Work with values as they arrive, using pull or push to coordinate the flow

TypeScriptGo
Concept moving

Race conditions in UI

Stale results, request identity, and which operation still owns the screen

TypeScriptGo
Concept moving

Idempotency & at-least-once delivery

Follow duplicate deliveries through lost acknowledgments, identity, and atomic effects

TypeScriptGo
Concept moving

Actor model

Give each actor its own state and reach it through messages

TypeScriptGo

Boundaries and contracts

What crosses a line, in what shape, and who checks it.

Choice moving

Validation at the edge

Check incoming data before trusting it inside the system

TypeScriptGo
Choice moving

API contracts

Make the agreement between a caller and a service explicit

TypeScriptGo
Pattern moving

Serialization hazards

See which distinctions survive a round trip through an external format

TypeScriptGo
Pattern moving

Versioning & compatibility

Compatibility over time and how consumers observe a change

TypeScriptGo
Choice moving

Module boundaries

Decide what is public and which parts of the application may depend on it

TypeScriptGo
Pattern moving

Configuration as a boundary

Turn external configuration into a validated value the application can trust

TypeScriptGo
Choice moving

The mapping layer

Translate between external shapes and domain values, and decide where that work belongs

TypeScriptGo
Pattern moving

Feature flags & kill switches

Change behavior at runtime and manage the lifetime of that decision

TypeScriptGo

Testing, debugging, and measurement

Make a claim about behavior, check it, and investigate what the evidence shows.

Concept moving

Invariants and example tests

Name what must stay true, then choose examples and edge cases that challenge it

TypeScriptGo
Concept moving

Property-based testing

Generate many inputs and shrink failures to a small example of a broken property

TypeScriptGo
Choice moving

Fakes, stubs, and mocks

Replace a collaborator deliberately and understand what the test stops exercising

TypeScriptGo
Technique moving

Contract and integration testing

Check the agreements between components and exercise their behavior together

TypeScriptGo
Concept moving

Debugging state and control flow

Reproduce a failure and follow the state changes that explain how it happened

TypeScriptGo
Concept moving

Diagnosing concurrency bugs

Investigate races, deadlocks, and timing-dependent failures with controlled schedules

TypeScriptGo
Technique moving

Designing useful benchmarks

Choose a workload, account for warmup and variability, and compare like with like

TypeScriptGo
Technique moving

CPU and memory profiling

Find where time and allocations go, then measure the effect of a change

TypeScriptGo

Data and persistence

Keep stored state useful and correct as reads, writes, and failures overlap.

Concept moving

Transactions and atomicity

Group related changes and reason about what remains after a failure

TypeScriptGo
Choice moving

Isolation and concurrent reads

Explore what a transaction can observe while other transactions change the data

TypeScriptGo
Concept moving

Indexes and query plans

Connect lookup structures to database access paths and the cost of maintaining an index

TypeScriptGo
Choice moving

Caching and invalidation

Choose what to cache, how long to trust it, and how to handle stale or missing entries

TypeScriptGo
Technique moving

Optimistic concurrency

Detect conflicting updates and decide whether to retry, merge, or ask the caller

TypeScriptGo