ChatGPT for Developers: Complete Coding Guide
What You'll Learn
By the end of this guide, you'll know how to write better prompts for code generation, debug with AI help, refactor existing code, and generate test coverage. The examples are real — adapt them to your own projects.
Day 1: Foundations
Understanding ChatGPT's Strengths & Weaknesses
What ChatGPT Does Well:
- ✅ Explaining code concepts
- ✅ Generating boilerplate
- ✅ Debugging logic errors
- ✅ Writing tests
- ✅ Code translation between languages
What ChatGPT Struggles With:
- ❌ Very new libraries (post-2023)
- ❌ Company-specific code
- ❌ Complex system design
- ❌ Security-critical code (review needed)
Your First Prompt
❌ Bad Prompt:
write a login function
✅ Good Prompt:
Create a secure login function in Python using Flask and SQLAlchemy.
Requirements:
- Hash passwords with bcrypt
- Return JWT token on success
- Handle errors (user not found, wrong password)
- Include input validation
- Add docstring with examples
Use type hints and follow PEP 8.
ChatGPT Output:
from flask import jsonify, request
from werkzeug.security import check_password_hash
from models import User
import jwt
import datetime
from typing import Tuple, Dict
import re
def validate_email(email: str) -> bool:
"""Validate email format using regex."""
pattern = r'^[\w\.-]+@[\w\.-]+\.\w+$'
return re.match(pattern, email) is not None
def login_user(email: str, password: str) -> Tuple[Dict, int]:
"""
Authenticate user and return JWT token.
Args:
email: User's email address
password: Plain text password
Returns:
Tuple of (response_dict, http_status_code)
Example:
>>> login_user('user@example.com', 'password123')
({'token': 'eyJ0eXAiOiJKV1...'}, 200)
Raises:
ValueError: If email format is invalid
"""
# Input validation
if not email or not password:
return {'error': 'Email and password are required'}, 400
if not validate_email(email):
return {'error': 'Invalid email format'}, 400
# Find user
user = User.query.filter_by(email=email).first()
if not user:
return {'error': 'Invalid credentials'}, 401
# Verify password
if not check_password_hash(user.password_hash, password):
return {'error': 'Invalid credentials'}, 401
# Generate JWT token
token = jwt.encode({
'user_id': user.id,
'email': user.email,
'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=24)
}, app.config['SECRET_KEY'], algorithm='HS256')
return {
'token': token,
'user': {
'id': user.id,
'email': user.email,
'name': user.name
}
}, 200
Practice Exercise
Generate a function for your project using the good prompt pattern:
- Specify language and framework
- List requirements
- Request error handling
- Ask for documentation
- Specify code style
Day 2: Debugging with ChatGPT
Debugging Pattern
Template:
I'm getting this error:
[paste error message]
Here's my code:
[paste relevant code]
Context:
- Language/Framework: [e.g., React 18 + TypeScript]
- What I'm trying to do: [brief explanation]
- What I've tried: [list attempts]
Please explain what's wrong and how to fix it.
Real Example: React Infinite Render
Your Code:
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
fetch(`/api/users/${userId}`)
.then(res => res.json())
.then(setUser);
}); // Bug: missing dependency array
return <div>{user?.name}</div>;
}
Error:
Warning: Maximum update depth exceeded. This can happen when a component
calls setState inside useEffect without a dependency array.
Prompt to ChatGPT:
I'm getting "Maximum update depth exceeded" error in React.
Code:
[paste code above]
Context:
- React 18 + TypeScript
- Trying to fetch user data on component mount
- Error appears immediately on page load
Please explain and fix.
ChatGPT Response:
The problem is the missing dependency array in useEffect.
Current code:
useEffect(() => {
fetch(`/api/users/${userId}`)
.then(res => res.json())
.then(setUser);
}); // Runs after EVERY render
What happens:
1. Component renders
2. useEffect runs, fetches data
3. setUser() causes re-render
4. useEffect runs again (because no dependency array)
5. Infinite loop!
Fix:
useEffect(() => {
fetch(`/api/users/${userId}`)
.then(res => res.json())
.then(setUser);
}, [userId]); // Only run when userId changes
Complete improved version:
useEffect(() => {
let cancelled = false;
const fetchUser = async () => {
try {
const res = await fetch(`/api/users/${userId}`);
if (!res.ok) throw new Error('Failed to fetch user');
const data = await res.json();
if (!cancelled) setUser(data);
} catch (error) {
console.error('Error fetching user:', error);
// Handle error state
}
};
fetchUser();
return () => {
cancelled = true; // Cleanup to prevent state update on unmounted component
};
}, [userId]);
Practice Exercise
Debug a real issue from your codebase using the template above.
Day 3: Learning New Technologies
Learning Pattern
Instead of reading docs for hours, use ChatGPT as a tutor:
Phase 1: Overview (5 min)
Explain [Technology] in simple terms for an experienced developer.
Include:
- What problem it solves
- Key concepts (5-7 most important)
- When to use it vs alternatives
- 30-second example
Example: React developer learning Vue 3
Phase 2: Hello World (10 min)
Create a simple [App Type] using [Technology].
Requirements:
- [Feature 1]
- [Feature 2]
- [Feature 3]
- Include comments explaining key parts
- Production-ready code quality
Example: Todo app with Vue 3 Composition API
Phase 3: Real-World Patterns (15 min)
Show me best practices for [Specific Task] in [Technology].
Include:
- Modern approach (2024)
- Error handling
- Performance considerations
- Common pitfalls to avoid
- Code example
Example: State management in Vue 3
Real Example: Learning FastAPI
Prompt 1:
Explain FastAPI for an Express.js developer.
Include:
- Key differences from Express
- Main advantages
- When to choose FastAPI
- 30-second example
ChatGPT gives clear comparison:
# FastAPI (Python) vs Express (JavaScript) - Key Differences
1. Type Safety: FastAPI uses Python type hints for automatic validation
2. Auto Documentation: Built-in Swagger UI (no extra setup)
3. Async: Native async/await support
4. Performance: Fast as Node.js (due to Starlette/Uvicorn)
When to use FastAPI:
✅ Python ecosystem (ML, data science)
✅ Need automatic API docs
✅ Strong typing important
❌ Node.js ecosystem required
❌ Team only knows JavaScript
# 30-second example
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class User(BaseModel):
name: str
email: str
@app.post("/users")
async def create_user(user: User):
# Type validation automatic!
# API docs automatic!
return {"id": 123, **user.dict()}
# Run: uvicorn main:app --reload
# Docs: http://localhost:8000/docs (auto-generated!)
Prompt 2:
Create a REST API for blog posts using FastAPI.
Requirements:
- CRUD operations (create, read, update, delete)
- SQLite database with SQLAlchemy
- Pydantic models for validation
- Error handling
- Include all necessary imports
Result: Complete working API in 2 minutes
Practice Exercise
Learn a new framework/library in 30 minutes:
- Get overview prompt
- Build hello world prompt
- Implement real feature prompt
Day 4: Code Refactoring
Refactoring Pattern
Refactor this code to improve [specific aspect]:
[paste code]
Requirements:
- [Improvement 1]
- [Improvement 2]
- Keep functionality identical
- Add comments explaining changes
Context:
- [Framework/language details]
- [Performance requirements if any]
Real Example: Cleaning Messy React Component
Original Code:
// 300-line component with everything mixed together
function Dashboard() {
const [users, setUsers] = useState([]);
const [products, setProducts] = useState([]);
const [orders, setOrders] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
// ... 10 more state variables
useEffect(() => {
// 100 lines of data fetching logic
fetch('/api/users').then(...)
fetch('/api/products').then(...)
fetch('/api/orders').then(...)
// ... more fetching
}, []);
// 50 lines of event handlers
return (
<div>
{/* 150 lines of JSX */}
</div>
);
}
Prompt:
Refactor this React component using best practices:
[paste code]
Requirements:
- Extract custom hooks for data fetching
- Separate into smaller components
- Use React Query for caching
- Add proper TypeScript types
- Improve loading/error states
ChatGPT Output:
// 1. Custom hook for data fetching
import { useQuery } from '@tanstack/react-query';
function useDashboardData() {
const users = useQuery({
queryKey: ['users'],
queryFn: () => fetch('/api/users').then(r => r.json())
});
const products = useQuery({
queryKey: ['products'],
queryFn: () => fetch('/api/products').then(r => r.json())
});
const orders = useQuery({
queryKey: ['orders'],
queryFn: () => fetch('/api/orders').then(r => r.json())
});
return {
users: users.data,
products: products.data,
orders: orders.data,
isLoading: users.isLoading || products.isLoading || orders.isLoading,
error: users.error || products.error || orders.error
};
}
// 2. Main component (now clean)
export function Dashboard() {
const { users, products, orders, isLoading, error } = useDashboardData();
if (isLoading) return <LoadingSpinner />;
if (error) return <ErrorMessage error={error} />;
return (
<DashboardLayout>
<UsersSection users={users} />
<ProductsSection products={products} />
<OrdersSection orders={orders} />
</DashboardLayout>
);
}
// 3. Separated components
function UsersSection({ users }: { users: User[] }) {
return (
<section>
<h2>Users</h2>
<UserList users={users} />
</section>
);
}
// ... more components
Before: 300 lines, hard to test, hard to read After: 50-line main component, 5 focused sub-components, easy to test
Practice Exercise
Find a messy file in your codebase and refactor it with ChatGPT.
Day 5: Test Generation
Testing Pattern
Generate comprehensive tests for this code:
[paste code]
Requirements:
- Framework: [Jest/Pytest/etc]
- Cover happy path and edge cases
- Include setup/teardown if needed
- Mock external dependencies
- Aim for >90% coverage
Real Example: Testing API Endpoint
Code to Test:
@app.route('/api/discounts', methods=['POST'])
def calculate_discount():
data = request.get_json()
price = data.get('price')
user_tier = data.get('user_tier')
promo_code = data.get('promo_code')
if not price or price <= 0:
return jsonify({'error': 'Invalid price'}), 400
discount = 0
# Tier discounts
if user_tier == 'bronze': discount += 5
elif user_tier == 'silver': discount += 10
elif user_tier == 'gold': discount += 15
# Promo code
if promo_code == 'SAVE20':
discount += 20
final_price = price * (1 - discount / 100)
return jsonify({
'original_price': price,
'discount_percent': discount,
'final_price': final_price
})
Prompt:
Generate pytest tests for this Flask endpoint:
[paste code]
Requirements:
- Test all user tiers
- Test with/without promo code
- Test edge cases (negative price, invalid tier, etc.)
- Test promo code stacking with tiers
- Use pytest fixtures for app setup
ChatGPT Output:
import pytest
from flask import Flask
from decimal import Decimal
@pytest.fixture
def app():
"""Create Flask app for testing"""
app = create_app('testing')
return app
@pytest.fixture
def client(app):
"""Create test client"""
return app.test_client()
class TestDiscountCalculation:
"""Test discount calculation endpoint"""
def test_no_tier_no_promo(self, client):
"""Test base case: no discount"""
response = client.post('/api/discounts', json={
'price': 100,
'user_tier': None,
'promo_code': None
})
assert response.status_code == 200
data = response.get_json()
assert data['original_price'] == 100
assert data['discount_percent'] == 0
assert data['final_price'] == 100
@pytest.mark.parametrize('tier,expected_discount', [
('bronze', 5),
('silver', 10),
('gold', 15),
])
def test_tier_discounts(self, client, tier, expected_discount):
"""Test each tier discount level"""
response = client.post('/api/discounts', json={
'price': 100,
'user_tier': tier,
'promo_code': None
})
data = response.get_json()
assert data['discount_percent'] == expected_discount
assert data['final_price'] == 100 - expected_discount
def test_promo_code_alone(self, client):
"""Test promo code without tier"""
response = client.post('/api/discounts', json={
'price': 100,
'user_tier': None,
'promo_code': 'SAVE20'
})
data = response.get_json()
assert data['discount_percent'] == 20
assert data['final_price'] == 80
def test_tier_plus_promo_stacking(self, client):
"""Test that tier and promo discounts stack"""
response = client.post('/api/discounts', json={
'price': 100,
'user_tier': 'gold', # 15%
'promo_code': 'SAVE20' # 20%
})
data = response.get_json()
assert data['discount_percent'] == 35 # 15 + 20
assert data['final_price'] == 65
def test_invalid_price_zero(self, client):
"""Test error handling for zero price"""
response = client.post('/api/discounts', json={
'price': 0,
'user_tier': 'gold'
})
assert response.status_code == 400
assert 'error' in response.get_json()
def test_invalid_price_negative(self, client):
"""Test error handling for negative price"""
response = client.post('/api/discounts', json={
'price': -50,
'user_tier': 'gold'
})
assert response.status_code == 400
def test_missing_price(self, client):
"""Test error when price not provided"""
response = client.post('/api/discounts', json={
'user_tier': 'gold'
})
assert response.status_code == 400
def test_invalid_promo_code(self, client):
"""Test that invalid promo codes are ignored"""
response = client.post('/api/discounts', json={
'price': 100,
'user_tier': 'silver',
'promo_code': 'INVALID'
})
data = response.get_json()
# Should only apply tier discount (10%)
assert data['discount_percent'] == 10
def test_large_price(self, client):
"""Test with large price values"""
response = client.post('/api/discounts', json={
'price': 999999.99,
'user_tier': 'gold',
'promo_code': 'SAVE20'
})
assert response.status_code == 200
data = response.get_json()
# 35% off 999999.99
expected = 999999.99 * 0.65
assert abs(data['final_price'] - expected) < 0.01
Coverage: 95%+ with all edge cases
Practice Exercise
Generate tests for a function you wrote recently.
Day 6: Advanced Prompting Techniques
Technique 1: Chain of Thought
Ask ChatGPT to explain its reasoning:
[Your coding question]
Please think step-by-step:
1. Analyze the requirements
2. Consider edge cases
3. Choose the best approach
4. Implement the solution
5. Explain trade-offs
Example:
Design a rate limiting system for an API.
Think step-by-step about:
1. Different rate limiting algorithms
2. Where to store rate limit data
3. Edge cases (distributed systems, clock skew)
4. Implementation approach
5. Trade-offs of each decision
Technique 2: Iterative Refinement
[Initial request]
# After seeing output:
"Great! Now improve it by [specific change]"
# Then:
"Add [feature]"
# Then:
"Optimize for [goal]"
Technique 3: Role-Based Prompting
Act as a senior [role] with 10 years experience.
Review this code and provide:
- What a junior would miss
- Best practices specific to [domain]
- Production readiness checklist
Code:
[paste code]
Example:
Act as a senior DevOps engineer.
Review this Dockerfile and provide:
- Security issues
- Performance optimizations
- Production readiness checklist
Dockerfile:
FROM python:latest
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
CMD python app.py
ChatGPT (as DevOps expert):
# Issues found:
1. SECURITY: Using 'latest' tag (unpredictable)
2. SECURITY: Running as root (default)
3. PERFORMANCE: Installing all deps every build (no caching)
4. PERFORMANCE: Large image size (python:latest ~900MB)
5. RELIABILITY: No health check
6. DEBUGGING: No logging configuration
# Improved Dockerfile:
FROM python:3.11-slim as builder # ✅ Specific version, smaller base
# Create non-root user
RUN useradd -m -u 1000 appuser
# Install dependencies (cached layer)
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy app code
COPY --chown=appuser:appuser . .
# Switch to non-root user
USER appuser
# Health check
HEALTHCHECK --interval=30s --timeout=3s \
CMD python -c "import requests; requests.get('http://localhost:8000/health')"
# Expose port
EXPOSE 8000
# Run app
CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:8000", "app:app"]
# Production checklist:
# ✅ Specific base image version
# ✅ Non-root user
# ✅ Dependency caching
# ✅ Small image size (~150MB vs 900MB)
# ✅ Health check
# ✅ Production WSGI server (gunicorn)
# ✅ Proper logging (gunicorn logs to stdout)
Day 7: Building Your Workflow
Create Your Prompt Library
Save effective prompts for reuse:
# prompts.md
## Code Review
Act as a senior developer. Review this [language] code for:
1. Bugs and logic errors
2. Performance issues
3. Security vulnerabilities
4. Code style and readability
5. Missing edge cases
Provide specific line numbers and fixes.
---
## Documentation
Generate comprehensive documentation for this code:
- Purpose and overview
- Parameters with types
- Return values
- Usage examples
- Edge cases and error handling
Format: [JSDoc/docstring/etc]
---
## Refactoring
Refactor this code following [framework] best practices:
- Improve readability
- Reduce complexity
- Optimize performance
- Add proper types
- Follow [style guide]
Explain each major change.
Keyboard Shortcuts / IDE Integration
VS Code Extension: ChatGPT - Genie AI
- Select code → Right click → "Ask ChatGPT"
- Keyboard shortcut:
Ctrl+Shift+G
Command Line:
# Create alias
alias askgpt='function _ask(){ curl -X POST https://api.openai.com/v1/chat/completions -H "Content-Type: application/json" -H "Authorization: Bearer $OPENAI_API_KEY" -d "{\"model\":\"gpt-4\",\"messages\":[{\"role\":\"user\",\"content\":\"$1\"}]}" | jq -r ".choices[0].message.content"; }; _ask'
# Usage
askgpt "Explain this regex: ^[\w\.-]+@[\w\.-]+\.\w+$"
Daily Workflow Integration
Morning:
- Review overnight errors with ChatGPT
- Plan day's tasks (architecture questions)
During Coding:
- Generate boilerplate
- Debug errors as they occur
- Explain unfamiliar code
Before Commit:
- Generate tests
- Write commit message
- Review changes
Code Review:
- Get AI review before human review
- Explain complex changes for PR description
Pro Tips
1. Always Verify AI Code
# Don't trust blindly!
# ❌ Bad: Copy-paste without reading
# ✅ Good: Read, understand, test
ai_generated_code = get_from_chatgpt()
# Read it
understand(ai_generated_code)
# Test it
run_tests(ai_generated_code)
# Review for security
check_security(ai_generated_code)
# Then use it
2. Use ChatGPT to Learn, Not Just Get Answers
# ❌ Bad: "Fix my code"
# ✅ Good: "Explain why this doesn't work and teach me the concept"
3. Combine with Documentation
# Best workflow:
1. Read official docs (15 min)
2. Ask ChatGPT for clarification (5 min)
3. Try implementation (20 min)
4. Debug with ChatGPT if needed (10 min)
Total: 50 min to learn new concept
4. Track Cost (GPT-4)
# If using API
import openai
def count_tokens(text):
# Approximate: 1 token ≈ 4 characters
return len(text) // 4
prompt = "Your prompt here"
tokens = count_tokens(prompt)
cost = tokens * $0.03 / 1000 # GPT-4 pricing
print(f"Estimated cost: ${cost:.4f}")
Common pitfalls
1. Hallucinated Functions
ChatGPT might invent functions that don't exist:
# ChatGPT might suggest:
result = pandas.magic_function(df) # ❌ Doesn't exist!
# Always verify in docs
2. Outdated Information
Training data cutoff (Jan 2024 for GPT-4):
# ❌ ChatGPT doesn't know about:
- Libraries released after 2024
- Latest API changes
- Recent security vulnerabilities
# ✅ Solution: Provide documentation in prompt
3. Over-Engineering
ChatGPT tends to suggest complex solutions:
# You asked: "Store user preferences"
# ChatGPT suggests: Redis + RabbitMQ + Kafka + Microservices
# Reality: JSON file is fine for your use case
# Always question: "Is this complexity necessary?"
After 7 days
You'll have a set of prompt patterns that work for your stack, and you'll know when ChatGPT is useful vs. when you need to just read the docs.
Next steps
Once you have the basics down, try combining ChatGPT with an IDE integration like Copilot or Cursor — chat plus inline suggestions work well together. Beyond that, use it on real problems.
Resources
- OpenAI Playground - Test prompts
- ChatGPT - Start coding
- Prompt Engineering Guide - Learn more
- Our Prompt Library - Ready-to-use prompts
Last Updated: 2025-11-09 | Difficulty: Beginner to Advanced | Time: 7 days
Want to explore other AI coding tools? Check our Complete Comparison Guide.