DEV Community

Cover image for AI Coding Pitfalls and Solutions: A Practical Guide
rodit-org
rodit-org

Posted on

AI Coding Pitfalls and Solutions: A Practical Guide

Introduction

Most developers, if not all, are using AI by now. This is helping both newbies and highly experienced professionals.

Unfortunately, like any other tool, AI coding can be less than helpful. Do you recall stories about people who end up in a lake following a GPS map application blindly? Something similar happens frequently to developers while using AI.

Common Issues

1. Default Pessimism

The AI not only misses the context you don't share with it, it will not ask for more context, assuming you are telling it everything that needs to be told. For example, if you don't say you have access to the production server, it will try to solve the issue assuming there isn't access.

2. Know-it-all Syndrome

The AI will give you a long list of all the things you can check and all the things you can try, like it had the magical bullet for your issue. Good luck working your way through.

3. Just Plaster It!

The AI knows nothing of root causes. Presented with an issue it will try to solve that one issue ONLY, without checking why the issue is there in the first place. It tries to solve symptoms, not problems.

4. Goldberg Machine Patch

The AI tries to give you a solution that will solve this issue and any other possible ever present in any system ever, and check and log everything under the sun. The solution seems to be bulletproof at first sight, but it is so complex it creates issues on its own that may be harder to fix than the original issue.

5. Dude Comparisons

The AI will compare what you need to compare, but will miss essential components, for example overall number of items.

Solutions and Examples

It is not hard to avoid these issues if you remember that you are a driver, not a passenger, in the coding process. Here are the solutions you can use to avoid each issue:

1. Default Pessimism - Solution

Share most of the context, and instruct it to request more context whenever necessary. Provide working similar samples if available.

Example:

Bad Prompt:

How can I check if users are active in my system?
Enter fullscreen mode Exit fullscreen mode

AI's Limited Response:

def check_user_activity(user_id):
    # Assumes only local database access
    with open('user_logs.txt', 'r') as f:
        logs = f.readlines()
    return any(str(user_id) in log for log in logs)
Enter fullscreen mode Exit fullscreen mode

Better Prompt:

I need to check if users are active in my system. We have:
- PostgreSQL database with user_sessions table
- Access to Redis cache
- Cloudwatch logs
- User activity tracked in NewRelic
Please ask if you need more context about any of these systems.
Enter fullscreen mode Exit fullscreen mode

AI's Comprehensive Response:

def check_user_activity(user_id):
    # Check Redis cache first for performance
    activity = redis_client.get(f"user_activity:{user_id}")
    if activity:
        return json.loads(activity)

    # Check database for recent sessions
    with db.connection() as conn:
        result = conn.execute("""
            SELECT last_active_at 
            FROM user_sessions 
            WHERE user_id = %s
            ORDER BY last_active_at DESC 
            LIMIT 1
        """, (user_id,))
        return result.fetchone()
Enter fullscreen mode Exit fullscreen mode

2. Know-it-all Syndrome - Solution

Request the AI to take only one step at a time, checking the result of each step before proceeding with the next.

Example:

Bad Prompt:

My API endpoints are slow. How can I improve performance?
Enter fullscreen mode Exit fullscreen mode

Better Prompt:

My /users endpoint is taking 2.5s to respond. Let's start by profiling the database queries.
Here's the current code:

def get_users():
    users = User.query.all()
    return jsonify([user.to_dict() for user in users])

What's the first step to identify the bottleneck?
Enter fullscreen mode Exit fullscreen mode

3. Just Plaster It! - Solution

Ask the AI to explain how that solution is going to solve the problem.

Example:

Bad Code Issue:

# Original problem
try:
    process_payment(amount)
except Exception:
    return "Payment failed"
Enter fullscreen mode Exit fullscreen mode

Bad Prompt:

How do I fix this payment error?
Enter fullscreen mode Exit fullscreen mode

Better Prompt:

We're seeing payment failures in production. Here's the code:

try:
    process_payment(amount)
except Exception:
    return "Payment failed"

