The 10 Prompting Patterns Every Developer Should Know
Beyond copy-pasting error messages — these are the reusable mental models that make AI genuinely useful for software engineering. Learn the pattern once, apply it to every problem.
Most developers treat AI prompting as a skill you either have or you don't. It's not. It's a set of learnable patterns — reusable structures you can apply to almost any problem. Learn the pattern once and you can adapt it to every new situation.
This article covers 10 patterns that experienced AI users reach for constantly. Some you probably know. Some will change how you work.
1. Role Assignment
You tell the AI who to be before you give it the task. The role sets the vocabulary, the level of depth, and the assumptions the AI makes about what you need.
Without a role: you get a general answer. With a role: you get an answer calibrated to a specific perspective, seniority level, and domain.
-- Without role: "Review this code." -- With role: "You are a senior backend engineer who has been burned by production incidents caused by poor error handling. Review this code with that lens — what would keep you up at night if this shipped? [paste code]"
Useful roles for developers: senior engineer (critical review), junior developer (explains what the code does simply), security researcher (looks for vulnerabilities), technical writer (makes documentation clear), developer who's never seen this codebase (tests whether the code is self-explanatory).
2. Rubber Duck Prompting
Rubber duck debugging is the practice of explaining a bug out loud to an inanimate object — the act of explaining forces you to think through the problem systematically. AI makes this dramatically more useful because the rubber duck talks back.
Instead of asking the AI to solve your problem, ask it to ask you questions. This keeps you thinking rather than just accepting an answer.
"I have a bug I can't solve and I want to work through it. Instead of giving me a solution, ask me one diagnostic question at a time — like a doctor narrowing down a diagnosis. I'll answer each one and you ask the next question based on my answer. Bug: my API endpoint returns 200 but the data is empty when called from the frontend. It works fine when I test it directly with Postman."
The AI will ask about authentication headers, CORS preflight, request parameters, environment differences — and your answers will often surface the issue before you even reach a fix.
3. Explain Then Fix
Instead of asking for a fix directly, ask the AI to explain what's wrong before it fixes it. This serves two purposes: you learn from the explanation, and it forces the AI to reason through the problem before committing to a solution — which produces more accurate fixes.
"Here is my code and the error I'm getting: [paste code + error] Before you give me a fix: 1. Explain what is causing this error in plain English 2. Explain why the current code produces this behaviour 3. Then give me the fix with an explanation of what changed and why I want to understand the bug, not just copy a fix."
This pattern works especially well for bugs in logic you don't fully understand — new language features, unfamiliar frameworks, or code written by someone else.
4. Test-First Prompting
Ask the AI to write tests before writing the implementation. This mirrors TDD and forces the AI to reason about what the code should do before thinking about how to implement it.
"I need to write a function that [describe what it should do]. Before you write the implementation: 1. Write comprehensive tests for this function — happy paths, edge cases, error cases 2. The tests should document the expected behaviour clearly 3. Then write the implementation that makes all the tests pass Requirements: - [list specific requirements] - Language: [language] - Testing framework: [framework]"
This also works well when you have existing untested code. Ask for the tests first, then ask the AI to review whether the tests match the actual behaviour — discrepancies reveal either bugs in the code or bugs in your assumptions.
5. The Constraints Frame
Add explicit constraints to every task where the output could go in many directions. Without constraints, the AI picks defaults that may not match your situation. With constraints, you get an answer shaped for your specific context.
-- Unconstrained: "Refactor this function to be cleaner." -- Constrained: "Refactor this function. Constraints: - Do not change the function signature (other code depends on it) - Do not introduce any new dependencies - Keep it in plain JavaScript — no TypeScript - Optimise for readability over cleverness — this will be maintained by junior devs - The function must run in Node.js 14+ (no optional chaining ?. please) [paste function]"
Useful constraint categories: don't change X, keep Y, optimise for Z, avoid W, must work with N. The more specific your constraints, the more usable the output.
6. Comparative Analysis
When you're deciding between two approaches, don't ask the AI which is better in the abstract. Give it both options and ask it to compare them against your specific priorities.
"I'm deciding between two approaches for [describe the problem]. Option A: [describe or paste code] Option B: [describe or paste code] My priorities in order: 1. [most important — e.g. correctness] 2. [second — e.g. performance at scale] 3. [third — e.g. ease of maintenance] 4. [fourth — e.g. developer experience] Compare the two options against each priority. Then give me a recommendation and explain any tradeoffs I should be aware of."
This pattern works for: implementation approaches, library choices, architecture decisions, database schema options, API design alternatives.
7. Before / After Refactoring
When asking for a refactor, ask the AI to show you the before and after side by side with an explanation of every change. This makes the refactor reviewable — you can see exactly what changed and why, rather than having to diff two versions yourself.
"Refactor this function to improve readability. Show me: 1. The original code (labelled BEFORE) 2. The refactored code (labelled AFTER) 3. A numbered list of every change you made with a one-line explanation of why Do not change the external behaviour. Do not change the function signature. [paste code]"
This pattern also works for documentation: ask for the before (original) and after (improved) version of a README, docstring, or comment with a list of what was changed.
8. The Socratic Prompt
Instead of asking for an answer, ask the AI to teach you by asking questions. This is especially useful when you're learning a new concept and want to test your understanding rather than just read an explanation.
"Quiz me on [concept] in [language]. Ask me one question at a time. After I answer each one: - Tell me if I'm right or wrong - Explain the correct answer if I got it wrong - Then ask the next question Start easy and get progressively harder. Begin." -- Variant for architecture decisions: "I'm going to describe my architecture plan. Instead of telling me if it's right or wrong, ask me questions about my assumptions and edge cases — like a technical interviewer would. I want to find the gaps in my thinking myself. My plan: [describe]"
This pattern builds real understanding rather than just transferring information. If you can answer the AI's questions correctly, you understand the material. If you can't, you know exactly where the gaps are.
9. The Exhaustive List
When you're doing something where missing an item has consequences — security review, edge case analysis, test coverage, migration planning — ask the AI to be exhaustive rather than comprehensive. The word choice matters.
"List EVERY possible cause of this error. I don't want the 3 most likely causes — I want all of them, including edge cases. I'll filter by likelihood myself: [paste error]" "List EVERY edge case this function doesn't currently handle. Be exhaustive. Include cases that are unlikely but would cause silent failures: [paste code]" "List EVERY thing that could go wrong when I run this database migration. Include things that are unlikely. I need to know what to roll back from: [describe migration]"
The AI will naturally tend to give you the 3-5 most likely things. Asking for an exhaustive list pushes it to think through the long tail — which is often where the real problems hide.
10. Iterative Refinement
The best prompt isn't the first prompt — it's the third. Each iteration narrows the output toward what you actually need. Most developers get a first response that's 60% right and give up. The 60% is the starting point, not the result.
Here's how an iterative refinement session looks:
-- Round 1: get the rough shape "Write a function that [describe requirement]" -- Round 2: fix what's wrong "Good start. A few issues: 1. The function doesn't handle [edge case] — it should [describe expected behaviour] 2. The variable names are too vague — rename [x] to [something descriptive] 3. The error message on line [N] isn't helpful — make it say exactly what went wrong Update the function with these fixes." -- Round 3: add what's missing "Almost there. Two more things: 1. Add input validation at the top — throw a specific error if [condition] 2. Add a JSDoc comment documenting the parameters and return value Final version please."
The key is being specific about what's wrong. "Make it better" produces generic improvements. "The error handling swallows the original error — re-throw it with the original message attached" produces exactly what you asked for.
Combining Patterns
The real power comes from combining these patterns in a single prompt. A code review prompt might combine Role Assignment (senior engineer), Exhaustive List (every possible issue), and Constraints Frame (focus on production readiness). A debugging session might combine Rubber Duck Prompting (ask me questions) with Explain Then Fix (explain the root cause before suggesting a solution).
- Role + Constraints: "As a security researcher reviewing production code, identify every input that could be maliciously crafted. Don't stop at the obvious ones."
- Test-First + Explain Then Fix: "Write tests that expose this bug, then explain the root cause, then fix it."
- Comparative + Exhaustive: "Compare these two approaches. For each, list every way it could fail in production."
- Rubber Duck + Iterative: "Ask me questions about this bug. After each answer, tell me what new information it gives you about the probable cause."
Ready to go further?
Take the interactive course — daily lessons, real exercises, XP and streaks. Turn reading into lasting skills.
