代码之丑
郑晔
开源项目 Moco 作者
19833 人已学习
新⼈⾸单¥59
登录后,你可以任选2讲全文学习
课程目录
已完结/共 24 讲
代码之丑
15
15
1.0x
00:00/00:00
登录|注册

04 | 长函数:为什么你总是不可避免地写出长函数?

你好,我是郑晔。
这一讲,我们来讲一个你一定深恶痛绝的坏味道:长函数。
有一个关于程序员的段子,说程序员一定要用大屏显示器,而且一定要竖起来用,这样才能看到一个函数的全貌。这显然是在调侃函数很长,小屏甚至横屏都不足以看到整个函数,只有竖起来才行。
只要一提到长函数,无论是去被迫理解一个长函数的含义,还是要在一个长函数中,小心翼翼地找出需要的逻辑,按照需求微调一下,几乎所有程序员都会有不愉悦的回忆。可以这么说,没有人喜欢长函数,但在实际工作中,却不得不去与各种长函数打交道。
不知道你在实际工作中遇到最长的函数有多长,几百上千行的函数肯定是不足以称霸的。在我的职业生涯中,经常是我以为自己够见多识广了,但只要新接触到一个有悠久历史的代码库,就总会有突破认知的长函数出现。
长函数是一个“我一说,你就知道怎么回事”的坏味道,我就不准备用一个典型的长函数来开启这一讲了,否则,这一讲的篇幅都不够了。但是,为了统一认识,我准备先讨论一下多长的函数算是长函数,我们来看一个案例。

多长的函数才算“长”?

有一次,我在一个团队做分享,讲怎么把一个长函数重构成小函数。现场演示之后,我问了大家一个问题:在你心目中,多长的函数才算长呢?
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

长函数在软件开发中是一个常见的问题,本文深入探讨了长函数产生的原因以及解决方案。作者指出,长函数的产生主要源于性能优化、平铺直叙和逐步累积修改等原因。然而,性能优化不应是代码编写的首要考虑因素,而应优先考虑可维护性。平铺直叙的代码容易导致将多个业务处理流程和不同层面的细节混合在一个函数中,降低代码的可读性和可维护性。逐步累积修改也会导致代码变得冗长且难以维护。为解决长函数问题,作者提出了拆分函数的解决方案,通过提取函数将长函数拆分成多个小函数,从而提高代码的可读性和可维护性。总的来说,本文通过深入分析长函数产生的原因和解决方案,为读者提供了思考和解决长函数问题的方法。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《代码之丑》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(42)

  • 最新
  • 精选
  • 我写过最长的类,写了4000行,还是我抽出去了几百行if代码。没错,就是我亲手写出来的

    作者回复: 你这算是勇于自我否定吗?😁

    2021-01-10
    13
  • Jxin
    举个场景: 创建商品聚合实体的场景: 1.查找商品,校验商品是否存在。 2.查找店铺, 校验店铺是否存在,获取店铺code。 3.用商品和店铺查找合作关系。 4.用合作关协查找合同,验证合同合法。 以上只是举例,实际场景可能还会有5,6,7,8,9。而这个场景的特点: 每个环节的执行依赖上个环节的回参作为输入,以至于只能平铺(哪怕每个环节都提炼成1行函数调用)而没办法拆分开去封装。而一旦平铺,行数超过10-20就很容易。 像这种场景,郑老师怎么看。可以进一步拆分的话该如何拆?

    作者回复: 拆分是没有问题的,但拆分出来的每一个步骤,都应该是一个独立的函数,然后,在大的函数中将它们聚合起来。

    2021-01-07
    2
    12
  • Geek_45023b
    我见过10万行的类,上万行的长函数。这些都是在工业软件中,由非计算机专业的人开发的代码

    作者回复: 代码行书没有上限,写的人就没有底线。

    2021-01-10
    2
    10
  • 桃子-夏勇杰
    郑老师,把一个开发人员从习惯写长函数培养到会写短函数大概需要多少时间和成本?

    作者回复: 看要求了,我在代码检查里加限制,新来的同学立刻就能学会。

    2021-01-08
    9
  • dev.bin
    前人留下的一个类6000多行代码,函数没有几个,想改却改不动,改完后,别人提交之后就产生冲突,解决冲突后,别人又提交,又冲突。只改一点点,CI过不了,一周下来,没啥产出。

    作者回复: 小步修改,小步提交。

    2021-01-08
    8
  • huaweichen
    "因为变量都是在这个短小的上下文里,也就不会产生那么多的命名冲突,变量名当然就可以写短一些。" 这句话真的很有启发。 之前还和同事在争论,变量名太长的问题。他们说“we love long variable names, because it is very self-explanatory” 。 我现在可以跟他们说问题在与函数写得太长。

    作者回复: 是的,变量名字长可能就是函数长的结果。

    2021-01-07
    2
    7
  • 斯盖丸
    请问一下老师,遇到JDBC读取resultset或者set一个prepared statement而列又很多时应该怎么简化?往往轻轻松松就几时行了…有什么精简优雅的缩短方法吗?

    作者回复: 难道不是用框架吗?这年头为啥要用裸的JDBC呢?

    2021-01-19
    2
    6
  • adang
    在代码库里看到很多这样平铺直叙的代码,类似这样。 ``` if 旧账号存在 删除旧账号的所有权限 if 删除成功 将新管理员身份设置为管理员 将旧管理身份设置为普通员工 if 设置成功 为新管理员添加管理员权限 if 权限设置成功 修改企业账号为新管理员账号 if 修改成功 修改 redis 缓存 ``` 这个方法的逻辑是,转移管理员账号给一个新的管理员,这个方法大约80行的样子。 分析了一下,大家这样写的原因, 1.成员都是自己野蛮生长起来的,没有见过好的范例; 2.团队里没有成型的规范,即使有也没有人坚持,代码随便写,只要功能实现了就行。 像上面这样只要把各种情况顺序写进去就行了,比较简单,不用考虑太多。可这样带来的问题就是,后面维护起来就要花很大精力把逻辑搞清楚才能下手去修改。另外,像上面那样,如果中间某一步执行失败,整个方法就失败,但是前面几步的操作却不能回滚。 对这段代码的优化,可以抽取出几个小方法,如:修改新旧管理员身份,删除旧账号权限,为新管理员赋值权限,修改企业账号,修改缓存等,使代码更容易阅读。另外,可以借鉴Rails中ActiveRecord::Callbacks的封装方式使代码看上去更简洁。 上面方法是Java的一段代码,对Java不是很熟,不知道Java相关的框架中是否有类似于Rails的Callbacks封装。

    作者回复: 你的分析思路是对的,把一步一步拆分开来。 Java有各种 AOP,有兴趣可以看一下。

    2021-01-10
    3
    6
  • 首长
    为啥是“关注点越多越好”?

    作者回复: 对于大多数人的问题在于,能发现的关注点太少了,能观察到的侧面就太少,拆分的粒度远远不足。所以,尝试多发现一些问题,再来说怎么组合。

    2021-01-10
    3
    6
  • 青鸟飞鱼
    函数不超过多少行时,别人会用一些有名的开源库来回你,这怎么办?

    作者回复: 有名的开源程序库是以什么著称的,是代码写得好吗?当然不是了,所以,它们并不是好代码的代表。

    2021-01-14
    2
    5
收起评论
显示
设置
留言
42
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部