Gains:
- Ability to write functions, classes and modules to AI with clear input-output and constraint definitions
- Ability to use AI as a pair programming partner and progress step by step, in small, verifiable chunks
- Ability to catch logic and edge case errors by compiling the code generated by AI and running it with small examples
Pair programming is when two developers work on the same problem, with one writing and the other revising. Coding with AI is the digital version of this very relationship: you set the direction, constraints and acceptance criteria; AI produces quick draft; You verify each step by compiling and testing it. The biggest trap here is to tell the AI “write me this application from start to finish” and blindly accept a 200-line block. Good pair programming proceeds in small steps: each step should be understandable, testable and reversible.
In this unit you will learn how to print functions, classes and modules with a clear input-output contract; How to guide AI step by step; and we'll see how to catch logic and edge case errors by running the code it produces with small examples. The goal is not speed, but verified speed.
Concepts: Input-output contract: A clear definition of what input a function takes and what output and error behavior it promises. Edge case: Input that is not ordinary but can actually occur (empty, zero, negative, very large, null). Incremental development: Proceeding with small, working pieces and validating each step.
Printing Code with Net Contract
The basis of quality code is to define exactly "what you want" before starting work. When writing a function to AI, give it five things: language and version, input types and meanings, output, error conditions, and constraints (performance, external library ban, style). This prevents the AI from guessing.
- Write the contract. Input, output, error, constraint.
- Ask for a small unit. A function with a single responsibility; It's not a huge module.
- Request a test block. Add a few sample runs/tests next to the code.
- Compile and run. Try it with edge cases, verify the output by eye.
- Go to the next step. Once a piece is confirmed, build on it.
Contracted function prompt: "Write a function for TypeScript 5. Purpose: calculate the total amount of items in a shopping cart. Input: { price: number, quantity: number }[] array. Output: number (total). Rules: throw Error if quantity or price is negative; return 0 for empty array; round amount to 2 decimal places for decimal error. Do not use external library. Add 5 test cases below the function (normal, empty, negative quantity, decimal price, single item).”
Guiding AI as a Pair
Good progress in pair programming is a dialogue rather than one big request. First, request the skeleton and run it; then add an edge state; then get a bug fixed. This approach keeps the code understandable and puts you in control at every step.
Incremental progress prompt: "We will write a reader that reads a CSV file and converts the lines into an object. Let's go STEP BY STEP, moving on to the next step without me confirming each step. Step 1: just write the skeleton that splits the file into lines and separates the header line. Don't add type conversion or error handling yet. Keep it short, explain."
Explain and justify the code prompt: "Explain the function you just wrote, not line by line, but decision by decision: which design decision you made and why, which edge case you handled and how, which cases you deliberately excluded? List 3 assumptions in the code that I should not miss."
Tip: Don't accept the AI-generated code without understanding it. “Explain this to me, what assumptions did you make?” The question both reveals hidden errors and allows you to defend that code, since the code remains your responsibility. Putting code you don't understand into production is like sending out a contract without signing it.
Weak Prompt / Strong Prompt
WEAK:"Write a sorting function."(Result: which language, what is being sorted, is it stable, what is the performance constraint, code that is vague and probably does not fit the requirement.)STRONG:"For Java 17, write a method that sorts a List<Employee> object first by department (alphabetical), then by salary (descending). DO NOT REPLACE the original list, return the new list. Let null department come last. Explain the complexity of the method in the comment line. specify add a main test block with 4 samples."
Powerful prompt; Includes sorting criterion (two-level), side effect rule (replacing original), null behavior, and test expectation. Without these details, AI produces a plausible but incorrect solution; for example it may corrupt the original list and this will lead to a silent error elsewhere.
Validation with Edge Cases and Small Samples
The code that works in the happy scenario is not the correct code. Consciously force each function produced:
Edge case type
sample input
expected behavior
blank input
Empty array/string
Not an error, logical empty result
Zero/negative
0, -1
Defined and correct behavior
great value
Millions of records
Overflow/performance control
null/undefined
missing space
Controlled error or default
Duplicate/unusual
repetitive, reverse order
correct result
Mini Cases
Case 1 — Silent rounding error. AI writes a function that collects money with decimal (float) types; 0.1 + 0.2 gives 0.30000000000000004. The error is solved when the engineer adds the rule "Round to 2 digits and use whole pennies". A 3-line rule prevents thousands of pennies of variance in the monthly reconciliation.
Case 2 — Side effect trap. The AI writes a method that “sorts” a list, but modifies the original list in place. Unexpected behavior occurs because another module uses the same list. If the "change original" constraint was in the prompt, the error would never occur; gets caught in code review and prevents 2 hours of debugging.
Case 3 — Earnings step by step. A developer prints a 150-line import module at once; When he finds a mistake, he cannot find where it came from. Another developer divides the same work into 5 small steps, tests each step in 2 minutes and catches the error immediately in the 3rd step.
Common mistakes
- Printing large blocks in one request. Risky code that is difficult to understand and debug is born.
- Asking for a code without giving a contract. If input-output-error is ambiguous, AI will guess and be wrong.
- Just testing the happy scenario. If empty, null, negative and large input is not tried, the error is left to production.
- Accepting without understanding. The code you do not disclose is a debt you cannot defend.
- Ignoring sensitive types like side effects and money/date. Float money with timeless history is a classic source of error.
In summary
Writing code with AI is disciplined pair programming: clear contract, small steps, build and test at each step. Giving the input-output-error-constraint quartet from the beginning determines the quality of the code. Explaining the code it produces and forcing it with edge cases brings to the surface the errors hidden under the happy scenario. The source of speed is not blind acceptance; is quick draft plus quick verification.
Application task
Choose a small but real function (e.g. basket total, date difference, text parsing). Print using the contracted function prompt; Add at least 5 test scenarios next to it. Run the code and try 5 edge cases consciously, using the table as a guide. Find a bug in at least one edge case (if not, design a new input to force the function), fix it with AI, and verify by retesting that the fix worked.
checklist
- [ ] I wrote a contract that includes input, output, errors and constraints.
- [ ] I generated the code in small steps instead of one big block.
- [ ] I added a test/sample run block next to the code.
- [ ] I have consciously tested at least 5 edge cases.
- [ ] I explained the code to the AI and reviewed its assumptions.
- [ ] I corrected the error found and confirmed the fix by retesting.