Module 8 · Expert Track15 min read · Prompt Engineering Mastery

Prompting for Code and Technical Tasks

Code generation is where prompt engineering meets the highest-stakes domain of AI-assisted work — bad outputs in a document are an inconvenience, but bad code can be a silent bug in production. The techniques in this module transform AI from an unreliable autocomplete into a disciplined technical collaborator.

The Anatomy of a Great Code Generation Prompt

Most people ask for code the same way they would ask a search engine: "Python function to parse CSV." This produces generic, untestable code that rarely fits the actual context. Expert code prompting provides the model with the complete specification a professional engineer would need before writing a single line.

A complete code generation prompt includes: the programming language and version, the runtime environment and constraints, the function signature or interface you need, edge cases that must be handled, what should happen on failure, and any existing code or APIs it must integrate with. Think of it as writing a ticket in a well-run engineering team.

Write a Python 3.11 function with this exact signature: def parse_webhook_payload( raw_body: bytes, signature: str, secret: str, tolerance_seconds: int = 300 ) -> dict: Requirements: - Verify the HMAC-SHA256 signature using the secret - Reject payloads where the timestamp is older than tolerance_seconds (use the 't' field in the payload) - Parse and return the JSON body as a dict on success - Raise ValueError with descriptive messages on: * Invalid signature * Expired timestamp * Malformed JSON * Missing required fields ('t', 'data') Do NOT use any external libraries beyond hashlib and json. Include type hints throughout. After the function, write pytest unit tests covering: - Happy path with valid signature and fresh timestamp - Expired timestamp rejection - Invalid signature rejection - Missing 't' field rejection

Notice what this prompt does: it specifies the exact signature (no ambiguity about interface), the exact error conditions (no guessing about edge cases), the constraints (no external libraries), and it requests tests alongside the implementation. This prompt is closer to a specification document than a question.

Test-Driven Prompting

One of the most powerful code prompting techniques is to provide the tests first and ask the model to write code that passes them. This flips the typical AI coding workflow and has several profound advantages: you define the contract explicitly, the model has an objective success criterion to optimize against, and you immediately have a test suite regardless of how the implementation looks.

Write a Python function called `merge_sorted_arrays` that makes all of the following tests pass. Do not modify the tests. import pytest def test_basic_merge(): assert merge_sorted_arrays([1,3,5], [2,4,6]) == [1,2,3,4,5,6] def test_empty_arrays(): assert merge_sorted_arrays([], []) == [] assert merge_sorted_arrays([1,2,3], []) == [1,2,3] assert merge_sorted_arrays([], [1,2,3]) == [1,2,3] def test_duplicates(): assert merge_sorted_arrays([1,2,2,3], [2,3,4]) == [1,2,2,2,3,3,4] def test_single_elements(): assert merge_sorted_arrays([5], [3]) == [3,5] def test_already_sorted(): assert merge_sorted_arrays([1,2,3], [4,5,6]) == [1,2,3,4,5,6] def test_large_arrays(): a = list(range(0, 1000, 2)) b = list(range(1, 1001, 2)) result = merge_sorted_arrays(a, b) assert result == list(range(1000)) assert len(result) == 1000 Implement the most efficient algorithm and state its time and space complexity after the code.
Why Test-Driven Prompting Works

When you provide tests, you eliminate an entire category of misunderstanding. The model cannot produce technically valid but semantically wrong code because the tests define semantics precisely. The model also cannot take shortcuts on edge cases — they are all enumerated in the test suite.

Debugging Prompts

Debugging is one of the highest-leverage uses of AI assistance, but generic "what's wrong with this code?" prompts waste the model's ability. Effective debugging prompts provide: the code, the exact error message or unexpected behavior, the expected behavior, what you have already tried, and the relevant environment information.

I have a bug I cannot figure out. Here is the context: LANGUAGE: Python 3.10 ENVIRONMENT: FastAPI 0.104, running in Docker on Linux THE CODE: [paste the relevant function or module] THE ERROR (exact output from terminal): Traceback (most recent call last): File "/app/api/routes.py", line 47, in process_request result = await service.transform(data) File "/app/services/transform.py", line 23, in transform return {k: float(v) for k, v in data.items()} ValueError: could not convert string to float: 'N/A' EXPECTED BEHAVIOR: The transform function should skip or substitute 0.0 for any values that cannot be converted to float. WHAT I HAVE TRIED: - Checked that the data dict looks correct before the call - Confirmed the error is always on 'N/A' strings from the upstream API Please: (1) explain the root cause, (2) provide a fix, (3) suggest any defensive improvements to make this more robust against other non-numeric strings in future.

