“AI 技术+人才”如何成为企业增长新引擎?戳此了解>>> 了解详情
写点什么

怎样写出可读性高的代码?

  • 2021-03-29
  • 本文字数:2672 字

    阅读完需:约 9 分钟

怎样写出可读性高的代码?

清楚你的优先级

代码的写法有很多种:有的运行起来很快,有的只会占用少量内存,有的更容易测试,而有的代码则有很高的可读性。


若要编写思路清晰的代码,第一步就是要将可读性放在第一位。


这也意味着势必要降低其他因素的优先级。如果把所有因素都作为最高优先级,就意味着没有优先级。

培养清晰的意识

想要写出好代码,首先要知道什么才是好代码,想要写出思路清晰的代码,也要了解什么才是思路清晰。多阅读一些质量上乘的代码可以让我们对好代码有个大概的认知。


了解什么才是优秀代码并不能杜绝我们继续写出糟糕的代码,但至少能让我们知道代码的哪里不对劲。

修订

编写代码时,我们最初所想的思路未必清晰。在大多数情况下,只有在第一次完成代码后,我们才能找到更适合的思路。反复阅读已完成的代码才会带来更改的空间。

从解释开始

如果我们还搞不清代码结构,那么可以试着想象一下怎样向他人解释清楚或者把逻辑思路写下来,比如“如果删除账户,那么我们需要跳过 xxx。如果 xxx 的进程还没有结束,那么……”。然后把这套逻辑翻译成代码就很顺了。


写程序时,带入人类沟通方式而不是计算机中的抽象概念要更容易。

注释

代码中的注释可以解释某段代码的用处,或者是程序结构为什么要这么写。


单单是阅读程序并不会告诉我们作者所想就是正确的逻辑。里面可能会有我们不了解的商业规则:美国境外的用户有时会把街道名写到地址栏第一行的最末尾。里面也可能有一些技术小技巧:以某种奇怪的方式构造查询,从而让 Postgres 正确地优化它。诸如此类的代码细节,都是只有了解逻辑背后的背景情况下才能彻底明白为什么要这么写的。


代码不会说话。如果我们决定跳过某些步骤,但又懒得留下注释解释为什么,过两天再回来看这段代码恐怕就真没人知道你当时在想什么了。


部分代码可能读两遍就能想明白个中缘由,但为了保险起见,还是不要给自己的大脑添加不必要的负担。

不要搞混层次

不要搞混函数中的抽象层次。


这段“欢迎”代码层次混乱:


def welcome(self):  results = db.query(    'SELECT EXISTS 1 FROM emails WHERE kind = ? AND user = ?',    'welcome_email', self.user.id,  )  if results[0]:    return  self.send_welcome_email()
复制代码


这段则是相对整齐的:


def welcome(self):  if not self.has_sent_welcome_email():    self.send_welcome_email()
复制代码


函数中混乱的抽象层次会让读者思考代码用途和实现方式时被迫进行思维跳跃。当前抽象层次的代码告诉我们代码在做什么,而下一层次的代码则是关于代码要如何实现的。


在例子里的“welcome”函数中,我们首先在数据库中查询是否有过往邮件记录,如果没有则发送一封欢迎邮件。请注意,第二个版本中的“welcome”函数将查询部分放到了另一个函数中,“welcome”中仅仅关注“做什么”,这就是将函数中的抽象层次保持在了同一层,逻辑也更加清晰。不同函数分散在不同抽象层次,将较低层次的实现细节委托给较低抽象层次的函数。

分解函数

有时,分解大体积函数到子函数会更便于阅读。


对于分步骤执行的函数,将函数中的每个步骤都分解成子函数效果会更好。而对于其他如决策类的函数,不同的决策会引向不同的函数:有的部分负责制定决策,有的则是负责执行决策。分解函数的方法有很多种维度,只有通过不断的练习才能一眼看穿哪种才是正确的。


小体积函数有以下几点好处:


  • 每一部分的逻辑都有自己函数名。知道每一块逻辑负责什么更方便我们找到这些函数应当被放在哪

  • 作用域中变量更少

  • 在运行堆栈轨迹和调试时能更清晰地看出函数的作用

  • 小型函数可以被单独测试


其实,没有任何函数计算机也能运行得好好的,函数的存在只是为了服务于程序员,所以还请多多利用它们。

不要分解函数

