Back to list
onshoreoutsourcing

development-best-practices

by onshoreoutsourcing

AI-powered desktop development environment with conversational file operations

0🍴 0📅 Jan 20, 2026

SKILL.md


name: development-best-practices description: Core development principles including anti-hallucination, anti-hardcoding, error handling, logging, testing, and security standards. Use during feature design, implementation, and code review to ensure code quality and maintainability. Applies universally to all code regardless of technology or feature.

Development Best Practices

Universal coding standards and anti-patterns that apply to ALL code regardless of feature or technology.

Quick Start

Validate feature design:

"Check feature-5.1 design against development-best-practices"

Validate implementation:

"Verify src/services/ follows development-best-practices"

Check code before commit:

"Review my changes against development-best-practices before committing"

Core Workflow

Step 1: Anti-Hallucination Validation

Purpose: Prevent AI agents from inventing code, APIs, or file structures that don't exist

Validation Checks:

  1. File Existence Before Reading

    # ❌ BAD: Assume file exists
    with open('config.yaml') as f:
        config = yaml.load(f)
    
    # ✅ GOOD: Check existence first
    if os.path.exists('config.yaml'):
        with open('config.yaml') as f:
            config = yaml.load(f)
    else:
        raise FileNotFoundError("config.yaml not found")
    
  2. API Response Validation

    // ❌ BAD: Assume response structure
    const user = await api.getUser(userId);
    console.log(user.email);
    
    // ✅ GOOD: Validate response structure
    const user = await api.getUser(userId);
    if (!user || !user.email) {
        throw new Error("Invalid user response");
    }
    console.log(user.email);
    
  3. Test Assumptions with Actual Data

    // ❌ BAD: Assume API returns array
    const items = await api.getItems();
    items.forEach(item => console.log(item));
    
    // ✅ GOOD: Verify it's an array
    const items = await api.getItems();
    if (!Array.isArray(items)) {
        throw new Error("Expected array, got " + typeof items);
    }
    items.forEach(item => console.log(item));
    
  4. Read Actual Code, Don't Invent Signatures

    // ❌ BAD: Guess function signature
    // Assume: calculateTotal(items, tax, discount)
    const total = calculateTotal(cartItems, 0.08, 10);
    
    // ✅ GOOD: Read actual function signature first
    // After reading code: calculateTotal(items: Item[]): number
    // Tax/discount handled internally via config
    const total = calculateTotal(cartItems);
    
  5. Validate Configuration Values Exist

    // ❌ BAD: Assume env var exists
    const apiUrl = process.env.API_URL;
    fetch(apiUrl + '/users');
    
    // ✅ GOOD: Validate env var exists
    const apiUrl = process.env.API_URL;
    if (!apiUrl) {
        throw new Error("API_URL environment variable not set");
    }
    fetch(apiUrl + '/users');
    

Checklist:

  • Verified file existence before reading/writing
  • Validated API response structure before accessing
  • Tested assumptions with console.log or debugger
  • Read actual function signatures from source code
  • Checked configuration values exist before using
  • No invented APIs, methods, or properties

Step 2: Anti-Hardcoding Validation

Purpose: Ensure all environment-specific values are externalized

Validation Checks:

  1. No Hardcoded URLs

    // ❌ BAD: Hardcoded URL
    const API_URL = 'https://api.prod.company.com';
    
    // ✅ GOOD: Environment variable
    const API_URL = process.env.API_URL || 'http://localhost:3000';
    
  2. No Hardcoded Credentials

    // ❌ BAD: Hardcoded API key
    const apiKey = 'sk_live_abc123xyz789';
    
    // ✅ GOOD: Environment variable
    const apiKey = process.env.API_KEY;
    if (!apiKey) throw new Error("API_KEY not configured");
    
  3. Extract Magic Numbers to Constants

    // ❌ BAD: Magic numbers
    if (user.age >= 18 && cartTotal > 100) {
        applyDiscount(cartTotal * 0.1);
    }
    
    // ✅ GOOD: Named constants
    const MINIMUM_AGE = 18;
    const DISCOUNT_THRESHOLD = 100;
    const DISCOUNT_RATE = 0.1;
    
    if (user.age >= MINIMUM_AGE && cartTotal > DISCOUNT_THRESHOLD) {
        applyDiscount(cartTotal * DISCOUNT_RATE);
    }
    
  4. Use Feature Flags for Toggles

    // ❌ BAD: Hardcoded feature toggle
    const enableNewCheckout = true;
    
    // ✅ GOOD: Configuration-based feature flag
    const enableNewCheckout = config.get('features.newCheckout', false);
    
  5. No Environment-Specific Logic in Code

    // ❌ BAD: Environment checks in code
    if (process.env.NODE_ENV === 'production') {
        // Use production logic
    } else {
        // Use dev logic
    }
    
    // ✅ GOOD: Configuration-driven
    const useCache = config.get('cache.enabled');
    if (useCache) {
        // Use cache
    }
    

