Chatbots like ChatGPT and GPT-4 have evolved from simple conversational agents into powerful coding assistants. When you craft the right prompt, these models can generate boilerplate code, debug subtle logic errors, refactor legacy systems, and even help you design high-level software architecture. However, the difference between a vague request and a precise, context-rich prompt can be night and day.
This article presents 15 carefully curated prompts for programming tasks, organized into three skill levels: Basic (writing and understanding code), Advanced (debugging and refactoring), and Expert (architecture and optimization). Each prompt includes a specific task, the exact text to use in ChatGPT or GPT-4, and a real-world example with output. By the end, you’ll have a toolkit that can accelerate your daily development work.
Sources note: The techniques described here leverage capabilities documented in OpenAI’s GPT-4 System Card (March 2023) and the Chain-of-Thought prompting paper by Wei et al. (2022). Real-world case studies come from the author’s experience and community reports.
Basic Level: Writing and Understanding Code
Prompt 1: Generate a Function from a Description
Task: Ask the model to implement a specific function when you provide a clear specification.
Prompt:
Write a Python function that takes a list of integers and returns the median. The function should handle empty lists by returning None. Include type hints and a docstring explaining the algorithm.
Example output:
from typing import List, Optional
def median(numbers: List[int]) -> Optional[float]:
"""
Compute the median of a list of integers.
If the list is empty, returns None.
Uses sorting and then picks the middle element(s).
Args:
numbers: A list of integers.
Returns:
The median as a float, or None if the list is empty.
"""
if not numbers:
return None
sorted_nums = sorted(numbers)
n = len(sorted_nums)
mid = n // 2
if n % 2 == 1:
return float(sorted_nums[mid])
else:
return (sorted_nums[mid - 1] + sorted_nums[mid]) / 2.0
Prompt 2: Explain Code Step by Step
Task: Ask GPT to act as a tutor and explain a piece of code line by line.
Prompt:
Explain the following JavaScript code line by line, assuming the reader is new to closures:
function createCounter() {
let count = 0;
return function() {
count += 1;
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
Example output:
- function createCounter() { ... } – defines a function that creates a local variable count and returns an inner function.
- let count = 0; – initializes a private variable inside the closure.
- return function() { ... } – the inner function is returned but retains access to count (closure).
- count += 1; – increments the closed-over variable.
- const counter = createCounter(); – executes createCounter, stores the returned function.
- Each call to counter() increments and returns the same count variable, demonstrating stateful closures.
Prompt 3: Convert Code Between Languages
Task: Translate a simple algorithm from one language to another.
Prompt:
Convert this Python code to Rust, preserving the logic and using idiomatic Rust:
def factorial(n: int) -> int:
if n <= 1:
return 1
return n * factorial(n - 1)
Example output:
fn factorial(n: u64) -> u64 {
if n <= 1 {
1
} else {
n * factorial(n - 1)
}
}
Prompt 4: Write Unit Tests for a Function
Task: Generate test cases for an existing function.
Prompt:
Given the following Python function, write a comprehensive set of unit tests using pytest. Include edge cases:
def is_palindrome(s: str) -> bool:
cleaned = ''.join(c.lower() for c in s if c.isalnum())
return cleaned == cleaned[::-1]
Example output:
import pytest
from my_module import is_palindrome
def test_simple_palindrome():
assert is_palindrome("racecar") == True
def test_simple_not_palindrome():
assert is_palindrome("hello") == False
def test_mixed_case():
assert is_palindrome("A man, a plan, a canal: Panama") == True
def test_empty_string():
assert is_palindrome("") == True
def test_only_spaces():
assert is_palindrome(" ") == True
def test_with_numbers():
assert is_palindrome("12321") == True
def test_none_input():
with pytest.raises(TypeError):
is_palindrome(None)
Prompt 5: Generate Regular Expressions
Task: Ask the model to create a regex based on natural language description.
Prompt:
Create a Python regular expression that matches valid email addresses according to the following rules:
- Local part can contain letters, digits, dots, hyphens, and underscores.
- Domain part can contain letters, digits, and hyphens, with at least one dot.
- TLD must be at least two letters.
Demonstrate usage with re.search.
Example output:
import re
email_pattern = r"^[a-zA-Z0-9._-]+@[a-zA-Z0-9-]+\.[a-zA-Z]{2,}$"
test_emails = ["user@example.com", "john.doe@company.co", "invalid@",
"@domain.com", "user@.com"]
for e in test_emails:
match = re.search(email_pattern, e)
print(f"{e}: {bool(match)}")
Advanced Level: Debugging and Refactoring
Prompt 6: Find the Bug in This Code
Task: Provide a snippet that has a logical error and ask GPT to pinpoint it.
Prompt:
The following function is supposed to return the largest element in a list, but it fails for some inputs. Identify the bug and provide a corrected version.
def find_max(arr):
max_val = 0
for x in arr:
if x > max_val:
max_val = x
return max_val
print(find_max([-5, -2, -10])) # Expected -2, but gets 0
Example explanation:
The bug is initializing max_val = 0. For lists with all negative numbers, 0 is always larger, so the function returns 0 incorrectly. The fix is to initialize max_val = arr[0] (or float('-inf')) after checking the list is not empty.
Corrected code:
def find_max(arr):
if not arr:
return None
max_val = arr[0]
for x in arr:
if x > max_val:
max_val = x
return max_val
Prompt 7: Add Error Handling
Task: Ask GPT to wrap existing code with proper error handling.
Prompt:
Add try/except blocks to the following function to handle file not found, permission errors, and JSON decode errors. Log each error appropriately using the logging module.
def load_config(path):
with open(path) as f:
return json.load(f)
Example output:
import json
import logging
logger = logging.getLogger(__name__)
def load_config(path):
try:
with open(path) as f:
return json.load(f)
except FileNotFoundError:
logger.error(f"Config file not found: {path}")
return {}
except PermissionError:
logger.error(f"Permission denied: {path}")
return {}
except json.JSONDecodeError as e:
logger.error(f"Invalid JSON in {path}: {e}")
return {}
Prompt 8: Refactor a Messy Function
Task: Give a poorly written function and ask for a clean, modular refactoring.
Prompt:
Refactor the following Python code into well-named functions with proper separation of concerns. Add type hints and a main block.
def process(data):
s = 0
for i in data:
s += i
avg = s / len(data)
above = 0
for i in data:
if i > avg:
above += 1
print("Sum:", s)
print("Average:", avg)
print("Count above average:", above)
Example output:
from typing import List
def calculate_sum(numbers: List[float]) -> float:
return sum(numbers)
def calculate_average(numbers: List[float]) -> float:
return sum(numbers) / len(numbers)
def count_above_threshold(numbers: List[float], threshold: float) -> int:
return sum(1 for x in numbers if x > threshold)
def main():
data = [10, 20, 30, 40, 50]
total = calculate_sum(data)
avg = calculate_average(data)
above = count_above_threshold(data, avg)
print(f"Sum: {total}")
print(f"Average: {avg}")
print(f"Count above average: {above}")
if __name__ == "__main__":
main()
Prompt 9: Optimize a Slow Loop
Task: Provide a piece of inefficient code and ask for a faster version.
Prompt:
This code finds pairs that sum to a target, but it runs in O(n²). Rewrite it to use a hash map for O(n) complexity.
def find_pairs(arr, target):
pairs = []
for i in range(len(arr)):
for j in range(i+1, len(arr)):
if arr[i] + arr[j] == target:
pairs.append((arr[i], arr[j]))
return pairs
Example output:
def find_pairs_optimized(arr, target):
seen = {}
pairs = []
for num in arr:
complement = target - num
if complement in seen:
pairs.append((complement, num))
seen[num] = True
return pairs
Prompt 10: Improve Code Readability
Task: Ask GPT to apply best practices like meaningful variable names and comments.
Prompt:
The following code works but is hard to read. Rename variables, add comments, and break it into smaller functions. The goal is to calculate the Levenshtein distance between two strings.
def ld(a, b):
m, n = len(a), len(b)
d = [[0]*(n+1) for _ in range(m+1)]
for i in range(m+1):
d[i][0] = i
for j in range(n+1):
d[0][j] = j
for i in range(1, m+1):
for j in range(1, n+1):
cost = 0 if a[i-1]==b[j-1] else 1
d[i][j] = min(d[i-1][j]+1, d[i][j-1]+1, d[i-1][j-1]+cost)
return d[m][n]
Example output:
def levenshtein_distance(str1: str, str2: str) -> int:
"""Compute the Levenshtein edit distance between two strings."""
len1, len2 = len(str1), len(str2)
# Initialize distance matrix with dimensions (len1+1) x (len2+1)
distance = [[0] * (len2 + 1) for _ in range(len1 + 1)]
# Base cases: distance from empty string
for i in range(len1 + 1):
distance[i][0] = i
for j in range(len2 + 1):
distance[0][j] = j
# Fill the matrix
for i in range(1, len1 + 1):
for j in range(1, len2 + 1):
substitution_cost = 0 if str1[i-1] == str2[j-1] else 1
distance[i][j] = min(
distance[i-1][j] + 1, # deletion
distance[i][j-1] + 1, # insertion
distance[i-1][j-1] + substitution_cost # substitution
)
return distance[len1][len2]
Expert Level: Architecture and Optimization
Prompt 11: Design a System Architecture
Task: Ask GPT to outline a high-level design for a given requirement.
Prompt:
Design a microservices architecture for an e-commerce platform that handles user authentication, product catalog, shopping cart, and order processing. Describe each service, its responsibilities, and how they communicate (synchronous vs async). Include considerations for scalability and fault tolerance.
Example output (abridged):
- Auth Service: Handles registration, login, JWT tokens. Uses a relational database. Communicates via REST.
- Product Catalog Service: Stores product data, images, inventory. Uses a read-optimized NoSQL database (e.g., MongoDB). Exposes REST endpoints.
- Cart Service: Manages user carts in a Redis cache for fast reads. Publishes events (e.g., “item added”) to a message queue (Kafka).
- Order Service: Listens to events from Cart, processes payments, updates inventory via async messages. Writes to a relational database.
- API Gateway: Single entry point, routes requests, enforces rate limiting.
- Async communication for order placement (Kafka) ensures the system can handle spikes without blocking.
- Fault tolerance: Each service is stateless and deployed behind a load balancer; database replicas and circuit breakers (e.g., Hystrix) are recommended.
Prompt 12: Suggest Code Review Improvements
Task: Paste a pull request diff and ask for a code review.
Prompt:
Act as a senior developer reviewing this pull request. Point out potential issues related to security, performance, and maintainability. Offer concrete suggestions.
```diff
+ def get_user(email):
+ conn = sqlite3.connect("users.db")
+ cursor = conn.cursor()
+ cursor.execute(f"SELECT * FROM users WHERE email = '{email}'")
+ return cursor.fetchone()
+
+ @app.route("/user")
+ def user_profile():
+ email = request.args.get("email")
+ user = get_user(email)
+ return jsonify(user)
**Example review:**
- **SQL Injection:** The query uses f-string interpolation. Use parameterized queries: `cursor.execute("SELECT * FROM users WHERE email = ?", (email,))`.
- **Connection Management:** The function opens a new database connection each call but never closes it. Use a context manager or connection pooling.
- **No Error Handling:** If `email` is missing or the connection fails, the function crashes. Add try/except and return appropriate HTTP errors.
- **Exposing Raw Data:** `jsonify(user)` might expose the entire row including hashed password. Convert to a dict with only safe fields.
---
### Prompt 13: Generate a Database Schema
**Task:** Describe a domain and ask for an optimized schema.
**Prompt:**
Design a PostgreSQL schema for a blogging platform. Include tables for users, posts, comments, and tags. Add appropriate indexes, foreign keys, and an optimized query to fetch the 10 most recent posts with their author name and comment count.
**Example output:**
```sql
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE posts (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id),
title VARCHAR(200) NOT NULL,
body TEXT NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_posts_created_at ON posts(created_at DESC);
CREATE TABLE tags (
id SERIAL PRIMARY KEY,
name VARCHAR(30) UNIQUE NOT NULL
);
CREATE TABLE post_tags (
post_id INTEGER REFERENCES posts(id),
tag_id INTEGER REFERENCES tags(id),
PRIMARY KEY (post_id, tag_id)
);
CREATE TABLE comments (
id SERIAL PRIMARY KEY,
post_id INTEGER NOT NULL REFERENCES posts(id) ON DELETE CASCADE,
user_id INTEGER REFERENCES users(id),
body TEXT NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_comments_post_id ON comments(post_id);
-- Query for latest 10 posts with author and comment count
SELECT p.id, p.title, u.username, COUNT(c.id) AS comment_count
FROM posts p
JOIN users u ON p.user_id = u.id
LEFT JOIN comments c ON c.post_id = p.id
GROUP BY p.id, u.id
ORDER BY p.created_at DESC
LIMIT 10;
Prompt 14: Refactor to Use Design Patterns
Task: Ask to apply a specific design pattern to improve code structure.
Prompt:
The following code handles different payment methods using if-else. Refactor it using the Strategy pattern in Python.
def process_payment(method, amount):
if method == "credit_card":
print(f"Charging {amount} via credit card")
# actual credit card logic
elif method == "paypal":
print(f"Charging {amount} via PayPal")
# PayPal logic
elif method == "bitcoin":
print(f"Charging {amount} via Bitcoin")
# Bitcoin logic
Example output:
from abc import ABC, abstractmethod
class PaymentStrategy(ABC):
@abstractmethod
def pay(self, amount: float):
pass
class CreditCardPayment(PaymentStrategy):
def pay(self, amount):
print(f"Charging {amount} via credit card")
class PayPalPayment(PaymentStrategy):
def pay(self, amount):
print(f"Charging {amount} via PayPal")
class BitcoinPayment(PaymentStrategy):
def pay(self, amount):
print(f"Charging {amount} via Bitcoin")
class PaymentProcessor:
def __init__(self, strategy: PaymentStrategy):
self.strategy = strategy
def process(self, amount):
self.strategy.pay(amount)
# Usage
processor = PaymentProcessor(CreditCardPayment())
processor.process(100)
Prompt 15: Write a Dockerfile and CI/CD Pipeline
Task: Ask for production-ready infrastructure configuration.
Prompt:
Generate a multi-stage Dockerfile for a Python Flask application, and a GitHub Actions workflow that builds, tests, and deploys the Docker image to Docker Hub on every push to main.
Example Dockerfile:
FROM python:3.11-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
FROM builder AS dev
COPY . .
CMD ["python", "app.py"]
FROM python:3.11-slim AS prod
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
COPY . .
EXPOSE 5000
CMD ["gunicorn", "-b", "0.0.0.0:5000", "app:app"]
Example GitHub Actions workflow (.github/workflows/deploy.yml):
name: Build and Deploy
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Log in to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: yourusername/app:latest
Conclusion
These 15 prompts demonstrate the breadth of what ChatGPT and GPT-4 can do for programmers—from writing a simple function to designing a full system architecture. The key is to be specific, provide context, and ask for structured output. As you incorporate these prompts into your workflow, you’ll likely discover new ways to delegate routine tasks and focus on the creative parts of software development.
Start by copying a prompt that matches your current need, then adapt it. The more precise your language, the more valuable the model’s response will be. Happy prompting!
Comments