不要重复你自己(don't repeat yourself, DRY)的意思经常被过度解读。


如今,抽取魔法数常量,以及针对某类特定决策的逻辑副本,已经算是公认的标准答案。此类重复的代码的确不好。而 DRY 的过度解读是指面对区区两行的重复代码,便如临大敌恨不得除之而后快。完全避免任何的重复代码意味着我们最后将面对一堆毫无意义、令人迷惑的代码,其存在只为了防止程序中的两三行重复代码。再加上由于在逻辑上毫不相干的两段代码被迫捆绑在一起,代码也更加难以修改。


判断一段代码的重复是否可容忍很简单:修改 A 段代码,保留 B 段不变,如果程序报错,那么就把 A 和 B 整理到同一段代码;如果无事发生,那么就放着别管。DRY 并不代表我们需要手动压缩代码库,而是为了避免两段代码要依赖于手动的同步。请记住,重复代码和抽象创造并不是同一件事。

避免使用可配置函数

宁可要十个零参数的小函数,也不要一个带十个参数的函数。


诸位对类似的事一定不陌生:初始干净的函数,只在三个不同的地方被调用。而当我们想要在第四处调用时,我们需要做一点小的调整,添加一个参数。但这样第一个 caller 就多了一个新功能,也需要多添加两个可配置的参数。等到第五个用例,我们还要再为它添加独特的参数,以此类推。但反过来我们就又会发现第二个 caller 跑起来太慢了,所以只好再添加另一个参数来跳过部分繁琐的程序。


不知不觉中,我们那个干净整洁的、只负责一件事的函数现在有了五个配置参数,现在能做的事情甚至可以达到 2 的五次方种!


这种情况下,将这一整个复杂的函数拆分成子函数,每个函数只负责各自的事就会好上很多。


但这样以来,又不可避免会出现重复。当这些重复的部分需要保持同步时,我们可以利用 DRY 的思路,将相同的部分抽取到子函数中。这时,做决策和考虑步骤就会容易很多。


请记住,区区几行重复代码是没问题的!像是在不同 list 上跑 for 循环的代码,这类就是可以接受的重复。


这种方法的好处之一是当其中一个用例被删除时,你可以轻松删除掉对应的函数,而不是在复杂函数的逻辑里掘地三尺试图找到对应的选项。只关注某个特定函数的读者也会更容易理解它们的用处。


(注意,当你能负责所有的 caller 时,这种方法才是正确的。如果你的函数只是公共 API 的一部分,那么请不要考虑使用这种方法。因为你并不清楚所有的用例都是什么,也不知道未来会有什么样的用例)

不要过早地进行优化

竞速赛车跑得比普通轿车要快,这点毋庸置疑。但这也是赛车在牺牲了柔软座椅、低噪音,以及车载空调的条件下。如果我们的程序不需要做竞速赛车,那就不要过早地拆掉空调。逐渐熟悉程序的构造,先从编写易于人理解的代码开始,不要一上来就试图挑战计算机的运行速度。


同理,也不应过早开始泛化。没人会在不需要处理大量物品的时候就买入一辆自卸货车,在没有过多需求的时候,我们也不用提前编写多余功能的代码。


原文链接:


[http://jeremymikkola.com/posts/2021_02_02_how_to_write_readable_code.html](

2021-03-29 13:431642
用户头像

发布了 138 篇内容, 共 73.4 次阅读, 收获喜欢 190 次。

关注

评论

发布
暂无评论
发现更多内容

Tower for Mac:强大的Git客户端

背包客

macos git Tower Mac 软件 mac软件下载

基于阿里云 Serverless 容器服务轻松部署企业级 AI 应用

阿里巴巴云原生

阿里云 Serverless Kubernetes 云原生 ASK

清爽快速全面的网址导航(cooltools.top)

Larry

人工智能 AI AIGC ChatGPT

连续两年!PingCAP 入选 Gartner 云数据库“客户之声”,获评“卓越表现者”最高分

PingCAP

《OpenHarmony 共建地图 2.0》在2023开放原子全球开源峰会发布

新消费日报

华为云企业快成长安全技术创新论坛广州站举办在即 都有哪些亮点干货?

说山水

MySQL读取的记录和我想象的不一致

华为云开发者联盟

数据库 后端 华为云 华为云开发者联盟 企业号 6 月 PK 榜

通过低代码平台,打造智能进销存系统

这我可不懂

低代码 进销存管理系统 进销存系统

美团买菜基于 Flink 的实时数仓建设

Apache Flink

大数据 flink 实时计算

博睿数据应邀出席第五届双态IT北京用户大会,分享《如何帮助用户构建高级可观测性》

博睿数据

可观测性 AIOPS 智能运维 博睿数据 IT行业

ChatGPT与Web的完美结合:创造一加一大于二的化学反应

加入高科技仿生人

Web 低代码 ChatGPT

麒麟操作系统是什么?和linux的区别是什么?

行云管家

信创 麒麟操作系统

软件测试/测试开发丨Pytest测试框架学习笔记

测试人

程序员 软件测试 pytest

Bartender 4 for Mac(菜单栏应用管理软件) 中文

背包客

macos Mac 软件 mac软件下载 MacBook Pro Bartender

Koordinator 最佳实践系列:精细化 CPU 编排

阿里巴巴云原生

阿里云 云原生 Koordinator

提升网站速度,选择香港主机的三大理由!

一只扑棱蛾子

香港主机

Pycharm配置远程调试

代码的路

我的多巴胺回来了!双手奉上在rumble上下载视频的最佳秘诀!

frank

Python的离线安装

代码的路

卡奥斯获开放原子开源基金会黄金捐赠人授牌

Openlab_cosmoplat

开放原子全球开源峰会

体验昇腾Ascend C 编程语言极简易用的算子开发

华为云开发者联盟

人工智能 华为云 昇腾AI 华为云开发者联盟 企业号 6 月 PK 榜

Python和Anaconda的版本对应关系

代码的路

三维人脸建模和驱动技术,让数字人快速“活”起来

华为云开发者联盟

人工智能 华为云 数字人 华为云开发者联盟 企业号 6 月 PK 榜

5款超级好用的开发效率工具,建议收藏!

引迈信息

程序员 前端 低代码 开发效率

火山引擎金融专区通过安全等保四级资质测评

科技热闻

KaiwuDB 数据库高可用方案及落地实现

KaiwuDB

KaiwuDB 数据库高可用

卡奥斯联合开放原子开源基金会倡议发起“云原生工作委员会”

Openlab_cosmoplat

开源社区 开放原子全球开源峰会

卡奥斯正式加入开放原子开源安全委员会

Openlab_cosmoplat

开源社区 开放原子全球开源峰会

重磅再推 | 基于OpenSearch向量检索版+大模型,搭建对话式搜索

阿里云大数据AI技术

人工智能 搜索引擎 企业号 6 月 PK 榜

怎样写出可读性高的代码?_语言 & 开发_Jeremy Mikkola_InfoQ精选文章