Checklist:

  • No hardcoded URLs, endpoints, or service addresses
  • No hardcoded API keys, tokens, or credentials
  • No magic numbers (extracted to named constants)
  • No hardcoded database connection strings
  • No environment-specific logic in code (use config)
  • Feature flags in configuration, not code

Step 3: Error Handling Validation

Purpose: Ensure all risky operations have proper error handling

Validation Checks:

  1. Wrap Risky Operations in Try-Catch

    // ❌ BAD: No error handling
    const data = JSON.parse(jsonString);
    const result = await api.fetchData();
    
    // ✅ GOOD: Try-catch around risky operations
    let data;
    try {
        data = JSON.parse(jsonString);
    } catch (error) {
        console.error("Failed to parse JSON", error);
        throw new Error("Invalid JSON format");
    }
    
    let result;
    try {
        result = await api.fetchData();
    } catch (error) {
        console.error("API call failed", error);
        throw new Error("Failed to fetch data from API");
    }
    
  2. Propagate Errors Correctly

    // ❌ BAD: Swallow errors
    async function loadUser(userId: string) {
        try {
            return await api.getUser(userId);
        } catch (error) {
            console.error(error);
            return null; // Error swallowed
        }
    }
    
    // ✅ GOOD: Re-throw or return error
    async function loadUser(userId: string): Promise<User> {
        try {
            return await api.getUser(userId);
        } catch (error) {
            console.error("Failed to load user", userId, error);
            throw new Error(`User ${userId} not found`);
        }
    }
    
  3. User-Friendly Error Messages

    // ❌ BAD: Technical error to user
    catch (error) {
        alert(error.stack);
    }
    
    // ✅ GOOD: User-friendly message
    catch (error) {
        console.error("Technical error:", error);
        showNotification("Unable to load data. Please try again later.", "error");
    }
    
  4. Log Errors Appropriately

    // ❌ BAD: No logging
    catch (error) {
        throw error;
    }
    
    // ✅ GOOD: Log before re-throwing
    catch (error) {
        logger.error("Failed to process payment", {
            userId: user.id,
            amount: amount,
            error: error.message,
            stack: error.stack
        });
        throw new Error("Payment processing failed");
    }
    
  5. Cleanup with Finally Blocks

    // ❌ BAD: Resources not cleaned up
    const connection = await db.connect();
    await connection.query(sql);
    await connection.close();
    
    // ✅ GOOD: Finally block ensures cleanup
    const connection = await db.connect();
    try {
        await connection.query(sql);
    } finally {
        await connection.close();
    }
    

Checklist:

  • All risky operations wrapped in try-catch
  • Errors logged with context (user ID, action, etc.)
  • Errors propagated or handled appropriately (not swallowed)
  • User-friendly error messages (no stack traces to users)
  • Cleanup code in finally blocks (close connections, files)
  • Specific error types thrown (not generic Error)

Step 4: Logging Validation

Purpose: Ensure consistent, structured logging throughout application

Validation Checks:

  1. Use Structured Logging (JSON Format)

    // ❌ BAD: String concatenation
    console.log("User " + userId + " logged in at " + new Date());
    
    // ✅ GOOD: Structured logging
    logger.info("User logged in", {
        userId: userId,
        timestamp: new Date().toISOString(),
        ipAddress: req.ip
    });
    
  2. No Sensitive Data in Logs

    // ❌ BAD: Logging sensitive data
    logger.info("User authenticated", {
        userId: user.id,
        password: user.password,  // 🚨 Never log passwords
        ssn: user.ssn             // 🚨 Never log PII
    });
    
    // ✅ GOOD: Redact sensitive data
    logger.info("User authenticated", {
        userId: user.id,
        email: maskEmail(user.email)  // user@example.com → u***@example.com
    });
    
  3. Appropriate Log Levels

    // ❌ BAD: Everything at INFO level
    logger.info("Starting application");
    logger.info("User not found");  // Should be WARN
    logger.info("Database connection failed");  // Should be ERROR
    logger.info("Query took 5ms");  // Should be DEBUG
    
    // ✅ GOOD: Proper log levels
    logger.info("Starting application");
    logger.warn("User not found", { userId });
    logger.error("Database connection failed", { error });
    logger.debug("Query executed", { duration: 5, query });
    
  4. Correlation IDs for Tracing

    // ❌ BAD: No request correlation
    logger.info("Processing payment");
    logger.info("Payment successful");
    
    // ✅ GOOD: Include correlation ID
    const correlationId = req.headers['x-correlation-id'] || uuidv4();
    logger.info("Processing payment", { correlationId, userId, amount });
    logger.info("Payment successful", { correlationId, transactionId });
    
  5. Performance Logging for Slow Operations

    // ❌ BAD: No performance tracking
    const result = await expensiveOperation();
    
    // ✅ GOOD: Log slow operations
    const start = Date.now();
    const result = await expensiveOperation();
    const duration = Date.now() - start;
    
    if (duration > 1000) {
        logger.warn("Slow operation detected", {
            operation: "expensiveOperation",
            duration,
            threshold: 1000
        });
    }
    