Code Review Prompts

AI code review is most valuable when you structure it as a multi-dimensional analysis rather than a generic "review this code" request. Different review dimensions require different mental modes: security analysis requires adversarial thinking, performance requires measurement orientation, readability requires empathy for future maintainers. Combining them in one prompt produces shallow treatment of each.

Review the following Python function for SECURITY vulnerabilities only. Do not comment on style, performance, or logic unless the issue is security-relevant. For each vulnerability found: 1. Name the vulnerability class (e.g., SQL injection, path traversal, SSRF) 2. Quote the exact line(s) containing the vulnerability 3. Explain the exploit scenario in plain language 4. Provide a corrected version of those specific lines If you find no security vulnerabilities, say so explicitly and briefly explain why the main risk areas appear safe. CODE TO REVIEW: [paste code here]

Run separate review passes for security, performance, and readability. Each pass produces actionable, focused feedback rather than a diluted overview of everything.

Documentation Generation

Documentation generation is an underutilized application of prompt engineering. Models can produce docstrings, README sections, API reference documentation, and architectural explanations — but only if you specify the audience, format, and depth precisely.

Generate complete documentation for the following Python module. TARGET AUDIENCE: Junior engineers who understand basic Python but are new to this codebase. REQUIRED SECTIONS: 1. Module Overview (2-3 sentences: what it does, when to use it) 2. Installation / Dependencies (list any non-stdlib dependencies) 3. Quick Start (a minimal working example in a code block) 4. Function Reference (for every public function: purpose, parameters with types, return value, exceptions raised, and one example call) 5. Common Gotchas (edge cases or non-obvious behaviors that junior engineers frequently get wrong) FORMAT: GitHub-flavored Markdown MODULE CODE: [paste module here]

Explaining Complex Codebases

When onboarding to an unfamiliar codebase or trying to understand inherited legacy code, prompt engineering turns what would take days of archaeology into hours of structured analysis. The key is to request a hierarchical explanation: architecture first, then modules, then specific functions — never the other way around.

I am a new engineer joining this project. Explain this codebase to me at three levels: LEVEL 1 — ARCHITECTURE (200 words) What does this system do overall? What are its main components? What is the data flow from input to output? LEVEL 2 — KEY MODULES (bullet list) For each major file or module in the code I've pasted: - What is its single responsibility? - What does it depend on? - What depends on it? LEVEL 3 — NON-OBVIOUS PATTERNS What design patterns, conventions, or architectural decisions would confuse a competent engineer who hasn't seen this specific codebase before? What do I need to know to avoid breaking things? CODEBASE: [paste relevant files]

Domain-Specific Technical Prompting

Technical prompting extends beyond general-purpose code into domain-specific contexts: data engineering, ML pipelines, infrastructure-as-code, database query optimization, and more. Each domain has its own vocabulary, failure modes, and performance considerations that a well-crafted prompt can activate.

The principle is the same: give the model enough domain context to reason like a specialist, not just write syntactically valid code. For SQL optimization, include the execution plan. For ML prompts, include the dataset shape and target metric. For infrastructure code, include the cloud provider, region constraints, and cost sensitivity.

Optimize this PostgreSQL query for a table with 50 million rows. The query currently takes 8-12 seconds. Target: under 500ms. CURRENT QUERY: SELECT u.email, COUNT(o.id) as order_count, SUM(o.total_cents) as lifetime_value FROM users u LEFT JOIN orders o ON o.user_id = u.id WHERE u.created_at > '2022-01-01' AND o.status = 'completed' GROUP BY u.id, u.email ORDER BY lifetime_value DESC LIMIT 100; CURRENT INDEXES: - users: primary key (id), index on created_at - orders: primary key (id), index on user_id EXPLAIN ANALYZE OUTPUT: [paste output here] Please: 1. Explain what is causing the slow performance 2. Suggest index changes with exact CREATE INDEX statements 3. Suggest query rewrites if applicable 4. Estimate the expected improvement for each suggestion
Summary

Code prompting rewards specificity above all else. Provide the language, version, constraints, signature, and edge cases upfront. Use test-driven prompting to define the contract precisely. Structure debugging prompts with the full error context. Run code reviews as focused single-dimension passes. For documentation and explanation tasks, specify audience, format, and depth explicitly. In domain-specific contexts, include the technical metadata (execution plans, dataset shapes, infrastructure constraints) that a specialist would need to reason correctly.