15 Prompts for ChatGPT and GPT-4: From Code Generation to System Architecture

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!

← All posts

Comments