当前位置: 首页 > news >正文

为什么优秀程序员总在拆函数?因为代码应该表达意图,而不是实现

很多人认为函数的作用是复用代码或减少代码长度,但在《重构:改善既有代码的设计》中,Martin Fowler 提出了一个更重要的观点:函数的意义是表达意图,而不是实现。

当阅读代码时,如果需要花时间理解一段逻辑在做什么,就应该提炼函数,让调用层只表达业务意图,而实现细节隐藏在函数内部。

本文从“重复代码(Duplicated Code)”这一常见坏味道出发,总结三种常见的重构方式:提炼函数、移动语句、函数上移,并通过简单示例说明如何让代码从“读逻辑”变成“读意图”。


一、如何消除重复代码

1. 完全重复:提炼函数(Extract Function)

最简单的重复代码可以直接提炼函数

// badif(user.age>=18&&user.emailVerified&&!user.suspended){grantAccess(user)}
// goodif(canUserAccessSystem(user)){grantAccess(user)}const canUserAccessSystem=(user)=>user.age>=18&&user.emailVerified&&!user.suspended

函数命名表达意图,调用处只需要理解做什么


2. 相似但不相同:移动语句 → 再提炼

有些代码看起来类似,但顺序不同或夹杂其他逻辑。

处理方式:

  1. 移动语句
    将相关的数据和逻辑移动到一起。
  2. 重组结构
  3. 提炼函数

核心思想:

先让代码结构变得一致,再消除重复。


👍移动语句的目标是改善代码结构,将数据与相关逻辑聚集在一起

移动时需要注意:

  • 变量依赖顺序
  • 副作用顺序

3. 子类中的重复:函数上移(Pull Up Method)

当多个子类实现了相同的方法时,可以将方法提升到父类。

class Engineer extends Employee{intgetAnnualSalary(){returnmonthlySalary *12;}}class Manager extends Employee{intgetAnnualSalary(){returnmonthlySalary *12;}}

重构后:

class Employee{intgetAnnualSalary(){returnmonthlySalary *12;}}

父类更适合定义共同行为


很多人认为:

  • 函数是为了复用
  • 函数是为了缩短代码

其实都不是。

作者给了一个很实用的判断方式:

如果你需要花时间浏览一段代码才能弄清它在干什么。

就应该提炼函数。

当然,也可能是你还没读懂代码😁

换句话说:

读代码应该读意图,而不是读逻辑。


好的函数命名可以让代码变成一种“叙事结构”。

例如:

processOrder()validateOrder()calculatePrice()applyDiscount()sendEmail()

调用层只表达业务流程,实现细节隐藏在函数内部。

提炼函数最直接的收益是:

降低阅读成本


提炼函数通常可以按下面步骤进行:

  1. 根据代码意图命名函数
  2. 检查变量依赖
    外部变量通过参数传入
  3. 编译代码
  4. 用函数调用替换原代码
  5. 运行测试验证
  6. 查找其他重复代码并替换

如果一开始想不到好名字也没关系。

先提炼函数,在重构过程中名字往往会逐渐清晰。

如果最后发现不合适,可以再内联回去

这不是无用功。


1. 嵌套在源函数

在被提炼代码的源函数内部定义新函数,可以减少参数数量。

functionprocessOrder(order){functioncalculatePrice(){...}}

注意:

如果有需要,可以提炼到外部


2. 注意变量赋值

如果被提炼代码对变量进行了赋值:新函数应该返回新的值

如果需要返回多个变量:通常说明这段代码暂时不适合提炼函数


处理重复代码通常有三种方式:

场景重构方式
完全重复提炼函数
相似但顺序不同移动语句 → 再提炼
子类重复实现函数上移

而提炼函数最核心的原则只有一句话:

代码应该表达意图,而不是实现。👊


http://www.jsqmd.com/news/454343/

相关文章:

  • 2026交通执法5g执法记录仪选购推荐榜:高清执法记录仪、高清红外执法记录仪、4g执法记录仪、4g智能安全帽选择指南 - 优质品牌商家
  • 将 DeepSeek 模型接入 Claude Code
  • 2000-2024年上市公司资产专用性数据(三种测度)+Stata代码
  • Kubenets集群安装记录02
  • Nature 正刊:可个性化适配所有左心耳类型的磁流体机器人
  • Abaqus中利用USDFLD子程序在TIG焊接降温阶段改变材料参数及高斯热源DFlux联合仿...
  • OpenClaw + Claude Code 超强教程:一个人就能搭建完整的开发团队
  • 2026年打工人必备Skill!新手华为云上及本地部署OpenClaw(Clawdbot) 集成小红书保姆级步骤
  • Java 中线程之间如何进行通信?
  • 无界等待:系统故障的隐形杀手
  • 四参数随机生长法(QSGS算法)在随机孔隙结构与微观孔隙优化处理中的应用:多孔介质随机生长软件...
  • 小程序商城制作流程,专业商城系统开发 - 码云数智
  • 连接、控制与精进:深入探索 Psycopg2 的现代 PostgreSQL 开发实践
  • 英伟达受挫,TPU能否改写算力格局?
  • 美校申请不内耗!十大留学中介实力护航冲藤校 - 博客湾
  • 【声呐技术】窄带干扰抑制技术:一项综述
  • 穿越周期:国际物流新格局下的理性选择与价值发现 - 品牌评测官
  • AI驱动的数据分类分级实战:从入门到进阶的自动化识别指南
  • 2005-2024年全国城市域名备案数据库
  • 零基础实战:靶场商场网站漏洞利用与安全测试
  • 留学中介TOP10实测|文书全流程服务最能打? - 博客湾
  • 【阅读笔记】OpenClaw入门
  • 【飞机】基于matlab光流的着陆和悬停机动仿真【含Matlab源码 15124期】
  • 2026国际物流公司怎么选?干货解析+权威数据,避开陷阱不踩坑 - 品牌评测官
  • 全开源代码:BLDC PMSM FOC控制程序,有感无感驱动及滑膜霍尔编码器实现
  • COMSOL光学模型下的手性小球特性分析与模拟研究
  • 1975-2030年全球1km分辨率人口空间分布栅格数据
  • 北京留学机构TOP10优选!解锁名校申请捷径 - 博客湾
  • 【声呐技术】FS2-DETR:基于Transformer的增强特征感知小样本声呐目标检测
  • 2026年首个基于OpenClaw pi内核的商用桌面AI私域助理