{"course":{"slug":"ai-for-students","title":"AI for Students","url":"https://addaly.com/learn/ai-for-students","level":"beginner","track":"work"},"lesson":{"slug":"programming-and-cs","title":"Code that runs and is wrong","url":"https://addaly.com/learn/ai-for-students/programming-and-cs","position":31,"of":73,"minutes":9,"answer":"Generated code that runs is not code that is correct: read every line, test the boundary case, refuse rewrites when debugging, and write the tests yourself from the specification.","keyIdea":"Generated code that runs is not code that is correct: read every line, test the boundary case, refuse rewrites when debugging, and write the tests yourself from the specification."},"body":{"format":"markdown","text":"## The most dangerous output in this course\n\nGenerated code has a property nothing else in this course has: it will happily run, produce plausible output, and be wrong, and you will only find out later. A wrong essay sentence gets marked. A wrong line of code gets a result you then build on.\n\nStudents new to programming are the most exposed, because the failure requires you to read the code to detect, and reading code is precisely the skill not yet acquired.\n\n## The characteristic failures\n\n**Off-by-one and boundary errors.** Loops that miss the last element, ranges that include an endpoint they should not. The code runs; the answer is slightly wrong.\n\n**Invented APIs.** A function, method or parameter that does not exist in the library, with a completely plausible name. This is fabrication in a different costume, and it is common enough to have its own security concern: attackers register package names that models frequently hallucinate. If a package name comes from a model, check it exists on the real index before installing it.\n\n**Version drift.** Correct code for an older version of a library. Deprecated arguments, renamed functions, changed defaults. The model's training has no clean sense of which version you have installed.\n\n**Silent type problems.** Integer division where you wanted float, string concatenation where you wanted addition, a pandas operation returning a copy when you expected a view.\n\n**Working code, wrong problem.** The most expensive one. It solves what the model understood you to mean, which is not what you meant, and it works perfectly.\n\n## The rule\n\n**Read every line before you run it, and be able to say what each line does.** If you cannot, you have not received help; you have received a liability. Run it, then test it on a case where you already know the answer, including an edge case: empty input, one element, a negative number, a duplicate.\n\n> Figure: The cell that costs you is the quiet one. A two by two grid, rows It runs and It errors, columns It is correct and It is wrong: It runs and It is correct: Fine; It runs and It is wrong: Silent cost; It errors and It is correct: Slow; It errors and It is wrong: Caught at once. Code that runs is not code that is correct. Errors announce themselves and cost a minute; the off-by-one, the integer division and the program that solves what the model understood you to mean all run cleanly and get built on. Read every line and be able to say what each one does, then test a case where you already know the answer, including empty input and a single element.\n\nThat last habit is worth more than any other in this lesson. Generated code is usually tested by the person who received it against exactly the case they had in mind. Testing the boundary takes ten seconds and catches most of the off-by-one class.\n\n## Debugging, which is the excellent use\n\nThis is where these tools are transformative and where using them well is unambiguously good.\n\n> Here is the error, the full traceback, and the relevant function. Do not rewrite my code. Tell me what the error means, and what would cause it here. I will fix it.\n\n*Do not rewrite my code* is the essential clause. Without it you get a rewritten file and no idea what was wrong. With it you get an explanation, and the ability to recognise that error unaided next time, which is the actual skill: professional programmers spend far more time reading errors than writing new code.\n\nAlso excellent: pasting a piece of unfamiliar code and asking what it does, line by line. This is reading practice with an infinitely patient annotator, and it is one of the fastest ways to get comfortable in a new codebase or language.\n\n## Version control is your process record\n\n**git** is free, and for a student it does two jobs at once. It is how you avoid losing work, and it is a dated, granular record of your work developing, which is exactly the evidence Module 7 says you want to have before anyone asks for it.\n\nThe minimum that helps:\n\n```bash\ngit init\ngit add -A && git commit -m \"first attempt at the parser, failing on nested cases\"\n```\n\nCommit at the end of every session, including the bad ones. A history of forty commits showing an idea developing, with failures in it, is worth more than any argument you could construct afterwards. GitHub and GitLab both host free private repositories.\n\n## What to keep doing yourself\n\nFor a computing student, this list is not optional:\n\n- Writing a function from a specification, unaided, regularly.\n- Reading a stack trace and locating the fault before asking anything.\n- Reasoning about complexity: why this is quadratic and that is linear.\n- Writing the tests. If the model writes both the code and the tests, the tests check the code's assumptions rather than the specification's.\n\nThat last point is subtle and important. Tests written by whatever produced the code will pass by construction. Write the tests first, yourself, from the spec, then let the model help with the implementation. That order preserves the check.\n\n## Free tools, named\n\nPython, VS Code or **VSCodium** (the same editor without the telemetry), git, and **Google Colab** for a free notebook with GPU access. For learning to read errors, no tool beats `print` statements and a debugger you have actually opened. Copilot-style completion in the editor is convenient and, for a learner, actively risky: it produces code before you have formed the intention, which removes the design step from the task. Turn it off while you are learning the language, and turn it on later when you can tell instantly whether what it suggested is right."},"check":{"question":"Why is it a problem to let a model write both the implementation and the tests for a piece of coursework?","options":[{"text":"Because generated tests tend to be shallow and only cover the obvious path through the function.","correct":false,"tempting":"Often true in practice, but a thorough generated suite would have the same structural flaw; coverage is not the issue."},{"text":"Because tests written after the implementation are always weaker than tests written first, regardless of who writes them.","correct":false,"tempting":"States a real test-first principle too absolutely; a human writing tests afterwards against the original specification still provides an independent check."},{"text":"Because most marking schemes award credit for tests separately, so generated ones cost marks directly.","correct":false,"tempting":"Answers a marking-policy question rather than a correctness one; the structural problem exists whether or not tests are assessed."},{"text":"Because the tests encode the same misunderstanding as the code, so they pass by construction.","correct":true}]},"prev":{"slug":"proofs-and-reasoning","title":"Proofs, and the step that looks fine","url":"https://addaly.com/learn/ai-for-students/proofs-and-reasoning"},"next":{"slug":"lab-sciences-and-units","title":"The lab sciences, and the dimension check","url":"https://addaly.com/learn/ai-for-students/lab-sciences-and-units"},"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) 'Code that runs and is wrong', in AI for Students. Edited by M. Mun. Addaly. Available at: https://addaly.com/learn/ai-for-students/programming-and-cs (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":"Code that runs and is wrong","courseTitle":"AI for Students","module":{"index":4,"slug":"subject-by-subject","title":"Subject by subject"},"answer":null,"keyIdea":"Generated code that runs is not code that is correct: read every line, test the boundary case, refuse rewrites when debugging, and write the tests yourself from the specification.","hero":{"kind":"figure","figure":{"t":"figure","label":"Figure","figure":{"cols":["It is correct","It is wrong"],"rows":["It runs","It errors"],"type":"matrix","cells":[["Fine","Silent cost"],["Slow","Caught at once"]],"title":"The cell that costs you is the quiet one","caption":"Code that runs is not code that is correct. Errors announce themselves and cost a minute; the off-by-one, the integer division and the program that solves what the model understood you to mean all run cleanly and get built on. Read every line and be able to say what each one does, then test a case where you already know the answer, including empty input and a single element.","cellLabels":[["you can move on","off-by-one errors"],["read the traceback","invented API names"]]},"alt":"Figure: The cell that costs you is the quiet one. A two by two grid, rows It runs and It errors, columns It is correct and It is wrong: It runs and It is correct: Fine; It runs and It is wrong: Silent cost; It errors and It is correct: Slow; It errors and It is wrong: Caught at once. Code that runs is not code that is correct. Errors announce themselves and cost a minute; the off-by-one, the integer division and the program that solves what the model understood you to mean all run cleanly and get built on. Read every line and be able to say what each one does, then test a case where you already know the answer, including empty input and a single element."}},"blocks":[{"t":"h2","id":"the-most-dangerous-output-in-this-course","runs":[{"text":"The most dangerous output in this course"}]},{"t":"p","runs":[{"text":"Generated code has a property nothing else in this course has: it will happily run, produce plausible output, and be wrong, and you will only find out later. A wrong essay sentence gets marked. A wrong line of code gets a result you then build on."}]},{"t":"p","runs":[{"text":"Students new to programming are the most exposed, because the failure requires you to read the code to detect, and reading code is precisely the skill not yet acquired."}]},{"t":"h2","id":"the-characteristic-failures","runs":[{"text":"The characteristic failures"}]},{"t":"p","runs":[{"text":"Off-by-one and boundary errors.","b":true},{"text":" Loops that miss the last element, ranges that include an endpoint they should not. The code runs; the answer is slightly wrong."}]},{"t":"p","runs":[{"text":"Invented APIs.","b":true},{"text":" A function, method or parameter that does not exist in the library, with a completely plausible name. This is fabrication in a different costume, and it is common enough to have its own security concern: attackers register package names that models frequently hallucinate. If a package name comes from a model, check it exists on the real index before installing it."}]},{"t":"p","runs":[{"text":"Version drift.","b":true},{"text":" Correct code for an older version of a library. Deprecated arguments, renamed functions, changed defaults. The model’s training has no clean sense of which version you have installed."}]},{"t":"p","runs":[{"text":"Silent type problems.","b":true},{"text":" Integer division where you wanted float, string concatenation where you wanted addition, a pandas operation returning a copy when you expected a view."}]},{"t":"p","runs":[{"text":"Working code, wrong problem.","b":true},{"text":" The most expensive one. It solves what the model understood you to mean, which is not what you meant, and it works perfectly."}]},{"t":"h2","id":"the-rule","runs":[{"text":"The rule"}]},{"t":"p","runs":[{"text":"Read every line before you run it, and be able to say what each line does.","b":true},{"text":" If you cannot, you have not received help; you have received a liability. Run it, then test it on a case where you already know the answer, including an edge case: empty input, one element, a negative number, a duplicate."}]},{"t":"p","runs":[{"text":"That last habit is worth more than any other in this lesson. Generated code is usually tested by the person who received it against exactly the case they had in mind. Testing the boundary takes ten seconds and catches most of the off-by-one class."}]},{"t":"h2","id":"debugging-which-is-the-excellent-use","runs":[{"text":"Debugging, which is the excellent use"}]},{"t":"p","runs":[{"text":"This is where these tools are transformative and where using them well is unambiguously good."}]},{"t":"quote","runs":[{"text":"Here is the error, the full traceback, and the relevant function. Do not rewrite my code. Tell me what the error means, and what would cause it here. I will fix it."}]},{"t":"p","runs":[{"text":"Do not rewrite my code","i":true},{"text":" is the essential clause. Without it you get a rewritten file and no idea what was wrong. With it you get an explanation, and the ability to recognise that error unaided next time, which is the actual skill: professional programmers spend far more time reading errors than writing new code."}]},{"t":"p","runs":[{"text":"Also excellent: pasting a piece of unfamiliar code and asking what it does, line by line. This is reading practice with an infinitely patient annotator, and it is one of the fastest ways to get comfortable in a new codebase or language."}]},{"t":"h2","id":"version-control-is-your-process-record","runs":[{"text":"Version control is your process record"}]},{"t":"p","runs":[{"text":"git","b":true},{"text":" is free, and for a student it does two jobs at once. It is how you avoid losing work, and it is a dated, granular record of your work developing, which is exactly the evidence Module 7 says you want to have before anyone asks for it."}]},{"t":"p","runs":[{"text":"The minimum that helps:"}]},{"t":"code","lang":"bash","label":"Bash","text":"git init\ngit add -A && git commit -m \"first attempt at the parser, failing on nested cases\""},{"t":"p","runs":[{"text":"Commit at the end of every session, including the bad ones. A history of forty commits showing an idea developing, with failures in it, is worth more than any argument you could construct afterwards. GitHub and GitLab both host free private repositories."}]},{"t":"h2","id":"what-to-keep-doing-yourself","runs":[{"text":"What to keep doing yourself"}]},{"t":"p","runs":[{"text":"For a computing student, this list is not optional:"}]},{"t":"ul","items":[[{"text":"Writing a function from a specification, unaided, regularly."}],[{"text":"Reading a stack trace and locating the fault before asking anything."}],[{"text":"Reasoning about complexity: why this is quadratic and that is linear."}],[{"text":"Writing the tests. If the model writes both the code and the tests, the tests check the code’s assumptions rather than the specification’s."}]]},{"t":"p","runs":[{"text":"That last point is subtle and important. Tests written by whatever produced the code will pass by construction. Write the tests first, yourself, from the spec, then let the model help with the implementation. That order preserves the check."}]},{"t":"h2","id":"free-tools-named","runs":[{"text":"Free tools, named"}]},{"t":"p","runs":[{"text":"Python, VS Code or "},{"text":"VSCodium","b":true},{"text":" (the same editor without the telemetry), git, and "},{"text":"Google Colab","b":true},{"text":" for a free notebook with GPU access. For learning to read errors, no tool beats "},{"text":"print","code":true},{"text":" statements and a debugger you have actually opened. Copilot-style completion in the editor is convenient and, for a learner, actively risky: it produces code before you have formed the intention, which removes the design step from the task. Turn it off while you are learning the language, and turn it on later when you can tell instantly whether what it suggested is right."}]}],"check":{"question":[{"text":"Why is it a problem to let a model write both the implementation and the tests for a piece of coursework?"}],"options":[{"text":[{"text":"Because generated tests tend to be shallow and only cover the obvious path through the function."}],"correct":false,"tempting":[{"text":"Often true in practice, but a thorough generated suite would have the same structural flaw; coverage is not the issue."}]},{"text":[{"text":"Because tests written after the implementation are always weaker than tests written first, regardless of who writes them."}],"correct":false,"tempting":[{"text":"States a real test-first principle too absolutely; a human writing tests afterwards against the original specification still provides an independent check."}]},{"text":[{"text":"Because most marking schemes award credit for tests separately, so generated ones cost marks directly."}],"correct":false,"tempting":[{"text":"Answers a marking-policy question rather than a correctness one; the structural problem exists whether or not tests are assessed."}]},{"text":[{"text":"Because the tests encode the same misunderstanding as the code, so they pass by construction."}],"correct":true,"tempting":null}],"order":[2,1,3,0],"why":null},"prev":{"slug":"proofs-and-reasoning","title":"Proofs, and the step that looks fine","minutes":8},"next":{"slug":"lab-sciences-and-units","title":"The lab sciences, and the dimension check","minutes":8}}}