Gains:
- Ability to map chat mode to correct task type with inline completion
- Ability to write powerful production prompts that include input/output contracts, edge cases and style constraints
- Ability to validate generated code and any new proposed dependencies before merging
A developer's first point of contact with AI is often autocomplete — a feature that suggests the next line as you type — or saying "type that function" into a chat window. They both use the same engine but require different disciplines. In this unit, we transform code generation from a random "write it down" into an engineering step whose output is predictable and verifiable.
The goal is to turn AI from a tool that speeds up your typing machine to an apprentice that works within the constraints you set. A well-guided apprentice saves time; An unguided apprentice produces a mess that you have to clean up later.
Two Usage Modes: Inline Completion and Chat
Inline completion comes into play as you type in your editor; You type a function signature or a comment line and it suggests the rest. It's great for speed, but it has a narrow context: it only sees code in the immediate area. That's why it works best when you write your intention clearly in a comment. For example, the //validate user email, throw ValidationError if invalid comment significantly improves the suggestion below.
Chat mode is for larger and structured tasks: "Add pagination to this class", "Extract an interface of that service". Here you have the luxury of giving role, context and format. The general rule is: completion for small and flowing tasks, conversation for tasks that require thinking and structure.
Tip: Don't blindly accept the completion suggestion with "Tab". Read the suggested line for a second; An incorrect variable name or an inverted condition most commonly leaks from here.
Steps to Translate Intention into Code
- Define contract. What is the function's input, output and error behavior? Like "Get email, normalize if valid, throw error if invalid".
- State the constraints. Don't use external dependency? A specific style guide? Is there a performance limit?
- Give an example. An input–output pair (“ali@x.com → valid, ali@ → error”) moves the model's understanding of intent from prediction to precision.
- Ask for small pieces. One function, one responsibility. Then move on to the next one.
- Read and run the generated code. Compiling + a quick manual try is the cheapest assurance step.
Three Mini Cases
Case 1 — Comment-driven production increases accuracy. A developer first requested a date parsing function with an empty body and got the correct result in 3 rounds. In the second attempt, when I defined the function with a 4-line comment (accepted formats, time zone rule, error condition) and requested it, the code that worked in the first round came. Same model, same day; the difference was only the clarity of intent.
Case 2 — Not specifying a version is expensive. One team struggled with the legacy callback-based API replacing fs.promises in code produced for Node.js. When the line "Use Node 20, ESM, async/await" was added to the prompt, production followed the project the first time; The average of 12 minutes spent on correction was reset.
Case 3 — Real gain in boilerplate code. A microservice required 6 new DTO (Data Transfer Object — a simple data class that carries data between layers) and their validation rules. What used to be approximately 90 minutes of manual work was reduced to 35 minutes when produced and reviewed by AI; Since code repetition is high and the pattern is clear, AI worked in its most efficient area here.
Four Copiable Templates
Contract-based function generation:
Role: You are a diligent {{language}} developer.Function contract:- Name: {{name}}- Input: {{types and their meaning}}- Output: {{type and meaning}}- Error status: {{what is thrown/returned when}}Constraints: {{no external dependencies / style / performance}}Examples:- {{input_1}} -> {{output_1}}- {{entry_2}} -> {{error_2}}Give signature + short plan first, then code. Writing tests, just function.
To match existing style (adapt to code base):
Below is an example function from our project; Learn naming, error handling and commenting style here. Write a function for {{new_task}} with the SAME style. Example: {{current_code}}
From skeleton to filling (stub → implementation):
Fill in the function skeleton below according to the TODOs in the comments. CHANGE the signature and return type. Don't make a helper function that doesn't exist; if necessary, let me know "this helper is needed". {{skelet_kod}}
Alternative app comparison:
Give 2 different implementations for {{task}}: (a) prioritizing readability, (b) prioritizing performance. Write down 1 sentence "when is preferable" under each one.
Weak prompt / Strong prompt
Weak: "Write me an email verification function."
Strong: "TypeScript 5, standard library only. Write isValidEmail(input: string): boolean. Trim spaces, make it case insensitive, a@b.co is valid, a@, @b.co, empty string is invalid. If you're going to use regex, don't be overly complex; add 2 lines of comments."
Powerful version; Returns the language, version, signature, edge cases, and a style constraint. Thus, the generated code both works and fits into your project.
Approach
When to use
Attention
Inline completion
Small inserts in flow
Do not accept the suggestion without reading it
Contract based production in chat
New function/class
Give example and edge case
Production by style sample
Adding to existing code
Select current sample code
skeleton stuffing
Signature fixed, body blank
Changing the signature
Code Duplication and the Dependency Trap
The AI often recommends a new library to make its job easier. Sometimes this is accurate, sometimes it adds an unnecessary dependency to your project or suggests a package that doesn't exist (a hallucination). Rule: you confirm each new dependency. Do not add it to the project without verifying that the package actually exists, is maintained, and has the appropriate license. Most of the time a helper already in the project is better than a new package.
Caution: Review the import lines suggested by AI. A non-existent package name (which can also resemble fake packages called "typo-squatting") both breaks compilation and poses a security risk.
Common mistakes
- Having the signature determined by the model. If you do not fix the input/output types, a different signature comes with each production and integration becomes difficult.
- Not to mention edge cases. Empty input, null, negative number, very large value — if you don't specify these, the model writes the "happy path", skipping edges.
- Combining the suggestion without testing it. Code that appears to work doesn't mean it works.
- Accepting unnecessary dependency. Adding a whole library for a one-liner creates technical debt.
- Style inconsistency. Different naming and error handling from the rest of the project makes the code base patchy.
In summary
Code generation is powerful when you translate intent into a clear contract. Use inline completion for small, in-stream tasks, and for tasks that establish structure in the conversation. You specify input/output types, edge cases, version, and style; Give an example of the model; verify each new dependency; and run and read every piece produced. AI pays off best in formulaic, repetitive code — run it right there, within the limits you set.
Application task
Choose an actual small function from your project that you need to write. First print it to the AI with the “contract-based function generation” template, giving input/output types, two edge cases, and a style constraint. Compile the generated code and try it with two different inputs. Then ask the same function again, this time “write me this” without any context, and compare the two outputs line by line: which edge cases were missed, how many corrections were required?
checklist
- [ ] I know where to use chat mode with inline completion.
- [ ] I determine the input/output contract and edge cases in function generation.
- [ ] I have made it a habit to add language and version information to the prompt.
- [ ] I compile and test each produced piece before assembling it.
- [ ] I confirm each new dependency the AI proposes by verifying its existence and necessity.
- [ ] I check that the generated code matches the style of the project.