[{"data":1,"prerenderedAt":302},["ShallowReactive",2],{"writing-2026-07-31-keep-module-documentation-next-to-the-code":3,"writing-surroundings-2026-07-31-keep-module-documentation-next-to-the-code":296},{"id":4,"title":5,"body":6,"date":282,"description":283,"draft":284,"extension":285,"image":286,"meta":287,"navigation":148,"path":288,"seo":289,"stem":290,"tags":291,"updated":286,"__hash__":295},"writing\u002Fwriting\u002F2026-07-31-keep-module-documentation-next-to-the-code.md","Keep Module Documentation Next to the Code",{"type":7,"value":8,"toc":276},"minimark",[9,13,16,85,88,91,94,97,100,103,106,111,118,126,129,132,193,196,199,203,210,213,229,232,236,239,242,245,248,252,259,269,272],[10,11,12],"p",{},"Sometimes code looks wrong for a good reason.",[10,14,15],{},"You open an order module and find this:",[17,18,23],"pre",{"className":19,"code":20,"language":21,"meta":22,"style":22},"language-python shiki shiki-themes min-light min-dark","class Order:\n    shipping_street = ...\n    shipping_city = ...\n    shipping_postal_code = ...\n    shipping_country = ...\n","python","",[24,25,26,43,55,65,75],"code",{"__ignoreMap":22},[27,28,31,35,39],"span",{"class":29,"line":30},"line",1,[27,32,34],{"class":33},"se1w0","class",[27,36,38],{"class":37},"sScJk"," Order",[27,40,42],{"class":41},"sHHeI",":\n",[27,44,46,49,52],{"class":29,"line":45},2,[27,47,48],{"class":41},"    shipping_street ",[27,50,51],{"class":33},"=",[27,53,54],{"class":41}," ...\n",[27,56,58,61,63],{"class":29,"line":57},3,[27,59,60],{"class":41},"    shipping_city ",[27,62,51],{"class":33},[27,64,54],{"class":41},[27,66,68,71,73],{"class":29,"line":67},4,[27,69,70],{"class":41},"    shipping_postal_code ",[27,72,51],{"class":33},[27,74,54],{"class":41},[27,76,78,81,83],{"class":29,"line":77},5,[27,79,80],{"class":41},"    shipping_country ",[27,82,51],{"class":33},[27,84,54],{"class":41},[10,86,87],{},"Why store the customer's address again?",[10,89,90],{},"The customer already has an address. It would seem cleaner to store a reference instead.",[10,92,93],{},"But there is a problem.",[10,95,96],{},"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.",[10,98,99],{},"An old order has to keep the address that was used when the order was placed.",[10,101,102],{},"So the duplicated address is not a mistake. It is part of the design.",[10,104,105],{},"The problem is that the reason is not obvious from the code.",[107,108,110],"h2",{"id":109},"the-simple-solution","The Simple Solution",[10,112,113,114,117],{},"Keep a small ",[24,115,116],{},"README.md"," inside the module:",[17,119,124],{"className":120,"code":122,"language":123,"meta":22},[121],"language-text","orders\u002F\n  docs\u002F\n    README.md\n  models\u002F\n  services\u002F\n","text",[24,125,122],{"__ignoreMap":22},[10,127,128],{},"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.",[10,130,131],{},"Then document the decision:",[17,133,137],{"className":134,"code":135,"language":136,"meta":22,"style":22},"language-markdown shiki shiki-themes min-light min-dark","## Key Decision\n\nOrders store a copy of the shipping address.\n\nCustomers can change their address later,\nbut old orders must keep the address used\nwhen the order was placed.\n\nDo not replace these fields with a\ncustomer address reference.\n","markdown",[24,138,139,144,150,155,159,164,170,176,181,187],{"__ignoreMap":22},[27,140,141],{"class":29,"line":30},[27,142,143],{},"## Key Decision\n",[27,145,146],{"class":29,"line":45},[27,147,149],{"emptyLinePlaceholder":148},true,"\n",[27,151,152],{"class":29,"line":57},[27,153,154],{},"Orders store a copy of the shipping address.\n",[27,156,157],{"class":29,"line":67},[27,158,149],{"emptyLinePlaceholder":148},[27,160,161],{"class":29,"line":77},[27,162,163],{},"Customers can change their address later,\n",[27,165,167],{"class":29,"line":166},6,[27,168,169],{},"but old orders must keep the address used\n",[27,171,173],{"class":29,"line":172},7,[27,174,175],{},"when the order was placed.\n",[27,177,179],{"class":29,"line":178},8,[27,180,149],{"emptyLinePlaceholder":148},[27,182,184],{"class":29,"line":183},9,[27,185,186],{},"Do not replace these fields with a\n",[27,188,190],{"class":29,"line":189},10,[27,191,192],{},"customer address reference.\n",[10,194,195],{},"Now the next developer does not have to guess.",[10,197,198],{},"The code shows what the system does. The markdown file explains why.",[107,200,202],{"id":201},"keep-it-small","Keep It Small",[10,204,205,206],{},"You do not need to document every function, model field, or file. ",[207,208,209],"strong",{},"If the code already answers it, leave it out.",[10,211,212],{},"Only write down the things that are not obvious from the code:",[214,215,216,220,223,226],"ul",{},[217,218,219],"li",{},"important decisions",[217,221,222],{},"business rules",[217,224,225],{},"unusual behavior",[217,227,228],{},"things that look wrong but are intentional",[10,230,231],{},"A few lines are often enough.",[107,233,235],{"id":234},"key-takeaway","Key Takeaway",[10,237,238],{},"A module isn't finished when it works. It's finished when someone else can change it safely.",[10,240,241],{},"Good code explains how a system works. A small markdown file can explain why it works that way.",[10,243,244],{},"Keep that explanation next to the code, while the decision is still fresh.",[10,246,247],{},"It may save the next developer from \"fixing\" something that was never broken.",[107,249,251],{"id":250},"the-same-idea-in-a-working-project","The Same Idea in a Working Project",[10,253,254,255,258],{},"A small Django REST Framework and PostgreSQL project built around this exact decision. Two modules, each with its own ",[24,256,257],{},"docs\u002FREADME.md",", and a test that fails if someone removes the duplicated address fields:",[10,260,261],{},[207,262,263],{},[264,265,266],"a",{"href":266,"rel":267},"https:\u002F\u002Fgithub.com\u002Frekanothman\u002Fdocs-next-to-code",[268],"nofollow",[10,270,271],{},"Place an order, change that customer's address, then read the order back.",[273,274,275],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .se1w0, html code.shiki .se1w0{--shiki-default:#D32F2F;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sHHeI, html code.shiki .sHHeI{--shiki-default:#24292EFF;--shiki-dark:#B392F0}",{"title":22,"searchDepth":45,"depth":45,"links":277},[278,279,280,281],{"id":109,"depth":45,"text":110},{"id":201,"depth":45,"text":202},{"id":234,"depth":45,"text":235},{"id":250,"depth":45,"text":251},"2026-07-31","Some code looks wrong until you know the decision behind it. A small README inside the module keeps that reason where the next developer will actually find it.",false,"md",null,{},"\u002Fwriting\u002F2026-07-31-keep-module-documentation-next-to-the-code",{"title":5,"description":283},"writing\u002F2026-07-31-keep-module-documentation-next-to-the-code",[292,293,294],"documentation","project-structure","engineering-practices","mlzbsgCm78SvZabt8HwQ8IdSvpoJtyvJvYPMvGFG8X0",[286,297],{"title":298,"path":299,"stem":300,"date":301,"children":-1},"A Reliable Way to Prevent Duplicate Database Records","\u002Fwriting\u002F2026-07-17-a-reliable-way-to-prevent-duplicate-database-records","writing\u002F2026-07-17-a-reliable-way-to-prevent-duplicate-database-records","2026-07-17",1785558902907]