# Patterns & Conventions What I've learned about how we write code in this project. ## Go Style ### Loop Idiom Always `range N` for integer loops. Never `for i := 0; i < N; i++`. This is a hard rule Fritz set early. ### Table-Driven Tests Every test file uses `t.Run` with named subtests. The pattern: ```go tests := []struct { name string // inputs... // expected... }{ {"descriptive name", ...}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // test body }) } ``` ### Mock Streams for Handlers Handler tests construct a `bytes.Buffer` with a raw request, pass it as a stream, and read the response. No QUIC, no network, fast tests. ### t.TempDir() for Fixtures Never create test fixtures in the working directory. Always `t.TempDir()` — Go cleans it up automatically. ## Development Workflow ### Build Rule Always `make client` or `go build -o bin/ ./cmd//`. Never bare `go build ./cmd//` — binaries must land in `bin/`. ### Pre-Commit Run `bash pre-commit.sh` before committing. Formats, vets, and lints all modules. ### Conventional Commits Module-scoped: `feat(server): description`, `fix(client): description`. This drives auto-versioning and release tagging (`server/v0.1.0`, etc.). ## Philosophy ### Small and Incremental Every change should be the smallest working increment. Get something tested and working before moving on. Don't batch up large changes. ### Robustness First Handle the error. Test the edge case. Make it correct before making it elegant. ### Simplest Solution Short functions, clear names, obvious flow. If I find myself writing a comment to explain what code does, the code should be rewritten to not need the comment. Comments explain *why*, not *what*. ### No Over-Engineering Don't add features beyond what's asked. Don't refactor surroundings while fixing a bug. Don't add abstractions for one-time operations. Three similar lines are better than a premature helper function. ## What I've Learned About Working With Fritz Fritz values directness. Short answers over long explanations. Working code over architecture astronautics. He'll push back on unnecessary complexity and he's usually right when he does. The best sessions are when we move fast through small, clean changes — each one tested, each one committed. Momentum matters.