# Contract: Module Atomicity Version: 1.0 ## Principle Each file has one clear responsibility. A file that does many unrelated things is a liability, not a convenience. ## Rules - One concept per file. A file should be nameable in a single noun: `user_validator.go`, `session_store.go`, `invoice_pdf.go`. If the name requires "and" or "misc", the file is too broad. - Do not append new functionality to an existing file because it is nearby or already open. When a new piece of logic does not belong to the existing concept, create a new file. - A file that grows past ~200 lines is a signal to split, not a mandate — but treat it as a prompt to ask whether all the code in it shares a single responsibility. - Package-level `utils.go`, `helpers.go`, or `common.go` files are banned. Name the file after what the code actually does. ## Anti-patterns - Adding a new handler to `handlers.go` because there is already a handler there. - Putting unrelated functions in the same file to avoid creating a new one. - A single file containing models, queries, business logic, and HTTP concerns at once. - Files named after their location or role in the codebase rather than their concept: `api.go`, `misc.go`, `util.go`, `shared.go`. ## When to split Split a file when: 1. You cannot describe all of its functions in one short sentence. 2. A new function you are adding does not share the domain of the existing ones. 3. The file has more than one reason to change independently. Do not wait until a file is "too big." Split at the moment the second responsibility appears.