Software Craft

How do I investigate and improve code?
Reason about the changes.

Build evidence for what your code does. Debug failures, test assumptions, design useful contracts, and improve behavior with measurements.

Work in progress. 2 of 24 lessons are drafted and open to read; they're still being reviewed.

Useful foundations: functions, types, collections, and errors. Runtime lessons support the performance investigations.

24 topics

Still being written 2 of 24 lessons are drafted and open to read while they're reviewed. Planned topics show where the catalog is going.

Tools and everyday workflow

Start here

Set up the small habits that make every later investigation faster.

Concept planned

Reading documentation and specifications

Where is the real answer? Compare a language specification, standard-library docs, and a blog post, and know which one makes a promise.

TypeScriptGoRustCHaskellJava
Concept planned

REPLs and scratch experiments

How do you test an idea in thirty seconds? Use a REPL or a scratch file to check one behavior before relying on it.

TypeScriptGoRustCHaskellJava
Concept planned

Formatters, linters, and warnings

What can a tool catch before you run anything? Turn on warnings, read lint findings, and let a formatter settle style.

TypeScriptGoRustCHaskellJava
Concept planned

Reading unfamiliar code

Where do you start in code you did not write? Find the entry point, follow one path, and write down what you learn.

TypeScriptGoRustCHaskellJava

Debugging with evidence

Build understanding

Move from a symptom to a small explanation you can check.

Concept planned

Compiler diagnostics and stack traces

What is the tool telling you, and where did the failure originate? Separate a diagnostic location from the cause.

TypeScriptGoRustCHaskellJava
Concept planned

Print statements and logging as evidence

What should you print, and where? Turn a print statement into a deliberate observation that can confirm or reject a guess.

TypeScriptGoRustCHaskellJava
Concept planned

Breakpoints, frames, and inspected values

Which values exist at this point? Inspect the call stack and scope without assuming an optimized program preserves every source-level detail.

TypeScriptGoRustCHaskellJava
Concept planned

Sanitizers, race detectors, and checked builds

Can a tool catch the bug while it happens? Use AddressSanitizer, go test -race, and Miri to turn silent errors into reports.

CGoRust

Tests, properties, and repeatability

Build understanding

Use examples and generated cases to challenge a claim about behavior.

Concept planned

Test structure and isolated state

How do you make an example repeatable? Compare assertions, fresh fixtures, and language-specific test runners.

TypeScriptGoRustCHaskellJava
Concept planned

Table-driven and parameterized tests

How do you check many cases without copying the test? List inputs and expected results, then report which row failed.

TypeScriptGoRustCHaskellJava
Concept planned

Testing failure paths

Does the code fail the way you promised? Check returned errors, thrown exceptions, and cleanup after a failure.

TypeScriptGoRustCHaskellJava
Concept planned

Properties and generated cases

What should hold over many inputs? Write a property, find a counterexample, and inspect which assumption failed.

TypeScriptGoRustCHaskellJava
Concept planned

Clocks, randomness, and test seams

How do you test code that depends on time or external state? Make those dependencies explicit and control them in a test.

TypeScriptGoRustCHaskellJava

Contracts, invariants, and safe changes

Build understanding

Choose useful boundaries and improve the code while keeping its promises.

Concept planned

Naming and readable code

Will the next reader understand this? Choose names that state intent, and shape code so the common path is easy to follow.

TypeScriptGoRustCHaskellJava
Concept planned

Domain types and smart constructors

Which values should be impossible to construct? Validate at a boundary and use a type or API to preserve the invariant.

TypeScriptGoRustCHaskellJava
Concept planned

API contracts and explicit dependencies

What may a caller assume? Describe inputs, outputs, effects, and failure behavior, then choose a dependency boundary that can be tested.

TypeScriptGoRustCHaskellJava
Concept planned

Reviewing code and hidden assumptions

What could break with a different caller, input, or lifetime? Review aliasing, ownership, failure paths, and implicit shared state.

TypeScriptGoRustCHaskellJava
Concept planned

Refactoring without changing behavior

Which observations must stay the same? Establish checks before changing the structure, then explain what they do and do not prove.

TypeScriptGoRustCHaskellJava

Cost, benchmarks, and profiles

Go underneath

Measure a representative workload before deciding where the cost comes from.

Concept planned

Time, space, and algorithmic cost

How does work grow with input size? Compare asymptotic cost with allocations, constant factors, and the actual workload.

TypeScriptGoRustCHaskellJava
Concept planned

Benchmarking and build modes

What does this timing measure? Account for warmup, optimization, eliminated work, input selection, and measurement noise.

TypeScriptGoRustCHaskellJava
Concept planned

CPU profiles and hot paths

Where is time being spent? Read samples and call paths, form a hypothesis, and measure the change.

TypeScriptGoRustCHaskellJava
Concept planned

Allocation profiles and retained memory

Does this program allocate frequently or keep data alive? Distinguish allocation rate, live memory, and resource leaks.

TypeScriptGoRustCHaskellJava