Checklist:

  • Structured logging (JSON format, not string concat)
  • No sensitive data in logs (passwords, tokens, PII)
  • Appropriate log levels (ERROR, WARN, INFO, DEBUG)
  • Correlation IDs included for request tracing
  • Performance logging for operations >1s
  • Contextual information (user ID, action, resource)

Step 5: Testing Validation

Purpose: Ensure adequate test coverage and quality

Validation Checks:

  1. Unit Tests for Business Logic

    // ❌ BAD: No tests
    export function calculateDiscount(price: number, discountPercent: number) {
        return price * (discountPercent / 100);
    }
    
    // ✅ GOOD: Unit tests cover logic
    describe('calculateDiscount', () => {
        it('should calculate 10% discount correctly', () => {
            expect(calculateDiscount(100, 10)).toBe(10);
        });
    
        it('should handle 0% discount', () => {
            expect(calculateDiscount(100, 0)).toBe(0);
        });
    
        it('should handle 100% discount', () => {
            expect(calculateDiscount(100, 100)).toBe(100);
        });
    });
    
  2. Integration Tests for Service Interactions

    // ❌ BAD: Only unit tests, no integration tests
    
    // ✅ GOOD: Integration test for API interaction
    describe('UserService', () => {
        it('should fetch user from API', async () => {
            const userService = new UserService(mockApiClient);
            const user = await userService.getUser('user123');
    
            expect(user).toBeDefined();
            expect(user.id).toBe('user123');
            expect(mockApiClient.get).toHaveBeenCalledWith('/users/user123');
        });
    });
    
  3. Test Coverage Meets Threshold (>80%)

    # Run test coverage
    npm run test:coverage
    
    # Ensure meets threshold
    # Lines: 85% (target: 80%)
    # Branches: 82% (target: 80%)
    # Functions: 90% (target: 80%)
    
  4. Edge Cases Covered

    // ❌ BAD: Only happy path tested
    it('should process valid input', () => {
        expect(processInput('valid')).toBe('processed');
    });
    
    // ✅ GOOD: Edge cases tested
    describe('processInput', () => {
        it('should process valid input', () => {
            expect(processInput('valid')).toBe('processed');
        });
    
        it('should handle empty string', () => {
            expect(() => processInput('')).toThrow('Input cannot be empty');
        });
    
        it('should handle null', () => {
            expect(() => processInput(null)).toThrow('Input cannot be null');
        });
    
        it('should handle very long input', () => {
            const longInput = 'a'.repeat(10000);
            expect(() => processInput(longInput)).toThrow('Input too long');
        });
    });
    
  5. Mocking Used Appropriately

    // ❌ BAD: Real API calls in tests
    it('should create user', async () => {
        const result = await realApi.createUser(userData);  // 🚨 Real API call
        expect(result.success).toBe(true);
    });
    
    // ✅ GOOD: Mock API calls
    it('should create user', async () => {
        const mockApi = {
            createUser: jest.fn().mockResolvedValue({ success: true, id: '123' })
        };
        const service = new UserService(mockApi);
        const result = await service.createUser(userData);
    
        expect(result.success).toBe(true);
        expect(mockApi.createUser).toHaveBeenCalledWith(userData);
    });
    

Checklist:

  • Unit tests for all business logic functions
  • Integration tests for service interactions
  • Test coverage >80% (lines, branches, functions)
  • Edge cases covered (null, empty, invalid, boundary)
  • Mocking used for external dependencies
  • Tests run in CI/CD pipeline

Step 6: Security Validation

Purpose: Ensure security best practices followed

