Skip to content

Instantly share code, notes, and snippets.

@BunHouth
Created March 21, 2025 13:15
Show Gist options
  • Save BunHouth/cf27d6f09653253568c4085c876b2dbe to your computer and use it in GitHub Desktop.
Save BunHouth/cf27d6f09653253568c4085c876b2dbe to your computer and use it in GitHub Desktop.

How AI Can Help with Software Development

A Guide for Software Teams


Agenda

  1. Understanding AI in Software Development
  2. Effective Prompting Techniques
  3. Practical Applications & Common Challenges
  4. Hands-on Examples

1. Understanding AI in Software Development

What AI Can Do for Developers

  • Code Generation: Create boilerplate, functions, and entire components
  • Code Explanation: Understand unfamiliar codebases or complex algorithms
  • Debugging: Identify and fix errors in your code
  • Refactoring: Improve existing code quality and structure
  • Documentation: Generate clear documentation for code and APIs
  • Testing: Create test cases and testing frameworks
  • Learning: Accelerate learning of new languages or frameworks

Types of AI Tools for Development

  • Large Language Models (ChatGPT, Claude, GitHub Copilot)
  • Code-Specific Models (Amazon CodeWhisperer, Tabnine)
  • Automated Testing Tools (Functionize, Testim)
  • Code Review Assistants (DeepCode, CodeGuru)
  • Natural Language to Code Converters (GPT-4, Claude)

Benefits of Using AI in Development

  • Productivity Boost: Reduce time spent on repetitive tasks
  • Knowledge Expansion: Access to broad technical knowledge
  • Error Reduction: Catch mistakes early in the development process
  • Learning Acceleration: Quick understanding of new technologies
  • Documentation Improvement: Better, more consistent documentation
  • Focus on Creativity: More time for complex problem-solving

2. Effective Prompting Techniques

What Makes a Good Prompt?

  • Specificity: Clear context and requirements
  • Structured Information: Well-organized input
  • Technical Details: Relevant constraints and specifications
  • Examples: Reference code or desired output format
  • Step-by-Step Guidance: Breaking down complex requests

Prompt Engineering for Developers

Basic Structure:

1. Context: What are you working on?
2. Task: What do you need?
3. Constraints: Any limitations or requirements?
4. Format: How should the response be structured?
5. Examples: Any reference implementations?

Example Prompts: Before and After

❌ Weak Prompt:

"Write a function to sort data"

✅ Strong Prompt:

"Write a TypeScript function that sorts an array of Product objects 
by price in descending order. Each Product has: id (number), 
name (string), price (number), and category (string).
Include error handling for empty arrays and handle ties by 
sorting alphabetically by name. Use ES6 syntax and include JSDoc."

Keywords That Improve Results

  • Technical specifications: "TypeScript", "React", "RESTful API"
  • Design patterns: "Singleton", "Factory", "Observer"
  • Code style: "ES6", "functional programming", "immutable"
  • Performance considerations: "O(n) time complexity", "memory efficient"
  • Quality markers: "unit tested", "edge cases", "error handling"

Advanced Prompting Techniques

  • Chain of Thought: Guide the AI through complex reasoning
  • Few-Shot Learning: Provide examples for the AI to learn from
  • Role Assignment: "Act as a senior developer reviewing this code"
  • Iterative Refinement: Start broad, then refine with follow-ups
  • System Design Prompting: Break down architecture design step-by-step

3. Practical Applications & Common Challenges

Real-World Applications

  • Bootstrapping Projects: Generate initial project structure
  • API Development: Create endpoints, documentation, and tests
  • Frontend Components: Build UI components from descriptions
  • Data Processing: Transform data between formats
  • Legacy Code Migration: Port code to new languages/frameworks
  • Technical Debt Reduction: Refactor and improve code quality

Common Challenges

  • Code Hallucinations: AI generating plausible but incorrect code
  • Outdated Knowledge: LLMs may not know recent frameworks/libraries
  • Security Concerns: Potential for insecure code suggestions
  • Dependency Understanding: Limited knowledge of project dependencies
  • Over-Reliance: Reduced learning and critical thinking
  • Integration Issues: Generated code may not fit larger architecture

Best Practices for AI in Development

  • Verify All Output: Always review and test AI-generated code
  • Maintain Security Standards: Check for vulnerabilities
  • Use for Augmentation: Not replacement of developer skills
  • Continuous Learning: Stay updated on AI capabilities
  • Document AI Usage: Note where AI was used in your codebase
  • Ethical Considerations: Be transparent about AI assistance

4. Hands-on Examples

Example 1: API Endpoint Development

Prompt:

Create a Node.js Express API endpoint that handles user registration.
Include validation for email and password, hashing for password storage,
and proper error responses. Use async/await and include comments.

Result:

/**
 * User registration endpoint
 * Validates input, hashes password, and stores user
 */
