# Prompting for Code — Write Specs, Not Wishes (Context, Constraints, Examples and Acceptance Tests)

Source: https://skills101.in/learn/ai-coding-assistants/prompting-for-code — Skills101 free tutorial (AI Coding Assistants). Updated 2026-11-09.

"Write a function to validate a phone number" gets you *a* function. Whether it's the function **you need** depends on everything you didn't say. Good prompting for code is mostly **good requirements writing** — a skill that also makes you a better engineer without AI.

## 1. Weak prompt vs strong prompt

**Weak:**

> write a python function to validate indian phone numbers

The model must guess: Which formats? Return `True/False` or a cleaned number? Landlines? `+91`? Spaces? It will pick something plausible — maybe not what your app needs.

**Strong:**

> Write a Python 3.12 function `normalise_indian_mobile(raw: str) -> str | None`.
> - Accept Indian **mobile** numbers typed in common ways: `9876543210`, `98765 43210`, `+91 98765 43210`, `+91-98765-43210`, `919876543210`, `09876543210`.
> - Return the number as `+91XXXXXXXXXX`, or `None` if invalid.
> - Valid mobiles have 10 digits starting with 6, 7, 8 or 9. Reject landlines, short numbers and non-Indian numbers.
> - No external libraries. Include a few `assert` tests covering valid and invalid inputs.

Now there is exactly one right answer, and the tests will prove it.

![Prompt anatomy: role and goal, context (language, versions, existing code), the exact task and signature, constraints, examples of input and output, and acceptance tests or a definition of done](https://skills101.in/learn-img/ai-coding-assistants/prompt-anatomy.svg)

## 2. A reusable spec template

```text
GOAL: what this code is for and who uses it (one or two lines)
CONTEXT: language + version, framework, relevant existing code/schema (paste it)
TASK: exact function/endpoint/component, with signature
INPUTS/OUTPUTS: types, formats, examples
RULES & EDGE CASES: empty input, limits, errors, time zones, money, permissions
CONSTRAINTS: libraries allowed/forbidden, style, performance, security
DONE WHEN: tests that must pass / behaviour to verify
OUTPUT FORMAT: just the code? code + tests? explain trade-offs first?
```

You won't need every line every time — but each line you skip is a guess you hand to the model.

## 3. Check the result like a reviewer

Here's what a good implementation of the strong prompt looks like, with the acceptance tests run for real:

```python
import re

def normalise_indian_mobile(raw: str) -> str | None:
    digits = re.sub(r"[\s\-()]", "", raw)
    if digits.startswith("+91"):
        digits = digits[3:]
    elif digits.startswith("91") and len(digits) == 12:
        digits = digits[2:]
    elif digits.startswith("0") and len(digits) == 11:
        digits = digits[1:]
    if re.fullmatch(r"[6-9]\d{9}", digits):
        return "+91" + digits
    return None

valid = ["9876543210", "98765 43210", "+91 98765 43210", "+91-98765-43210", "919876543210", "09876543210"]
invalid = ["12345", "5876543210", "01414937243", "+1 415 555 0100", "", "98765432101"]
for v in valid:
    assert normalise_indian_mobile(v) == "+919876543210", v
for v in invalid:
    assert normalise_indian_mobile(v) is None, v
print("all", len(valid) + len(invalid), "acceptance tests passed")
```

```text
all 12 acceptance tests passed
```

The tests came **from the prompt**. Writing the "DONE WHEN" section first is the single best habit in this lesson.

## 4. Techniques that consistently help

**Ask for a plan first.** For anything bigger than one function:

> Before writing code, list the steps, the files you'd change, and any questions or assumptions. Wait for my OK.

You catch misunderstandings when they cost one message, not 300 lines.

**Show, don't just tell.** Paste an existing function written in your project's style and say *"follow this pattern"*. Paste one real input row and the exact expected output.

**Give the error and the code together** (lesson 5) — never just "it doesn't work".

**Split big tasks.** "Build a full exam portal" → schema → API for one entity → tests → UI page → next entity. Small steps are easier to review and easier for the model to get right.

**State what NOT to do.** "Don't add new dependencies." "Don't change the function signature." "Don't touch files outside `src/payments/`."

**Ask it to ask you.** "If anything is ambiguous, ask me before assuming." Good assistants will.

**Iterate precisely.** Instead of "still wrong", say *"For input `[]` it returns `None`; it should return `0.0`. Keep everything else the same."*

## 5. Example: a better prompt for a real task

> **Goal:** Students should get a certificate when they pass every lesson quiz in a subject.
> **Context:** Next.js 16 + Prisma. Relevant models pasted below (`User`, `Quiz`, `QuizAttempt`, `Certificate`). Existing helper `awardXp(userId, kind, refId, amount)` pasted below.
> **Task:** Write `checkTutorialCertificate(userId, topicId)` that issues a certificate if the user has a passing attempt for every published lesson quiz in the topic.
> **Rules:** Only published quizzes count. Issue at most one certificate per user per topic (idempotent). Passing = score ≥ 60%.
> **Constraints:** Use the existing Prisma client; no raw SQL; one transaction.
> **Done when:** Unit tests cover: no quizzes, some passed, all passed, called twice (still one certificate).
> **Output:** Plan first, then code, then tests.

Compare that to "add certificates for tutorials". The second prompt produces something; the first produces **your** feature.

## 6. Prompts for learning (not just output)

When you're learning, change the request:

- "Don't give me the solution. Give me a hint about which data structure to use."
- "Here's my solution — what's the time complexity, and what edge case breaks it?"
- "Explain this code line by line as if I'm in second year."
- "Quiz me with 5 questions on Python dictionaries, one at a time."

You'll learn faster than with either a textbook or copy-pasting answers.

## Common mistakes

- One-line prompts for multi-step features.
- Not pasting the relevant existing code, schema or error.
- Accepting the first answer without tests.
- Saying "make it better" instead of describing exactly what's wrong.
- Pasting secrets (API keys, customer data) into prompts — lesson 7.

## Quick recap

- Prompt = **spec**: goal, context, task, inputs/outputs, edge cases, constraints, **done when**, output format.
- Write acceptance tests first; check the result against them.
- Ask for a plan first, show examples, split big tasks, say what not to do, iterate precisely.
- For learning, ask for hints and explanations instead of full solutions.


Practice quiz and free certificate: https://skills101.in/learn/ai-coding-assistants/prompting-for-code