Validation Checks:

  1. Input Validation on All User Inputs

    // ❌ BAD: No input validation
    app.post('/users', async (req, res) => {
        const user = await db.createUser(req.body);
        res.json(user);
    });
    
    // ✅ GOOD: Validate input
    app.post('/users', async (req, res) => {
        const schema = z.object({
            email: z.string().email(),
            age: z.number().min(0).max(150),
            name: z.string().min(1).max(100)
        });
    
        const validated = schema.parse(req.body);
        const user = await db.createUser(validated);
        res.json(user);
    });
    
  2. Authentication Checks on Protected Operations

    // ❌ BAD: No auth check
    app.get('/admin/users', async (req, res) => {
        const users = await db.getAllUsers();
        res.json(users);
    });
    
    // ✅ GOOD: Require authentication
    app.get('/admin/users', requireAuth, async (req, res) => {
        const users = await db.getAllUsers();
        res.json(users);
    });
    
  3. Authorization/RBAC Enforced

    // ❌ BAD: No permission check
    app.delete('/users/:id', requireAuth, async (req, res) => {
        await db.deleteUser(req.params.id);
        res.json({ success: true });
    });
    
    // ✅ GOOD: Check permissions
    app.delete('/users/:id', requireAuth, requireRole('admin'), async (req, res) => {
        await db.deleteUser(req.params.id);
        res.json({ success: true });
    });
    
  4. SQL Injection Prevention (Parameterized Queries)

    // ❌ BAD: String concatenation (SQL injection)
    const query = `SELECT * FROM users WHERE email = '${email}'`;
    const users = await db.query(query);
    
    // ✅ GOOD: Parameterized query
    const query = `SELECT * FROM users WHERE email = ?`;
    const users = await db.query(query, [email]);
    
  5. XSS Prevention (Output Encoding)

    // ❌ BAD: Unescaped user input
    res.send(`<h1>Welcome ${req.query.name}</h1>`);
    
    // ✅ GOOD: Escape user input
    const escape = require('escape-html');
    res.send(`<h1>Welcome ${escape(req.query.name)}</h1>`);
    

Checklist:

  • Input validation on all user inputs (schema validation)
  • Authentication required for protected endpoints
  • Authorization/RBAC checks enforced
  • Parameterized queries (no SQL injection)
  • Output encoding (no XSS vulnerabilities)
  • HTTPS enforced (no sensitive data over HTTP)
  • CSRF protection enabled
  • Rate limiting on public endpoints

Available Resources

Scripts

  • scripts/validate_no_hardcoded_values.py — Scan for hardcoded URLs, keys, magic numbers

    python scripts/validate_no_hardcoded_values.py --path src/ --report hardcoding-report.json
    
  • scripts/check_error_handling.py — Verify try-catch coverage for risky operations

    python scripts/check_error_handling.py --path src/ --threshold 90
    
  • scripts/verify_configuration.py — Ensure all config externalized

    python scripts/verify_configuration.py --path src/ --config-file .env.example
    
  • scripts/check_logging_practices.py — Validate logging standards

    python scripts/check_logging_practices.py --path src/ --check-sensitive-data
    
  • scripts/calculate_test_coverage.py — Check test coverage meets threshold

    python scripts/calculate_test_coverage.py --threshold 80 --report coverage-report.json
    

References

  • references/anti-hallucination-checklist.md — Specific checks to prevent AI hallucination
  • references/configuration-patterns.md — How to externalize configuration properly
  • references/error-handling-patterns.md — Standard error handling approaches
  • references/logging-standards.md — Structured logging formats and standards
  • references/testing-requirements.md — Unit/integration test requirements
  • references/security-checklist.md — Security validation checklist

Integration with Workflow

During Feature Design (/design-features)

Before designing features:

  • Review anti-hallucination checklist
  • Plan configuration externalization
  • Design error handling strategy
  • Plan logging approach
  • Define test strategy
  • Identify security requirements

During Wave Design (/design-waves)

Before designing waves:

  • Validate wave follows best practices
  • Check for hardcoding opportunities
  • Plan error handling for wave
  • Define tests needed for wave

During Implementation (/implement-waves)

Before implementing:

  • Invoke development-best-practices skill
  • Review relevant checklist sections
  • Run validation scripts during implementation
  • Test against best practices before commit

During Code Review

Before merging:

  • Run all validation scripts
  • Review against best practices checklist
  • Verify test coverage meets threshold
  • Check security checklist

Success Criteria

  • ✅ No hallucinated code (all APIs/files verified to exist)
  • ✅ No hardcoded values (URLs, credentials, magic numbers)
  • ✅ All risky operations have error handling
  • ✅ Structured logging with appropriate levels
  • ✅ Test coverage >80%
  • ✅ Security checklist items addressed

Tips for Effective Practice

  1. Invoke early and often - Use skill before design, during implementation, before commit
  2. Run validation scripts - Catch violations automatically
  3. Review checklists - Systematic approach beats ad-hoc checks
  4. Learn from violations - Understand why rules exist
  5. Automate enforcement - Use pre-commit hooks, CI/CD checks
  6. Update skill - Add patterns as you discover them
  7. Share violations - Help team learn from mistakes

Last Updated: 2025-01-30

Score

Total Score

50/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

0/10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

Reviews

💬

Reviews coming soon