{"course":{"slug":"ai-careers","title":"Working in AI","url":"https://addaly.com/learn/ai-careers","level":"beginner","track":"work"},"lesson":{"slug":"reading-code-you-did-not-write","title":"Landing in a codebase nobody documented","url":"https://addaly.com/learn/ai-careers/reading-code-you-did-not-write","position":78,"of":85,"minutes":9,"answer":"Trace one behaviour end to end rather than reading the codebase, and use git history to recover the reasons: the strange condition usually has a commit explaining the incident that caused it.","keyIdea":"Trace one behaviour end to end rather than reading the codebase, and use git history to recover the reasons: the strange condition usually has a commit explaining the incident that caused it."},"body":{"format":"markdown","text":"## Week two, and 40,000 lines\n\nThe repository has no README worth reading, three directories whose names mean nothing, a `utils.py` of 1,800 lines, and the person who wrote most of it left in March. Somebody has asked you to change how one number is calculated.\n\nThis situation is the normal case, not the unlucky one, and being good at it is one of the most transferable skills in this field. Almost nobody is taught it.\n\n## Do not read from the top\n\nThe instinct is to open the first file and start reading. This fails because a codebase is not a book; it is a graph, and you have no idea which parts matter.\n\n**Start from a behaviour and trace it.** Pick one thing the system visibly does (one endpoint, one scheduled job, one number on one dashboard) and follow it end to end. You will understand a thin slice completely, which is far more useful than understanding forty per cent of everything vaguely.\n\nFind the entry point by searching for something you can see: the URL path, the table name, the text of an error message, the label on the dashboard. Then follow the calls outward, writing down each hop.\n\n## The tools that answer \"why\"\n\nGit holds the history and almost nobody uses it for archaeology. Four commands do most of the work:\n\n```bash\n# history of one file, newest first\ngit log --oneline -- src/pricing/discount.py\n\n# every commit that added or removed this string, anywhere\ngit log -S \"customer_status\" --oneline\n\n# who wrote these lines, and in which commit\ngit blame -L 120,150 src/pricing/discount.py\n\n# the full commit: message, diff, and often the ticket link\ngit show 4f2a91c\n```\n\n`git log -S` is the one to remember. It finds the commit where a magic constant, a strange flag or an odd condition first appeared, and the commit message frequently contains the entire explanation: *\"Handle the Belgian VAT case: see TICKET-4412.\"*\n\nCommit messages, pull request descriptions and the tickets they link to are the real documentation of most systems. They are also the reason the commit-message convention in this course's guidelines asks for a body explaining *why*.\n\n## Tests are the specification\n\nIf tests exist, read them before the implementation. A test says what the authors believed the code should do, in executable form, and it usually says it more clearly than the code does. Running one test under a debugger, or with print statements inserted, teaches more in ten minutes than an hour of reading.\n\nIf there are no tests, writing one for the behaviour you are about to change is the safest first move you can make, and it converts your reading into something the team keeps.\n\n## The fence you should not remove\n\nYou will find a condition that makes no sense: a hard-coded date, an exception for one customer, a retry with an oddly specific timeout. The temptation is to clean it up.\n\nDo not, until you know why it exists. Use `git log -S` on the strange value. Nine times out of ten there is a commit saying exactly what broke, and the tenth time you ask someone with the evidence in hand. Removing a condition somebody added at 2am after an incident is how a new joiner causes the same incident again, and it is remembered.\n\n## Write the map as you go\n\nKeep a file as you trace: what calls what, which table holds what, which directory is dead, which name is a lie. Two weeks later, tidy it into a page and open a pull request adding it to the repository.\n\nThis is the highest-value first contribution a new joiner can make. It is useful, it is unarguably yours, and it makes your learning visible without anybody having to take your word for it.\n\n## Ask questions with your homework attached\n\nThere is an enormous difference between two questions.\n\n> \"How does the pricing service work?\"\n\nThis costs somebody a meeting, and you will retain a third of it.\n\n> \"I traced the discount calculation from the API handler to `apply_tier`, and it looks like the branch at line 214 exists to handle legacy contracts. Is that right, and is there anything else that path touches?\"\n\nThis costs thirty seconds, gets a precise answer, and tells the person you are worth answering. Do the tracing first, then ask about the one thing you could not resolve.\n\n## The limitation\n\nSome code is unknowable: no history because it was imported in one commit, no tests, no one left who remembers. The professional response is not heroic archaeology; it is to **bound it**. Write tests capturing what it currently does, change only what you must, and treat it as a black box with a known interface.\n\nAn AI assistant is good at summarising what a file does and is confidently unreliable about *why* it does it, because the reasons live in tickets and in people's memories rather than in the code. Use it for the first pass, then use `git log` for the part that matters."},"check":{"question":"A new joiner finds a hard-coded three-second timeout with no comment and wants to remove it as untidy. What is the most effective first step?","options":[{"text":"Run `git log -S \"3\"` on the file to find the commit that introduced the value, and read its message and linked ticket.","correct":true},{"text":"Remove it behind a feature flag so it can be restored quickly if something breaks.","correct":false,"tempting":"Manages the rollback while still shipping a change whose purpose is unknown, so the failure it prevented can recur before anyone connects the two."},{"text":"Ask in the team channel whether anyone knows why the timeout is there.","correct":false,"tempting":"Reasonable, but spends someone else's attention on a question the repository can usually answer in twenty seconds."},{"text":"Check whether any test covers the timeout, and if none does, treat it as dead configuration.","correct":false,"tempting":"Uses test coverage as evidence of intent, when the least-documented behaviours are exactly the ones added under incident pressure without tests."}]},"prev":{"slug":"the-first-ninety-days","title":"The first ninety days","url":"https://addaly.com/learn/ai-careers/the-first-ninety-days"},"next":{"slug":"being-trusted-with-a-number","title":"Being trusted with a number","url":"https://addaly.com/learn/ai-careers/being-trusted-with-a-number"},"authorship":"Founder and series editor: Dr Mustafa Mun. Written by AI models to a written standard. Exam keys checked blind by a second model: 3,665 of 3,666 agreed. Academic review invited.","review":{"status":"Draft, open for academic review"},"cite":"Addaly (2026) 'Landing in a codebase nobody documented', in Working in AI. Edited by M. Mun. Addaly. Available at: https://addaly.com/learn/ai-careers/reading-code-you-did-not-write (Accessed: 13 October 2026).","licence":{"name":"CC BY-NC-SA 4.0","url":"https://creativecommons.org/licenses/by-nc-sa/4.0/"},"reader":{"schema":1,"title":"Landing in a codebase nobody documented","courseTitle":"Working in AI","module":{"index":9,"slug":"staying","title":"Staying: the first ninety days and the ten years after"},"answer":null,"keyIdea":"Trace one behaviour end to end rather than reading the codebase, and use git history to recover the reasons: the strange condition usually has a commit explaining the incident that caused it.","hero":{"kind":"plate","image":null,"alt":null,"caption":null},"blocks":[{"t":"h2","id":"week-two-and-40-000-lines","runs":[{"text":"Week two, and 40,000 lines"}]},{"t":"p","runs":[{"text":"The repository has no README worth reading, three directories whose names mean nothing, a "},{"text":"utils.py","code":true},{"text":" of 1,800 lines, and the person who wrote most of it left in March. Somebody has asked you to change how one number is calculated."}]},{"t":"p","runs":[{"text":"This situation is the normal case, not the unlucky one, and being good at it is one of the most transferable skills in this field. Almost nobody is taught it."}]},{"t":"h2","id":"do-not-read-from-the-top","runs":[{"text":"Do not read from the top"}]},{"t":"p","runs":[{"text":"The instinct is to open the first file and start reading. This fails because a codebase is not a book; it is a graph, and you have no idea which parts matter."}]},{"t":"p","runs":[{"text":"Start from a behaviour and trace it.","b":true},{"text":" Pick one thing the system visibly does (one endpoint, one scheduled job, one number on one dashboard) and follow it end to end. You will understand a thin slice completely, which is far more useful than understanding forty per cent of everything vaguely."}]},{"t":"p","runs":[{"text":"Find the entry point by searching for something you can see: the URL path, the table name, the text of an error message, the label on the dashboard. Then follow the calls outward, writing down each hop."}]},{"t":"h2","id":"the-tools-that-answer-why","runs":[{"text":"The tools that answer “why”"}]},{"t":"p","runs":[{"text":"Git holds the history and almost nobody uses it for archaeology. Four commands do most of the work:"}]},{"t":"code","lang":"bash","label":"Bash","text":"# history of one file, newest first\ngit log --oneline -- src/pricing/discount.py\n\n# every commit that added or removed this string, anywhere\ngit log -S \"customer_status\" --oneline\n\n# who wrote these lines, and in which commit\ngit blame -L 120,150 src/pricing/discount.py\n\n# the full commit: message, diff, and often the ticket link\ngit show 4f2a91c"},{"t":"p","runs":[{"text":"git log -S","code":true},{"text":" is the one to remember. It finds the commit where a magic constant, a strange flag or an odd condition first appeared, and the commit message frequently contains the entire explanation: "},{"text":"”Handle the Belgian VAT case: see TICKET-4412.”","i":true}]},{"t":"p","runs":[{"text":"Commit messages, pull request descriptions and the tickets they link to are the real documentation of most systems. They are also the reason the commit-message convention in this course’s guidelines asks for a body explaining "},{"text":"why","i":true},{"text":"."}]},{"t":"h2","id":"tests-are-the-specification","runs":[{"text":"Tests are the specification"}]},{"t":"p","runs":[{"text":"If tests exist, read them before the implementation. A test says what the authors believed the code should do, in executable form, and it usually says it more clearly than the code does. Running one test under a debugger, or with print statements inserted, teaches more in ten minutes than an hour of reading."}]},{"t":"p","runs":[{"text":"If there are no tests, writing one for the behaviour you are about to change is the safest first move you can make, and it converts your reading into something the team keeps."}]},{"t":"h2","id":"the-fence-you-should-not-remove","runs":[{"text":"The fence you should not remove"}]},{"t":"p","runs":[{"text":"You will find a condition that makes no sense: a hard-coded date, an exception for one customer, a retry with an oddly specific timeout. The temptation is to clean it up."}]},{"t":"p","runs":[{"text":"Do not, until you know why it exists. Use "},{"text":"git log -S","code":true},{"text":" on the strange value. Nine times out of ten there is a commit saying exactly what broke, and the tenth time you ask someone with the evidence in hand. Removing a condition somebody added at 2am after an incident is how a new joiner causes the same incident again, and it is remembered."}]},{"t":"h2","id":"write-the-map-as-you-go","runs":[{"text":"Write the map as you go"}]},{"t":"p","runs":[{"text":"Keep a file as you trace: what calls what, which table holds what, which directory is dead, which name is a lie. Two weeks later, tidy it into a page and open a pull request adding it to the repository."}]},{"t":"p","runs":[{"text":"This is the highest-value first contribution a new joiner can make. It is useful, it is unarguably yours, and it makes your learning visible without anybody having to take your word for it."}]},{"t":"h2","id":"ask-questions-with-your-homework-attached","runs":[{"text":"Ask questions with your homework attached"}]},{"t":"p","runs":[{"text":"There is an enormous difference between two questions."}]},{"t":"quote","runs":[{"text":"“How does the pricing service work?”"}]},{"t":"p","runs":[{"text":"This costs somebody a meeting, and you will retain a third of it."}]},{"t":"quote","runs":[{"text":"“I traced the discount calculation from the API handler to "},{"text":"apply_tier","code":true},{"text":", and it looks like the branch at line 214 exists to handle legacy contracts. Is that right, and is there anything else that path touches?”"}]},{"t":"p","runs":[{"text":"This costs thirty seconds, gets a precise answer, and tells the person you are worth answering. Do the tracing first, then ask about the one thing you could not resolve."}]},{"t":"h2","id":"the-limitation","runs":[{"text":"The limitation"}],"role":"limit"},{"t":"p","runs":[{"text":"Some code is unknowable: no history because it was imported in one commit, no tests, no one left who remembers. The professional response is not heroic archaeology; it is to "},{"text":"bound it","b":true},{"text":". Write tests capturing what it currently does, change only what you must, and treat it as a black box with a known interface."}]},{"t":"p","runs":[{"text":"An AI assistant is good at summarising what a file does and is confidently unreliable about "},{"text":"why","i":true},{"text":" it does it, because the reasons live in tickets and in people’s memories rather than in the code. Use it for the first pass, then use "},{"text":"git log","code":true},{"text":" for the part that matters."}]}],"check":{"question":[{"text":"A new joiner finds a hard-coded three-second timeout with no comment and wants to remove it as untidy. What is the most effective first step?"}],"options":[{"text":[{"text":"Run "},{"text":"git log -S \"3\"","code":true},{"text":" on the file to find the commit that introduced the value, and read its message and linked ticket."}],"correct":true,"tempting":null},{"text":[{"text":"Remove it behind a feature flag so it can be restored quickly if something breaks."}],"correct":false,"tempting":[{"text":"Manages the rollback while still shipping a change whose purpose is unknown, so the failure it prevented can recur before anyone connects the two."}]},{"text":[{"text":"Ask in the team channel whether anyone knows why the timeout is there."}],"correct":false,"tempting":[{"text":"Reasonable, but spends someone else’s attention on a question the repository can usually answer in twenty seconds."}]},{"text":[{"text":"Check whether any test covers the timeout, and if none does, treat it as dead configuration."}],"correct":false,"tempting":[{"text":"Uses test coverage as evidence of intent, when the least-documented behaviours are exactly the ones added under incident pressure without tests."}]}],"order":[1,2,3,0],"why":null},"prev":{"slug":"the-first-ninety-days","title":"The first ninety days","minutes":8},"next":{"slug":"being-trusted-with-a-number","title":"Being trusted with a number","minutes":8}}}