app.post('/api/register', async (req, res) => {
  try {
    const { email, password, name } = req.body;
    
    // Validation
    if (!email || !password || !name) {
      return res.status(400).json({ error: 'All fields are required' });
    }
    
    if (!/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/.test(email)) {
      return res.status(400).json({ error: 'Invalid email format' });
    }
    
    if (password.length < 8) {
      return res.status(400).json({ 
        error: 'Password must be at least 8 characters long' 
      });
    }
    
    // Check if user already exists
    const existingUser = await User.findOne({ email });
    if (existingUser) {
      return res.status(409).json({ error: 'Email already registered' });
    }
    
    // Hash password
    const saltRounds = 10;
    const hashedPassword = await bcrypt.hash(password, saltRounds);
    
    // Create new user
    const user = new User({
      email,
      password: hashedPassword,
      name,
      createdAt: new Date()
    });
    
    await user.save();
    
    // Return success without exposing password
    res.status(201).json({
      message: 'User registered successfully',
      userId: user._id
    });
    
  } catch (error) {
    console.error('Registration error:', error);
    res.status(500).json({ error: 'Server error during registration' });
  }
});

Example 2: UI Component Creation

Prompt:

Create a React functional component for a filterable product table.
It should display products grouped by category, allow searching by name,
and have a toggle to show only in-stock items. Use hooks for state
management and include proper TypeScript typing.

Result:

import React, { useState } from 'react';

interface Product {
  id: number;
  name: string;
  price: number;
  category: string;
  inStock: boolean;
}

interface FilterableProductTableProps {
  products: Product[];
}