Before implementing a fix, can you help me understand:
1. What types of exceptions might occur here?
2. How would each exception impact our payment flow?
3. What logging would help us identify the root cause?
Enter fullscreen mode Exit fullscreen mode

4. Goldberg Machine Patch - Solution

Ask the AI if this is a standard, best practice way to solve the issue, and if there is a simpler solution that will solve it.

Example:

Problem:

def save_user(user_data):
    db.users.insert(user_data)
Enter fullscreen mode Exit fullscreen mode

Bad Prompt:

How can I make this user save function more robust?
Enter fullscreen mode Exit fullscreen mode

AI's Overcomplicated Response:

def save_user(user_data: Dict[str, Any]) -> Union[str, None]:
    """
    Ultra-robust user saving with extensive validation and logging
    """
    transaction_id = str(uuid.uuid4())
    logger.info(f"Starting user save operation {transaction_id}")

    try:
        # Pre-save validation
        validation_result = validate_user_schema(user_data)
        if not validation_result.is_valid:
            logger.error(f"Schema validation failed: {validation_result.errors}")
            metrics.increment("user.save.validation_error")
            raise ValidationError(validation_result.errors)

        # Backup current state
        existing_user = db.users.find_one({"email": user_data["email"]})
        if existing_user:
            backup_collection.insert_one({
                "type": "user_backup",
                "data": existing_user,
                "timestamp": datetime.utcnow()
            })

        # Complex retry logic
        for attempt in exponential_backoff(max_attempts=5):
            with attempt:
                result = db.users.insert_one(user_data)

        # Post-save validation
        saved_user = db.users.find_one({"_id": result.inserted_id})
        assert saved_user == user_data, "Save verification failed"

        # Extensive logging
        logger.info(f"User save successful {transaction_id}")
        metrics.increment("user.save.success")

        return str(result.inserted_id)

    except Exception as e:
        logger.error(f"User save failed {transaction_id}: {str(e)}")
        metrics.increment("user.save.error")
        notification.alert_team("User save failed", context=locals())
        raise
Enter fullscreen mode Exit fullscreen mode

Better Prompt:

I need to add basic error handling and validation to this user save function.
What's the minimal change that would catch common issues?
Enter fullscreen mode Exit fullscreen mode

AI's Simpler Response:

def save_user(user_data: dict) -> bool:
    """
    Save user with basic validation and error handling
    """
    if not all(k in user_data for k in ['email', 'name']):
        logger.error(f"Missing required fields: {user_data}")
        return False

    try:
        db.users.insert_one(user_data)
        return True
    except DuplicateKeyError:
        logger.error(f"User already exists: {user_data['email']}")
        return False
Enter fullscreen mode Exit fullscreen mode

5. Dude Comparisons - Solution

Ask the AI to perform a bijective comparison of items. This guarantees each and every item is compared with a peer only once.

Example:

Bad Prompt:

Compare these two API response formats
Enter fullscreen mode Exit fullscreen mode

Better Prompt:

Can you do a field-by-field comparison of these two API response formats,
ensuring every field in both formats is addressed:

Format A:
{
    "user_id": "string",
    "name": "string",
    "roles": ["string"]
}

Format B:
{
    "id": "string",
    "full_name": "string",
    "permissions": ["string"]
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

By following these guidelines and remembering that you are the driver in the development process, you can effectively leverage AI as a powerful tool while avoiding its common pitfalls. The key is to be specific, provide context, and guide the AI step-by-step towards the solution you need.

API Trace View

Struggling with slow API calls? 🕒

Dan Mindru walks through how he used Sentry's new Trace View feature to shave off 22.3 seconds from an API call.

Get a practical walkthrough of how to identify bottlenecks, split tasks into multiple parallel tasks, identify slow AI model calls, and more.

Read more →

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Explore a sea of insights with this enlightening post, highly esteemed within the nurturing DEV Community. Coders of all stripes are invited to participate and contribute to our shared knowledge.

Expressing gratitude with a simple "thank you" can make a big impact. Leave your thanks in the comments!

On DEV, exchanging ideas smooths our way and strengthens our community bonds. Found this useful? A quick note of thanks to the author can mean a lot.

Okay