逐步改进
-
从草稿开始
- 初始代码虽然功能正确,但存在重复逻辑、长函数、模糊的命名等问题。例如,
parseSchema和parseArguments函数冗长且职责混杂。 - 作者强调:“先让代码能工作,再让它变整洁”,但不要长期容忍糟糕的代码。
- 初始代码虽然功能正确,但存在重复逻辑、长函数、模糊的命名等问题。例如,
-
渐进式改进
- 通过小步重构(如提取方法、拆分逻辑、引入中间变量)逐步改善代码。例如:
- 将
parseSchema中的类型解析逻辑拆分为独立的parseSchemaElement函数。 - 用
ArgumentMarshaler接口统一参数处理逻辑,消除重复代码。
- 将
- 每次修改后运行测试,确保功能不被破坏。
- 通过小步重构(如提取方法、拆分逻辑、引入中间变量)逐步改善代码。例如:
-
关键重构技巧
- 单一职责原则:每个函数只做一件事。例如,将参数解析拆分为解析Schema、解析参数、设置参数值等独立步骤。
- 命名清晰化:将
d改为args,m改为marshalers,提升可读性。 - 消除重复:通过多态和策略模式(如
ArgumentMarshaler的子类)处理不同类型的参数。
-
最终成果
- 代码量减少,但逻辑更清晰。例如,
parse函数从50行缩减到10行,职责明确。 - 通过单元测试验证每一步重构的正确性。
- 代码量减少,但逻辑更清晰。例如,
前端开发的思考
-
小步重构
- 前端代码(如React组件)也常因需求迭代变得臃肿。可以逐步拆分逻辑到自定义Hook或工具函数中。例如:
// 重构前:混杂的逻辑 const Component = () => { const [data, setData] = useState([]); useEffect(() => { fetchData().then(res => { const filtered = res.filter(item => item.active); setData(filtered); }); }, []); // ...渲染逻辑 }; // 重构后:拆分职责 const useActiveData = () => { const [data, setData] = useState([]); useEffect(() => { fetchData().then(res => setData(res.filter(item => item.active))); }, []); return data; };
- 前端代码(如React组件)也常因需求迭代变得臃肿。可以逐步拆分逻辑到自定义Hook或工具函数中。例如:
-
命名即文档
- 避免缩写(如
btn),用handleClick代替onClk。例如:// 差 const fn = (d) => d.map(i => i * 2); // 好 const doubleNumbers = (numbers) => numbers.map(num => num * 2);
- 避免缩写(如
-
消灭重复逻辑
- 前端常见的重复可能是表单验证、API请求封装。可以抽象为共享函数或Hook:
// 封装fetch逻辑 const useApi = (endpoint) => { const [data, setData] = useState(null); useEffect(() => { fetch(endpoint).then(res => setData(res.json())); }, [endpoint]); return data; };
- 前端常见的重复可能是表单验证、API请求封装。可以抽象为共享函数或Hook:
-
测试护航
- 用Jest或Cypress保证重构安全性。例如:
test('useActiveData filters inactive items', () => { mockFetch([{active: true}, {active: false}]); const { result } = renderHook(() => useActiveData()); expect(result.current).toEqual([{active: true}]); });
- 用Jest或Cypress保证重构安全性。例如:
总结
整洁代码的核心是持续改进。无论是Java还是JavaScript,都要像作者一样:
- 敢于动手:不要畏惧重构“能跑但很丑”的代码。
- 保持节奏:每次提交只做一小步优化,并通过测试验证。
- 追求表达力:代码是写给人看的,命名和结构要像讲故事一样清晰。
“代码的阅读次数远多于编写次数,优化阅读体验就是节省团队时间。” —— 前端版“鲍勃大叔”