手动检查测试函数参数的最佳实践?TDD下参数检查代码臃肿疑问
关于TDD模式下参数校验代码的规范与优化方案
你的TDD实践完全符合规范——先写测试用例覆盖各类边界场景,再实现参数校验逻辑拦截错误,这种方式能有效保障代码健壮性,测试用例的覆盖度也做得很到位。但确实,重复的校验代码会让类的核心逻辑显得臃肿,下面给你几个可行的优化方向:
一、提取通用校验工具函数
把重复的校验逻辑(比如检查是否为整数、是否是单个参数、数值范围校验)抽成独立的工具函数,既能复用代码,也能让类的核心逻辑更清晰。
示例代码:
// 校验工具函数 const validateSingleNumberArg = (arg, name) => { if (typeof arg !== 'number') throw new Error(`${name} must be a number`); if (!Number.isInteger(arg)) throw new Error(`${name} must be an integer`); }; const validatePositiveInteger = (num, name) => { validateSingleNumberArg(num, name); if (num < 1) throw new Error(`${name} must be greater than 0`); }; const validateWithinRange = (num, min, max, name) => { validateSingleNumberArg(num, name); if (num < min || num > max) throw new Error(`${name} must be between ${min} and ${max}`); }; // 优化后的Ship类 export default class Ship { constructor(shipLength, ...rest) { if (rest.length > 0) throw new Error('Must enter only 1 argument'); validatePositiveInteger(shipLength, 'Length'); this.length = shipLength; this.hits = Array(this.length).fill(false); } hit(location, ...rest) { if (rest.length > 0) throw new Error('Can only accept one argument'); validateWithinRange(location, 0, this.length - 1, 'Location'); this.hits[location] = true; } }
二、使用静态类型检查(推荐)
如果项目可以引入TypeScript,或者用JSDoc配合编辑器的类型检查,能在编译/开发阶段就拦截大部分类型错误,减少运行时的校验代码。
TypeScript版本示例:
export default class Ship { public length: number; public hits: boolean[]; constructor(shipLength: number) { // 仅保留无法通过静态类型检查覆盖的校验(比如数值范围、整数判断) if (!Number.isInteger(shipLength) || shipLength < 1) { throw new Error('Length must be a positive integer'); } this.length = shipLength; this.hits = Array(this.length).fill(false); } hit(location: number): void { if (!Number.isInteger(location) || location < 0 || location >= this.length) { throw new Error('Location must be a non-negative integer within ship body'); } this.hits[location] = true; } }
TypeScript会在开发阶段就阻止你传入非number类型的参数,也会限制参数数量,这样运行时的校验代码就能大幅减少。
三、环境区分校验(可选)
如果这个类是项目内部使用的工具类,而非对外暴露的API,可以考虑只在开发环境保留校验代码,生产环境移除,减少性能开销:
constructor(shipLength, ...rest) { if (process.env.NODE_ENV === 'development') { if (rest.length > 0) throw new Error('Must enter only 1 argument'); if (typeof shipLength !== 'number') throw new Error('Length must be a number'); if (shipLength < 1) throw new Error('Length must be greater than 0'); if (!Number.isInteger(shipLength)) throw new Error('Length must be an integer'); } this.length = shipLength; this.hits = Array(this.length).fill(false); }
总结:你的原始实现是规范的,但通过提取工具函数、引入静态类型检查等方式,可以有效减少代码冗余,同时不丢失校验能力。
内容的提问来源于stack exchange,提问作者Khaled
相关产品推荐
相关产品推荐

