代码重构:过长函数

举报
孙小北 发表于 2022/04/24 23:56:39 2022/04/24
【摘要】 代码重构:过长函数

什么是过长函数(Long Function)

  • 定义:一个函数包含了过多的逻辑功能或过分体现逻辑功能的实现细节,导致函数产生过长的代码块

  • 影响:过长的函数往往意味着函数功能不单一;或过分呈现细节未进行抽象。造成可读性差和增加代码维护成本;过长函数还容易发生资源未释放等编码问题

  • 改进目标:抽象待重构函数流程,分解出子函数,最大化精简出可读性强、功能单一的函数

  • 方法:提炼函数:找到函数中适合集中在一起的部分,将他们提炼出来形成一个新函数,并用函数“做什么”来命名新的函数

代码案例

  • 代码背景:一个打印发票的函数,发票的内容包含三块:

    • 打印发票头。发票头包含买方、卖方姓名;

    • 打印产品明细列表。每包含行产品号、名称、数量和价格信息;

    • 打印发票汇总。输出总金额。

  • 症状/问题:函数功能逻辑实现过于呈现细节,导致函数过长,理解难度大:

    • 函数较长且过分呈现实现细节,理解函数意图困难

    • 代码实现解耦性差,for循环复杂,包含两个功能

    • 代码实现语句理解难,if条件复杂,不能够快速理解条件含义

    • 临时变量过多,for循环中使用了过多的不必要临时变量

    • 类功能未内聚,属于Invoice和InvoiceLine的函数未内聚。例如计算总价不应属于打印器的能力

  • 重构目标:简化print函数实现流程,提高可读性

(1)理解长函数功能意图,归纳功能流程,提炼功能步骤

  • 理解函数意图

    • 寻找注释:注释间的代码块可能表明了代码可以分块提炼。同时注释通常能指出代码意图,帮助提炼函数的命名

    • 若无注释,阅读理解长函数实现功能,归纳长函数的执行步骤

  • 归纳功能流程

    • 将属于同一逻辑功能的代码通过移动语句聚合到一起 printHeader

      printDetail

      • printTableHeader

      • printInvoiceLines

      printFooter

  • 功能逻辑分割 可以看出printDetail步骤中夹杂了计算所有商品总价的功能,为帮助提炼函数,必须解耦函数算法的逻辑

  • for功能逻辑分割

  • for循环包含功能:

  • 打印发票正文的每行信息

  • 计算所有产品总价

  • 注:产品总价实际服务于最后的Total打印,分割出的for循环需要移动语句到对应位置

  • 提炼函数抽象主函数流程

  • 注:以“做什么”命名提炼的函数,而不是“怎么做”

(2)复杂语句下沉到子函数,对复杂子函数递归重构–printDetail函数

  • 子函数进行流程分析和提炼

  • 临时变量过多:以查询取代变量

  • 功能内聚到合适的位置,并以查询取代变量

  • 分解条件语句:复杂的条件表达式

  • 分解条件语句:复杂的条件分支语句:如果条件分支语也有过长语句的坏味道,可继续进行递归重构。

  • 注:对于双分支的条件语句可使用三目运算符exp1?exp2:exp3精简


代码案例2

  • 代码背景:这是一个保存数据的方法,根据用户指定的保存方式和保存目的地址进行文件的上传或保存。保存方式包括:本地保存、SFTP上传、EMAIL发送、华为云、百度云方式

  • 症状/问题:函数功能不单一且实现过于呈现细节,导致函数过长且需翻页阅读

    • 过于呈现实现细节,导致功能不单一:包含分类工作和具体的保存/上传操作

    • 函数太长,导致显示屏不能一屏显示,造成阅读和理解的困难

    • 后续的维护将使该函数不断增大,例如增加保存/上传类型

  • 重构目标:简少save函数代码行,方便用户一页显示,提高可读性

  • Switch分支语句的提炼&重构前后对比

重复的Switch语句:特别地,如果统一Switch分支条件模式出现了多次,可使用多态取代重复的switch进行重构。

重构对比

重构前

  • Print打印函数功能复杂、函数过长、代码理解难度高

  • InvoicePrinter类功能不单一,print函数内部做了非本类的职责

重构后

  • 各函数短小精悍,能快速定位到子功能函数进行维护修改

  • 函数职责单一,

  • 相对来说函数功能清晰,极易理解代码逻辑和流程

相关技巧

识别工具:华为通用编码规范

规范从表象上要求对于一般超过50行的函数需要优先进行过长函数的重构,可通过IDE端侧CodeCheck进行识别超过50行的函数: 选中目录或文件-> 右击-> Code Check -> Full Check -> 等待结果

注:不仅仅超过50行的才需要过长函数的重构,仅仅是优先项,只要函数过于呈现业务细节,影响了可读性和可维护性,就应该通过过长函数的重构手法进行重构

总结

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。