Clean Code 之函数
在软件开发过程(Where)中,程序员(Who)随时随地都有需要编写函数(方法)大多数语言编写的系统都是以主函数main作为系统启动入口,这也从侧面表现出函数在软件系统中的重要性。在日常编程(When)中,函数也无处不在,如何编写一个好的函数就成为一个很重要的话题。
当然,部分读者会秉着”够用就好“的思想认为一个函数,由输入至输出可以实现基本功能就足以。但是作者认为,函数作为系统中无处不在的模块,应当具备规则去保证软件系统的高可重用性、高可扩展性、高可靠性。
本文结合《Clean Code》函数章节和《Alibaba Java 开发手册》部分内容。从以下几个方面分析如何编写一个好的函数:
什么是好的函数
从结果而言,好的函数首要保证的是可执行并能完成基本功能。一个函数若不能执行,便沦为空谈,毫无意义,函数不能执行的原因可能与函数内部逻辑或执行环境有关。
但若是编写的函数没有实现预期的功能,那么该函数的意义也无从体现,其更多可能就是逻辑有误。并且若是函数正确执行但却做了意外之事,就会变得更令人迷惑。
从协作开发而言,好的函数需要具备可读性、可重用性、可靠性。提高函数的可读性,可以方便自己或他人理解并进行维护和修改。可重用性指函数的复用性,可多次调用,其没有过多的重复性代码,保证代码的整洁度。也从侧面体现了好的函数的优点。
绝大部分情况下,一个具有基本素质的工程师都会保证函数从结果上看都是完全合格的,即保证了可执行并正确实现功能。因此,从协作开发角度,如何实现函数的高可读性、高可重用性就尤为重要。
编写优雅的函数
《Clean Code》中对如何编写优雅的函数做出了几点建议。以下将进行简单总结:
函数体的表现形式
短小的函数可读性更佳。在几十年前,因为硬件限制,建议函数长度不长于一屏(不利于整体阅读)。建议一个函数最长不过20行,若需要描述逻辑过多,可以对函数内逻辑进行提炼,保证一个函数实现一个目的。
在初学编程之际,我们通常会在main函数内写入所有逻辑,不懂分层提炼等等。但在实际系统开发中,一个函数只做一件事就尤为重要,更利于代码的编写与维护。判断函数是否只做了一件事可以看此函数内部是否可以再提炼出有意义的更短小的函数。请记住,只做一件事的函数式无法被合理切分为多个区段的。
在函数只做一件事的同时,同样可以注意提炼相同逻辑代码来避免重复性,以提高函数的可重用性。当然,若函数的职责始终单一,重复的可能性便十分之小。
当然,在进行函数提炼时,需要注意函数的抽象层次结构。函数中的语句都要在同一个抽象层级最佳,不同的抽象层级不要放在一起。以一个经典案例表明,如何把大象放进冰箱:
public void pushElephantIntoRefrige() { openRefrige(); pushElephant(); closeRefrige(); }这样保证内部函数在同一层次更利于代码自上而下的阅读规则。让每个函数后面跟着位于下一抽 象层级的函数,如此便可在查看函数列表时就能循着抽象层级向下阅读了。
在条件选择语句或循环语句中,若能实现其内代码块只占一行,即将其内部代码逻辑提炼为一个私有函数,也可以保证更好的可读性。当然这也就会保证函数内的嵌套层级不会太多。
若函数内有多种异常情况需要处理,应当将错误处理代码和主路径代码进行分离,以保障主干代码的整洁程度。若使用了try/catch代码块,可以将其内部代码块进行提炼。
函数的名与参
当函数极为短小且精悍时,函数只做一件事,再用一个优雅的命名描述这一件事便可造就一个优雅的函数。在对提炼函数命名时,要考虑的便是如何保证一系列函数的命名一致性。使用前后一致的模块名为相关联的函数进行命名。保证函数名清晰有效的描述清楚其功能即可,不必拘束于函数名称长短,函数名与功能统一且单一即可。
对于函数的参数,理想的参数数量是零个,建议不要使用三个及以上的参数数量。参数数量过多,会对测试覆盖和代码阅读提高难度。对于函数的参数,可以遵循以下几点建议:
- 不要使用参数作为输出。无论是使用指针还是引用,将函数的入参作为函数结果的输出是十分不利于函数的阅读的。因此,若要对函数输入参数进行转换操作,建议转换结果作为函数返回值返回。
- 函数中不要使用标识参数(比如Boolean 类型参数)。若使用标识参数,则此函数必然做了不止一件事,其次,会增加阅读难度。因此,在这类情况中,可以将函数划分提炼为两个下一抽象层级的函数。
- 若有多参数的需求,可以考虑重构函数以减少入参个数。或将多个参数抽象封装为一个对象,以减少参数数量。
- 若函数有参数,可将函数与参数命名结合形成良好的动词与名称对的形式。
实践是检验真理的唯一途径
书中曾言:
写代码与写文章很像,先有初稿,再不断打磨,直至达到心目中的样子。
函数是语言的动词,类是名称。
对于函数而言,一开始只实现功能,冗长且复杂,缩进与嵌套比比皆是,还有过长的参数列表,随意的名称,重复的代码等等。
然后经过打磨,分解函数、赋予有意义的名称、提炼函数、消除重复代码等等,经过重重升级,获得最终版优雅的函数。
实践是检验真理的唯一途径。本文结合作者粗略的见解进行了总结与分析。
但“如何写好函数”本就是一个偏主观的话题,在编程实践中人人都会积累了大量客观的评价指标,其中有些指标可能是相互制约的,例如复用性、可扩展性、可读性,三者就不容易共同提高。写好函数的重要性是不言而喻的。“编程一时爽,重构火葬场”的俚语人人时常耳闻。因此,我们可以在实践中不断改进提升我们的代码,从函数到系统架构,以小积大,构建优雅的系统故事。
从今天开始,从此刻开始,拿出之前的书写的函数代码,操作起来。Do IT.
Reference