Defensive Programming

Write defensive code to prevent errors

JavaScriptIntermediate
JavaScript
// Method 1: Input validation
function processUserInput(input) {
    if (typeof input !== 'string') {
        throw new TypeError('Input must be a string');
    }
    
    if (input.length === 0) {
        throw new Error('Input cannot be empty');
    }
    
    if (input.length > 100) {
        throw new Error('Input too long');
    }
    
    return input.trim();
}

// Method 2: Null/undefined checks
function safeAccess(obj, path) {
    const keys = path.split('.');
    let current = obj;
    
    for (const key of keys) {
        if (current == null) {
            return null;
        }
        current = current[key];
    }
    
    return current;
}

const user = { profile: { name: 'John' } };
console.log('Name:', safeAccess(user, 'profile.name'));
console.log('Missing:', safeAccess(user, 'profile.email'));

// Method 3: Default values
function getValue(value, defaultValue) {
    return value != null ? value : defaultValue;
}

function processConfig(config) {
    return {
        timeout: getValue(config.timeout, 5000),
        retries: getValue(config.retries, 3),
        url: getValue(config.url, 'https://api.example.com')
    };
}

// Method 4: Type checking
function validateType(value, expectedType) {
    const actualType = typeof value;
    if (actualType !== expectedType) {
        throw new TypeError(`Expected ${expectedType}, got ${actualType}`);
    }
    return value;
}

// Method 5: Range validation
function validateRange(value, min, max) {
    if (value < min || value > max) {
        throw new RangeError(`Value must be between ${min} and ${max}`);
    }
    return value;
}

// Method 6: Safe array operations
function safeArrayOperation(array, index, operation) {
    if (!Array.isArray(array)) {
        throw new TypeError('First argument must be an array');
    }
    
    if (index < 0 || index >= array.length) {
        return null;
    }
    
    return operation(array[index]);
}

// Method 7: Error boundaries
function withErrorBoundary(fn, fallback) {
    try {
        return fn();
    } catch (error) {
        console.error('Error in function:', error);
        return fallback();
    }
}

const result = withErrorBoundary(
    () => riskyOperation(),
    () => 'Default value'
);

Output

Name: John
Missing: null

Defensive programming prevents errors.

Input Validation

  • Check types
  • Validate ranges
  • Check required fields
  • Sanitize input

Null Checks

  • Check for null/undefined
  • Safe property access
  • Optional chaining
  • Default values

Type Checking

  • Validate types
  • Throw early
  • Clear error messages
  • Type guards

Range Validation

  • Min/max values
  • Array bounds
  • String length
  • Numeric ranges

Safe Operations

  • Array bounds
  • Object properties
  • Function calls
  • Error boundaries

Best Practices

  • Validate early
  • Fail fast
  • Provide defaults
  • Handle edge cases