Defensive Programming Framework
The `defensive-programming-framework` is a TypeScript and JavaScript utility library designed to streamline and standardize input parameter validation, thereby fostering more robust code. Currently at version 1.0.4, it provides a collection of concise helper functions that abstract away common validation checks, reducing the boilerplate associated with manual `if (...) { throw new ArgumentError(...) }` statements. Its primary differentiator is the focus on either immediate termination via `ArgumentError` on failure (unconditional validation) or optional input correction, making validation logic more readable and maintainable. The framework aims to reduce the time and effort typically required for comprehensive input validation, encouraging developers to implement these crucial checks without inflating function bodies with repetitive error-checking code.
Common errors
-
ReferenceError: ArgumentError is not defined
cause The `ArgumentError` class was used without being imported from the package.fixAdd `import { ArgumentError } from 'defensive-programming-framework';` to your file. -
TypeError: cannotBeNull is not a function
cause A validation utility function (e.g., `cannotBeNull`, `mustBeEqualTo`) was called without being imported.fixEnsure you have `import { cannotBeNull } from 'defensive-programming-framework';` (or the specific function) at the top of your file. -
UnhandledPromiseRejectionWarning: ArgumentError: Value cannot be null.
cause An unconditional validation function threw an `ArgumentError` which was not caught, typically in an asynchronous context or at the top level of execution.fixWrap the code that calls the validation function in a `try...catch` block. For asynchronous operations, ensure the `catch` block is properly chained or awaited.
Warnings
- gotcha The framework's 'unconditional' validation functions (e.g., `cannotBeNull`, `mustBeEqualTo`) throw an `ArgumentError` on failure. This is an assertive pattern that halts execution, which might not be suitable for all validation contexts, especially those requiring soft failures or complex UI feedback.
- gotcha To specifically catch and handle errors thrown by the framework's validation, you must import and use `ArgumentError` with `instanceof`. Generic `catch (e)` blocks will not allow distinguishing framework errors from other exceptions.
- gotcha While the framework simplifies common checks, it does not inherently replace all custom validation logic. For complex, multi-variable conditions or custom error messages not covered by existing helpers, developers still need to implement explicit checks.
Install
-
npm install defensive-programming-framework -
yarn add defensive-programming-framework -
pnpm add defensive-programming-framework
Imports
- cannotBeNull
const cannotBeNull = require('defensive-programming-framework');import { cannotBeNull } from 'defensive-programming-framework'; - mustBeGreaterThanOrEqualTo
import mustBeGreaterThanOrEqualTo from 'defensive-programming-framework';
import { mustBeGreaterThanOrEqualTo } from 'defensive-programming-framework'; - whenIsNull
import { whenIsNull } from 'defensive-programming-framework'; - ArgumentError
new ArgumentError('message')import { ArgumentError } from 'defensive-programming-framework';
Quickstart
import {
cannotBeNull,
mustBeGreaterThanOrEqualTo,
whenIsNull,
whenIsLessThan,
ArgumentError
} from 'defensive-programming-framework';
/**
* Example function demonstrating defensive programming with the framework.
* Validates and potentially corrects input parameters.
*/
export function write(buffer: number[], startIndex: number, data: number[]): void {
// Unconditional validation - throws ArgumentError on failure
cannotBeNull(buffer); // Throws if buffer is null
cannotBeNull(data); // Throws if data is null
// Corrective validation - attempts to fix input, returns corrected value
// If startIndex is less than 0, it's corrected to 0.
startIndex = whenIsLessThan(startIndex, 0, 0);
// If data is null, it's corrected to an empty array.
data = whenIsNull(data, []);
// Mixed validation - ensuring corrected values meet further conditions
mustBeGreaterThanOrEqualTo(startIndex, 0); // Re-validate startIndex (now guaranteed >= 0 if corrected)
// Custom conditional check (can be wrapped in a framework function if frequently used)
if (data.length >= buffer.length - startIndex) {
throw new ArgumentError(`Length of data cannot be greater than remaining buffer space (${buffer.length - startIndex}).`);
}
console.log('Validation passed. Proceeding with actual write operation...');
// Actual execution code would go here
// For demonstration, let's just log the validated inputs
console.log('Buffer:', buffer);
console.log('StartIndex:', startIndex);
console.log('Data:', data);
}
// Example usage:
try {
console.log('\n--- Valid Case ---');
write([1, 2, 3, 4, 5], 1, [10, 20]); // Valid inputs
console.log('\n--- Corrective Case ---');
write([1, 2, 3, 4, 5], -5, null); // startIndex corrected to 0, data corrected to []
console.log('\n--- Error Case ---');
write([1, 2], 0, [10, 20, 30]); // Data length too large for buffer
} catch (e) {
if (e instanceof ArgumentError) {
console.error('Validation Error (caught):', e.message);
} else {
console.error('Unexpected Error (caught):', e);
}
}