Sometimes code looks wrong for a good reason.
You open an order module and find this:
class Order:
shipping_street = ...
shipping_city = ...
shipping_postal_code = ...
shipping_country = ...
Why store the customer's address again?
The customer already has an address. It would seem cleaner to store a reference instead.
But there is a problem.
Customers can change their address. If the order points to the customer record, then the day a customer moves, every past order starts showing the new address. A delivery dispute from last year now points to a place the package was never sent.
An old order has to keep the address that was used when the order was placed.
So the duplicated address is not a mistake. It is part of the design.
The problem is that the reason is not obvious from the code.
The Simple Solution
Keep a small README.md inside the module:
orders/
docs/
README.md
models/
services/
Not in a wiki, and not in a shared document somewhere else. Inside the module, so the person reading the code finds it without looking for it, and so it travels with the code when the code changes.
Then document the decision:
## Key Decision
Orders store a copy of the shipping address.
Customers can change their address later,
but old orders must keep the address used
when the order was placed.
Do not replace these fields with a
customer address reference.
Now the next developer does not have to guess.
The code shows what the system does. The markdown file explains why.
Keep It Small
You do not need to document every function, model field, or file. If the code already answers it, leave it out.
Only write down the things that are not obvious from the code:
- important decisions
- business rules
- unusual behavior
- things that look wrong but are intentional
A few lines are often enough.
Key Takeaway
A module isn't finished when it works. It's finished when someone else can change it safely.
Good code explains how a system works. A small markdown file can explain why it works that way.
Keep that explanation next to the code, while the decision is still fresh.
It may save the next developer from "fixing" something that was never broken.
The Same Idea in a Working Project
A small Django REST Framework and PostgreSQL project built around this exact decision. Two modules, each with its own docs/README.md, and a test that fails if someone removes the duplicated address fields:
https://github.com/rekanothman/docs-next-to-code
Place an order, change that customer's address, then read the order back.
Top comments (0)