Coding with LLMs: Practical Guidance, Challenges, and Everyday Use

Introduction

  • What are LLMs? Large Language Models trained on vast amounts of code and text
  • Why use LLMs for coding? Boost productivity, tackle new languages, solve unfamiliar problems
  • This presentation covers:
    • Practical techniques for effective prompting
    • Common challenges and solutions
    • Real-world use cases and workflows
    • Future of coding with AI assistance

The LLM Coding Landscape

  • Popular coding assistants:
    • GitHub Copilot
    • Claude
    • GPT-4/ChatGPT
    • Anthropic Claude Code
    • Amazon CodeWhisperer
    • Google Gemini
  • Strengths: Documentation, boilerplate, refactoring, learning, debugging
  • Limitations: Complex algorithms, cutting-edge frameworks, security-critical code

Effective Prompting Techniques

  • Be specific about context:

    • Programming language
    • Libraries/frameworks in use
    • Project constraints
    • Error messages (when debugging)
  • Request step-by-step explanations:

    Write a Python function to process CSV data. Explain each step of your implementation.
    

Code Generation Best Practices

  • Start with requirements, not implementation:

    I need a function that takes a list of user records and returns only active users sorted by registration date. Use JavaScript.
    
  • Include examples for clarity:

    Input: [{"name": "Alice", "active": true, "registered": "2023-01-15"}, 
            {"name": "Bob", "active": false, "registered": "2022-11-03"}]
    Expected output: [{"name": "Alice", "active": true, "registered": "2023-01-15"}]
    

Example: Basic Code Generation

Ask:

Write a Python function that calculates the Fibonacci sequence up to n terms.

Result:

def fibonacci(n):
    """Generate Fibonacci sequence up to n terms."""
    sequence = []
    if n <= 0:
        return sequence
    if n >= 1:
        sequence.append(0)
    if n >= 2:
        sequence.append(1)
    
    for i in range(2, n):
        sequence.append(sequence[i-1] + sequence[i-2])
    
    return sequence

# Example usage
print(fibonacci(10))  # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

Iterative Refinement

  • Start simple and build complexity:

    Can you modify the function to be more memory efficient using a generator?
    
  • Request specific improvements:

    Add error handling for negative inputs and type validation.
    
  • Ask for optimization:

    Can you optimize this code for performance? The current implementation is too slow.
    

Example: Iterative Refinement

Improved version:

def fibonacci_generator(n):
    """Generate Fibonacci sequence up to n terms using a generator."""
    if not isinstance(n, int):
        raise TypeError("Input must be an integer")
    if n < 0:
        raise ValueError("Input must be a non-negative integer")
    
    if n > 0:
        yield 0
    if n > 1:
        yield 1
    
    a, b = 0, 1
    for _ in range(2, n):
        a, b = b, a + b
        yield b

# Example usage
print(list(fibonacci_generator(10)))  # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

Debugging with LLMs

  • Share the complete error message:

    I'm getting this error: "TypeError: cannot unpack non-iterable int object"
    Here's my code: [paste code here]
    
  • Provide execution context:

    This function works with small inputs but crashes with larger datasets.
    
  • Ask for explanations, not just fixes:

    Can you explain why this error is occurring and how to fix it?
    

Example: Debugging with LLMs

Error:

RecursionError: maximum recursion depth exceeded

Code:

def factorial(n):
    return n * factorial(n - 1)

LLM-assisted fix:

def factorial(n):
    if n == 0 or n == 1:
        return 1
    return n * factorial(n - 1)

Unit Testing with LLMs

  • Request comprehensive test cases:

    Generate unit tests for this function covering edge cases and normal operation.
    
  • Ask for specific testing frameworks:

    Write pytest test cases for this user authentication function.
    
  • Generate test data:

    Create sample test data for validating this e-commerce checkout process.
    

Example: Test Generation

import pytest
from fibonacci import fibonacci_generator

def test_fibonacci_zero_terms():
    assert list(fibonacci_generator(0)) == []

def test_fibonacci_one_term():
    assert list(fibonacci_generator(1)) == [0]

def test_fibonacci_two_terms():
    assert list(fibonacci_generator(2)) == [0, 1]

def test_fibonacci_ten_terms():
    assert list(fibonacci_generator(10)) == [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

def test_fibonacci_negative_input():
    with pytest.raises(ValueError):
        list(fibonacci_generator(-1))

def test_fibonacci_type_error():
    with pytest.raises(TypeError):
        list(fibonacci_generator("10"))

Documentation Generation

  • Create function docstrings:

    Write detailed docstrings for this Python class following NumPy style.
    
  • Generate README files:

    Create a README.md for my project that [describe project].
    
  • Create API documentation:

    Generate OpenAPI documentation for this REST endpoint.
    

Example: Documentation Generation

def process_transaction(transaction_id, amount, currency="USD", description=None):
    """
    Process a financial transaction and record it in the database.
    
    Parameters
    ----------
    transaction_id : str
        Unique identifier for the transaction
    amount : float
        The amount to be processed, must be positive for credits,
        negative for debits
    currency : str, optional
        Three-letter ISO currency code, by default "USD"
    description : str, optional
        Additional information about the transaction
    
    Returns
    -------
    dict
        Transaction receipt with status and confirmation number
    
    Raises
    ------
    ValueError
        If amount is zero or currency is invalid
    TransactionError
        If the transaction processing fails
        
    Examples
    --------
    >>> process_transaction("T123", 99.99, description="Annual subscription")
    {'status': 'success', 'confirmation': 'C987654321', 'timestamp': '2023-06-01T14:30:00Z'}
    """

Common Challenges

  • Hallucinated APIs and functions:

    • Always verify library functions exist
    • Cross-check documentation for correct usage
  • Outdated knowledge:

    • Verify compatibility with your framework/library versions
    • Update prompts with version specifics
  • Security vulnerabilities:

    • Review code for security best practices
    • Never trust LLM code for authentication/authorization without review

Real-world Workflow: New Feature Development

  1. Define requirements with the LLM:

    I need to add a user profile export feature that generates a PDF summary.
    What components would I need to build?
    
  2. Generate component architecture:

    Create a sequence diagram for the user profile export flow.
    
  3. Implement components incrementally

  4. Test and refine

Real-world Workflow: Learning New Technology

  1. Ask for conceptual overview:

    Explain how React hooks work and when to use them.
    
  2. Request example implementation:

    Show me how to implement a custom useState hook for form validation.
    
  3. Ask for best practices:

    What are common mistakes when using React hooks?
    
  4. Build incrementally with guidance

Best Practices for Everyday Use

  • Maintain a critical eye - Always review generated code
  • Use LLMs as collaborative partners, not autonomous replacements
  • Build a prompt library for common tasks
  • Treat LLM outputs as first drafts
  • Learn from explanations, not just code
  • Create clear boundaries for which code can be LLM-assisted vs. manual

Future Trends

  • More specialized coding assistants
  • Better context understanding
  • Improved customization
  • Tighter IDE integration
  • Enhanced security analysis
  • Multi-modal assistance (code + diagrams + natural language)

Resources

Questions?

Thank you!

Contact:

deck

By A Bakker

deck

  • 60