const FilterableProductTable: React.FC<FilterableProductTableProps> = ({ products }) => {
  const [searchText, setSearchText] = useState('');
  const [inStockOnly, setInStockOnly] = useState(false);
  
  // Filter products based on search and stock filter
  const filteredProducts = products.filter(product => {
    const matchesSearch = product.name.toLowerCase().includes(searchText.toLowerCase());
    const matchesStock = inStockOnly ? product.inStock : true;
    return matchesSearch && matchesStock;
  });
  
  // Group products by category
  const groupedProducts: Record<string, Product[]> = {};
  filteredProducts.forEach(product => {
    if (!groupedProducts[product.category]) {
      groupedProducts[product.category] = [];
    }
    groupedProducts[product.category].push(product);
  });
  
  return (
    <div className="filterable-product-table">
      <div className="search-bar">
        <input
          type="text"
          placeholder="Search products..."
          value={searchText}
          onChange={(e) => setSearchText(e.target.value)}
        />
        <label>
          <input
            type="checkbox"
            checked={inStockOnly}
            onChange={(e) => setInStockOnly(e.target.checked)}
          />
          Only show products in stock
        </label>
      </div>
      
      <div className="product-table">
        {Object.keys(groupedProducts).length === 0 ? (
          <p>No products found</p>
        ) : (
          Object.entries(groupedProducts).map(([category, categoryProducts]) => (
            <div key={category} className="category-section">
              <h3>{category}</h3>
              <table>
                <thead>
                  <tr>
                    <th>Name</th>
                    <th>Price</th>
                    <th>Status</th>
                  </tr>
                </thead>
                <tbody>
                  {categoryProducts.map(product => (
                    <tr key={product.id}>
                      <td>{product.name}</td>
                      <td>${product.price.toFixed(2)}</td>
                      <td>{product.inStock ? 'In Stock' : 'Out of Stock'}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          ))
        )}
      </div>
    </div>
  );
};

export default FilterableProductTable;

Example 3: Code Refactoring

Prompt:

Refactor this function to be more readable and efficient:

function getData(id, callback) {
  db.connect(function(err, connection) {
    if (err) { callback(err, null); return; }
    connection.query("SELECT * FROM users WHERE id = " + id, function(err, user) {
      if (err) { callback(err, null); return; }
      if (!user) { callback(new Error("User not found"), null); return; }
      connection.query("SELECT * FROM orders WHERE user_id = " + id, function(err, orders) {
        if (err) { callback(err, null); return; }
        user.orders = orders;
        callback(null, user);
        connection.close();
      });
    });
  });
}

Result:

/**
 * Fetches user data and their orders by user ID
 * 
 * @param {number} id - The user ID to query
 * @returns {Promise<Object>} - Promise resolving to user object with orders
 */
async function getUserWithOrders(id) {
  // Input validation
  if (!id || typeof id !== 'number') {
    throw new Error('Valid user ID is required');
  }
  
  let connection;
  try {
    // Establish database connection
    connection = await db.connectAsync();
    
    // Use parameterized queries for security
    const userQuery = "SELECT * FROM users WHERE id = ?";
    const user = await connection.queryAsync(userQuery, [id]);
    
    if (!user || user.length === 0) {
      throw new Error('User not found');
    }
    
    // Get user orders with parameterized query
    const orderQuery = "SELECT * FROM orders WHERE user_id = ?";
    const orders = await connection.queryAsync(orderQuery, [id]);
    
    // Add orders to user object
    const userData = user[0];
    userData.orders = orders || [];
    
    return userData;
    
  } catch (error) {
    // Rethrow with context for better debugging
    throw new Error(`Error fetching user data: ${error.message}`);
  } finally {
    // Ensure connection is always closed
    if (connection) {
      await connection.closeAsync();
    }
  }
}

Example 4: Test Case Generation

Prompt:

Write unit tests for a function that validates a password
according to these rules:
- At least 8 characters long
- Contains at least one uppercase letter
- Contains at least one number
- Contains at least one special character (!@#$%^&*)
- Does not contain spaces

Use Jest for testing and include tests for both valid and invalid cases.

Result:

import { validatePassword } from './passwordValidator';

describe('Password Validator', () => {
  // Valid password tests
  test('should accept a valid password with all requirements', () => {
    expect(validatePassword('Passw0rd!')).toBe(true);
  });
  
  test('should accept a longer password that meets all criteria', () => {
    expect(validatePassword('SecureP@ssw0rd123')).toBe(true);
  });
  
  // Length tests
  test('should reject a password shorter than 8 characters', () => {
    expect(validatePassword('P@ss1')).toBe(false);
  });
  
  test('should accept a password exactly 8 characters', () => {
    expect(validatePassword('P@ssw0rd')).toBe(true);
  });
  
  // Character type tests
  test('should reject a password without uppercase letters', () => {
    expect(validatePassword('passw0rd!')).toBe(false);
  });
  
  test('should reject a password without numbers', () => {
    expect(validatePassword('Password!')).toBe(false);
  });
  
  test('should reject a password without special characters', () => {
    expect(validatePassword('Passw0rd')).toBe(false);
  });
  
  // Space test
  test('should reject a password containing spaces', () => {
    expect(validatePassword('Passw0rd !')).toBe(false);
  });
  
  // Edge cases
  test('should reject an empty password', () => {
    expect(validatePassword('')).toBe(false);
  });
  
  test('should reject null input', () => {
    expect(validatePassword(null)).toBe(false);
  });
  
  test('should reject undefined input', () => {
    expect(validatePassword(undefined)).toBe(false);
  });
  
  test('should reject non-string input', () => {
    expect(validatePassword(12345678)).toBe(false);
  });
});

Example 5: Technical Documentation

Prompt:

Generate comprehensive API documentation for a user management REST API
with endpoints for user creation, authentication, profile management,
and password reset. Include request/response formats, status codes,
authentication requirements, and examples using JSON.

Result:

# User Management API Documentation

## Base URL

https://api.example.com/v1


## Authentication
Most endpoints require a valid JWT token in the Authorization header:

Authorization: Bearer


## Endpoints

### 1. User Registration
Creates a new user account.

**URL**: `/users`  
**Method**: `POST`  
**Auth required**: No  

#### Request Body
```json
{
  "email": "[email protected]",
  "password": "SecureP@ss123",
  "firstName": "John",
  "lastName": "Doe"
}

Success Response

Code: 201 Created
Content:

{
  "id": "12345",
  "email": "[email protected]",
  "firstName": "John",
  "lastName": "Doe",
  "createdAt": "2025-03-20T15:30:00Z"
}

Error Responses

Code: 400 Bad Request
Condition: Invalid input
Content:

{
  "error": "Invalid input",
  "details": ["Email is not valid", "Password must be at least 8 characters"]
}

Code: 409 Conflict
Condition: Email already registered
Content:

{
  "error": "Email already registered"
}

2. User Authentication

...

[Documentation for other endpoints would continue here]


---

## Conclusion

### Key Takeaways

- **AI as a Development Partner**: Enhance productivity without replacing human expertise
- **Effective Prompting**: Be specific, structured, and provide context
- **Verify All Output**: Always review AI-generated code for correctness
- **Continuous Improvement**: Refine your prompting skills over time
- **Balanced Approach**: Use AI for appropriate tasks while maintaining critical thinking

---

### Next Steps

- **Experiment** with different AI tools and prompting techniques
- **Develop** team best practices for AI integration
- **Create** a prompt library for common development tasks
- **Share** successful AI implementations with the team
- **Evaluate** impact on development workflows and productivity

---

## Prompt Engineering Workshop

### Prompt Construction Exercise

Let's practice building effective prompts together:

---

### Example 1: Building a Data Validation Function

**Task**: Create a function to validate user input for a registration form

**Step 1: Start with basic request**

Write a function to validate form data


**Step 2: Add context and specifics**

Write a JavaScript function to validate user registration form data


**Step 3: Add technical details and constraints**

Write a JavaScript function that validates user registration form data with fields for email, password, name, and age. The function should return validation errors for each field.


**Step 4: Add requirements and edge cases**

Write a JavaScript function that validates user registration form data with these requirements:

  • Email: Must be valid format and from allowed domains (.com, .org, .edu)
  • Password: At least 8 chars with 1 uppercase, 1 number, 1 special char
  • Name: 2-50 chars, letters and spaces only
  • Age: Number between 18-120

Return an object with validation errors for each invalid field. Handle empty inputs appropriately.


**Step 5: Add format preferences and examples**

Write a modern JavaScript (ES6+) function that validates user registration form data with these requirements:

  • Email: Must be valid format and from allowed domains (.com, .org, .edu)
  • Password: At least 8 chars with 1 uppercase, 1 number, 1 special char
  • Name: 2-50 chars, letters and spaces only
  • Age: Number between 18-120

Return an object with validation errors for each invalid field. Handle empty inputs and edge cases appropriately.

Example usage: validateForm({ email: "[email protected]", password: "Pass123!", name: "John Doe", age: 25 }) // Should return { valid: true }

validateForm({ email: "invalid-email", password: "weak", name: "", age: 15 }) // Should return errors for each field


---

### Example 2: Building a Database Query Prompt

**Task**: Generate a SQL query for reporting

**Step 1: Basic request**

Write a SQL query to get sales data


**Step 2: Add database context**

Write a SQL query to get sales data from a database with tables for customers, orders, and products


**Step 3: Add specific requirements**

Write a SQL query that retrieves monthly sales totals by product category from a database with these tables:

  • customers (id, name, email, region)
  • orders (id, customer_id, order_date, total_amount)
  • order_items (order_id, product_id, quantity, price)
  • products (id, name, category_id, price)
  • categories (id, name)

**Step 4: Add constraints and formatting requirements**

Write a SQL query that retrieves monthly sales totals by product category for the year 2024. Use these tables:

  • customers (id, name, email, region)
  • orders (id, customer_id, order_date, total_amount)
  • order_items (order_id, product_id, quantity, price)
  • products (id, name, category_id, price)
  • categories (id, name)

Requirements:

  • Group by month and category name
  • Sort by month (ascending) and then by sales total (descending)
  • Include only completed orders (status = 'completed')
  • Format the date as 'Month Year' (e.g., 'January 2024')
  • Round sales totals to 2 decimal places

---

### Example 3: Building a React Component Prompt

**Task**: Create a table component for displaying data

**Step 1: Basic request**

Create a React component for a data table


**Step 2: Add component details**

Create a React component for a sortable and filterable data table


**Step 3: Add technical specifications**

Create a React functional component with TypeScript for a sortable and filterable data table. The table should display a list of products.


**Step 4: Add detailed requirements and props**

Create a React functional component with TypeScript for a sortable and filterable data table with the following features:

  • Display products with columns: name, category, price, and stock status
  • Allow sorting by clicking on column headers
  • Include a search box to filter products by name or category
  • Add pagination with configurable items per page
  • Highlight out-of-stock items in red

Props:

  • products: Array of product objects
  • initialSortColumn: String
  • initialSortDirection: 'asc' | 'desc'
  • itemsPerPage: Number

**Step 5: Add styling, accessibility and example data**

Create a React functional component with TypeScript for a sortable and filterable product data table with the following features:

  • Display products with columns: name, category, price, and stock status
  • Allow sorting by clicking on column headers (with sort indicators)
  • Include a search box to filter products by name or category
  • Add pagination with configurable items per page
  • Highlight out-of-stock items in red
  • Use CSS modules for styling
  • Ensure keyboard accessibility for sorting and pagination
  • Include proper ARIA attributes for screen readers

Props interface: interface ProductTableProps { products: Product[]; initialSortColumn?: string; initialSortDirection?: 'asc' | 'desc'; itemsPerPage?: number; onProductSelect?: (product: Product) => void; }

Example product data structure: interface Product { id: number; name: string; category: string; price: number; inStock: boolean; quantity: number; }


---

## Team Exercise: Prompt Building Challenge

### Instructions:

1. Form small groups of 2-3 people
2. Choose one of these development tasks:
   - Creating a date formatting utility
   - Building a password strength meter component
   - Writing unit tests for an authentication service
   - Creating an API error handling middleware

3. Follow these steps:
   - Start with a basic prompt
   - Add context and specific requirements
   - Add technical constraints and preferences
   - Include format requirements and examples
   - Test your prompt with an AI assistant

4. Share your prompts and results with the team
5. Discuss what worked well and how to improve

---

### Questions?

Thank you for your attention!
@BunHouth
Copy link
Author

Implement an website that allow users to test the speed typing.

  • Users login
  • Users Register
  • Sample data for typing can be 10 or more.
  • Track user typing record

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment