代码的“审美”

本文摘自 《编写可读代码的艺术》第三章—— “审美”

好的代码应该 “看上去养眼”,如何使用好的留白、对齐、顺序使你的代码变得更易读?

确切地说,有三条原则:

  1. 使用一致的布局,让读者很快习惯这种风格
  2. 让相似的代码看上去相似
  3. 把相关代码行分组,形成代码块

本文只关注可以改进代码的简单“审美”方法,有时候代码也可能与审美无关,更需要大规模重构、拆分。

为什么审美这么重要

我们来看看下面代码:

image.png

相对于下面这个更整洁的版本,你可能需要花更长的时间来理解上面代码。

image.png

很明显,使用从审美角度讲让人愉悦的代码更容易

你可能会说,哪有人故意把代码写成那么烂。那么,对于常见的有一定约束的代码,也可以做优化。

比如下面这段 Java 代码,来评估你的程序在不同的网络连接速度下的行为。 你有一个 TcpConnectionSimulator, 它的构造函数有4个参数:

  1. 网络连接速度 (Kbps)
  2. 平均延时(ms)
  3. 延时的“抖动”(ms)
  4. 丢包率(ms)

你的代码需要三个不同的实例:

image.png
这段代码需要有很多额外的换行来满足每行 80 字符的限制(假设这是你公司的规范),但这样会使 t3_fiber 变得很奇怪,违反了“相似的代码看上去相似” 原则。

为了让代码看上去一致,我们可以引入更多换行:
image.png
这段代码有优雅一致的风格,并且很容易从头到尾快速浏览。但它占用了更多纵向空间,并且注释重复了3遍.


下面是这个类更紧凑的写法:
image.png
把注释移到了上面,所有参数都放在一行。"数据"排成了紧凑的一个表格。

用方法来整理不规则的东西

假设你有一个数据库,它提供了下面这个函数:

// Turn a partial_name like "Doug Adams" into "Mr. Douglas Adams"
// If not possible, 'error' is filled with an explanation.
string ExpandFullName(Database Connection dc, string partial_name, string* error);

并且这个函数由一系列例子来测试:

image.png
这段代码毫无美感,有些行还得换行,风格也不一致。

但对这种情况,重新布置换行也仅能如此,甚至还有一些重复的操作会产生 error,比如“assert(…)”。
如果真的想改进这段代码,我们需要一个辅助函数,像这样:
image.png
尽管把所有脏活都封装在 CheckFullName 中,但仍不影响其可读性:
image.png
即使我们只是想让代码更有美感,但也带来了一些好处:

  • 消除了原先代码中大量重复,让代码更加紧凑。
  • 每个测试用例重要的部分(名字和错误字符串)都变得更加直白
  • 现在添加新测试应当更简单

所以我想表达的意思是使代码看上去漂亮不限于表面层次的改进,还可能会帮你把代码结构做得更好。

需要时使用列对齐

有时可以借用「列对齐」的方法使代码易读,例如上面例子的
CheckFullName() 的参数:
image.png
很容易区分第二个和第三个参数。

又比如 Google 编码规范,可以使人快速浏览全貌
image.png
应该使用列对齐吗?
有人可能会觉得建立和维护对齐的工作量比较大,甚至“牵一发而动全身”。 我们的建议是可以试试,它其实并不像想象中那么费时间,如果真的很费工夫,可以不这么做。

选一个有意义的顺序

在列对齐的基础上,很多时候,代码的顺序不会影响其正确性,例如:

image.png
这种情况下,不要随机排序,把它们按有意义的排列更有帮助,一般遵循以下原则:

  • 让变量的顺序与对应 HTML 表单中字段匹配
  • 从 “最重要” 到 “最不重要” 排序
  • 按字母顺序排序

把声明按块组织起来

我们的大脑很自然地会分组、分层次结构思考,因此同样可以组使读者快速理解你的代码。

例如,下面是一个前端服务器的 C++ 类,这是它所有方法的声明:

image.png
其实也并不难看,但这样的布局对读者快速理解不会有帮助,我们按逻辑将它们分组,像下面这样:

image.png
这样会更加易读。因为你可以快速找出 4 个高层次段落,然后在需要时再阅读每个段落具体内容。

把代码分成“段落”

书面文字分段落是由于以下原因:

  • 它是一种把相似的想法放在一起并与其他想法分开的方法,
  • 它提供了可见的“脚印”, 如果没有它,会很容易找不到读到哪了
  • 便于段落之间导航

同样,代码也应当分“段落”, 例如,没有人会喜欢这样的代码

image.png
这个函数会经过数个不同的步骤,因此,把这些代码分成段落特别有用:
image.png
我们还给每个段落加了一条总结性的注释,这也会使它更易读。

个人风格与一致性

有相当一部分审美选择可以归结为个人风格, 例如,类定义的大括号

class Logger {
	...
}
// 或是
class Logger
{
  ...
};

选择哪种都不会影响代码可读性,但混在一起,对可读性就很有影响了。
一致的风格比“正确” 的风格更重要,这在团队协作时尤为重要。

总结

大家都喜欢读“漂亮”的代码,通过把代码用一致的,有意义的方法“格式化”,可以把代码变得更易读,读的更快。

下面是讨论过的方法:

  • 如果多个代码块做相似的事情,尝试让它们有同样的剪影
  • 把代码按“列”对齐可以让代码更容易浏览
  • 选择一个有意义的顺序,并始终用这样的顺序
  • 用空行来把大块代码分成逻辑上的段落。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值