舒服的代码读起来是清晰的、整洁的,让人看起来愉悦的,像诗一样。不舒服的代码反之。

好的代码像诗一样(不是朦胧诗手动狗头)。
那么雷总写的代码究竟如何呢?人邮君为大家找到了雷总1994年写的代码片段。


这段用x86汇编写成的代码(以上是代码片段)用于清除内存驻留程序,类似内存加速工具,雷军教科书般规范的注明了代码用意,时间,作者……还细腻的用符号组成了分隔符让代码更加优雅,读起来清晰、舒适,所以雷总称之为诗一般的代码其实也不算过分。

在B站六月份的一个访谈直播活动中,雷总也在给后辈的寄语中不断强调代码要整洁,逻辑要无懈可击。
因为我们编写的代码,除了用于机器执行产生我们预期的效果以外,更多的时候是给人读的,这个读代码的可能是后来的维护人员,更多时候是一段时间后的作者本人。
人邮君发现许多程序员都遇到过这样的情况:过几周或者几个月之后,再看到自己写的代码,感觉一团糟,不禁怀疑人生。
《代码整洁之道》的作者Bob大叔就提出一种观点:代码质量与其整洁度成正比。优秀的系统往往有优秀的结构设计,层次清晰,职责单一,模块化,方便拓展和复用。功能的添加往往只是在现有的框架中添加少量代码。而且Bob大叔在书中给了我们一些行之有效的规则,涵盖从命名到重构的多个方面,只要遵循这些规则,就能编写出干净的、让人舒服的代码。

代码整洁之道(异步图书出品)
代码整洁之道(异步图书出品)
¥77.9
购买
就拿函数举例吧。类和函数应短小,更短小
简化代码的一个简单方式就是不断拆分函数,一直拆分,拆分到不能再分出一个函数为止。拆分后的类和函数更加短小,能使代码可读性更高。
例如下面这段代码,又长又复杂,有大量字符串、怪异且不显见的数据类型和API。花3分钟时间,你能读懂多少?
public static String testableHtml(
PageData pageData,
boolean includeSuiteSetup
) throws Exception {
WikiPage wikiPage = pageData.getWikiPage();
StringBuffer buffer = new StringBuffer();
if (pageData.hasAttribute("Test")) {
if (includeSuiteSetup) {
WikiPage suiteSetup =
PageCrawlerImpl.getInheritedPage(
SuiteResponder.SUITE_SETUP_NAME, wikiPage
);
if (suiteSetup != null) {
WikiPagePath pagePath =
suiteSetup.getPageCrawler().getFullPath(suiteSetup);
String pagePathName = PathParser.render(pagePath);
buffer.append("!include -setup .")
.append(pagePathName)
.append("\n");
}
}
WikiPage setup =
PageCrawlerImpl.getInheritedPage("SetUp", wikiPage);
if (setup != null) {
WikiPagePath setupPath =
wikiPage.getPageCrawler().getFullPath(setup);
String setupPathName = PathParser.render(setupPath);
buffer.append("!include -setup .")
.append(setupPathName)
.append("\n");
}
}
buffer.append(pageData.getContent());
if (pageData.hasAttribute("Test")) {
WikiPage teardown =
PageCrawlerImpl.getInheritedPage("TearDown", wikiPage);
if (teardown != null) {
WikiPagePath tearDownPath =
wikiPage.getPageCrawler().getFullPath(teardown);
String tearDownPathName = PathParser.render(tearDownPath);
buffer.append("\n")
.append("!include -teardown .")
.append(tearDownPathName)
.append("\n");
}
if (includeSuiteSetup) {
WikiPage suiteTeardown =
PageCrawlerImpl.getInheritedPage(
SuiteResponder.SUITE_TEARDOWN_NAME,
wikiPage
);
if (suiteTeardown != null) {
WikiPagePath pagePath =
suiteTeardown.getPageCrawler().getFullPath (suiteTeardown);
String pagePathName = PathParser.render(pagePath);
buffer.append("!include -teardown .")
.append(pagePathName)
.append("\n");
}
}
}
pageData.setContent(buffer.toString());
return pageData.getHtml();
}
这段长代码有太多不同层级的抽象,有奇怪的字符串和函数调用,混以双重嵌套、用标识来控制的 if 语句等,不一而足。
但是,我们只要做几个简单的方法抽离和重命名操作,加上一点点重构,就能在几行代码之内解决问题。

当然,这段代码还可以再次重构。

怎么样,清爽多了有没有?
所以,if 语句、else语句、while语句等,其中的代码应该只占一行,该行大抵应该是一个函数调用语句,这样不但能保持函数短小,而且,因为块内调用的函数拥有较具有说明性的名称,还可以增加代码的可读性和价值。
- 函数只做一件事(同一层级的事)
同一个函数的每条执行语句应该是同一层级的抽象。函数中混杂不同抽象层级,往往会让人迷惑,无法判断某个表达式是基础概念还是细节。
例如,我们经常会写一个函数需要给某个 DTO 赋值,然后再调用接口,接着返回结果。那么这个函数应该包含三步:DTO 赋值,调用接口,处理结果。如果函数中还包含了 DTO 赋值的具体操作,那么说明此函数的执行语句并不是在同一层次的抽象。
- 自顶向下读代码:向下规则
我们想要让代码拥有自顶向下的阅读顺序,想要让每个函数后面都跟着位于下一抽象层级的函数,这样一来,在查看函数列表时,就能循抽象层级向下阅读了。这就是向下规则。
《代码整洁之道》的Bob大叔就给我们了一个思路:程序就像是一系列TO起头的段落,每一段都描述当前抽象层级,并引用位于下一抽象层级的后续TO起头段落。
比如:
1.要获取查询结果,先处理查询参数,然后再判断参数合法性,然后再进行查询。(这是最大的思路步骤)
2.要处理查询参数,要先拿到传过来的参数做一些逻辑处理。 ---->getSearchFileds()
3.要判断参数合法性,要进行一系列业务逻辑的判断,最后返回错误信息,统一处理。 ----> checkParam()
4.要进行查询获取结果,要先把引入model,然后处理组装数据,最后返回。把所有组装细节都放在查询获取里面。 ----> _searchWebGameStatis()
- 参数越少越好
参数越多的函数,调用时越麻烦。尽量保持参数数量足够少,最好是没有。
此外,注释与命名,都是非常重要的。针对这些,Bob大叔还为我们整理了很多准则和技巧,如果你也是和雷总一样有追求的程序员,可以读一读Bob大叔的代码整洁之道系列丛书,能让你的代码更加整洁,工作起来更加得心应手。


整洁之道三部曲:代码整洁之道+代码整洁之道
整洁之道三部曲:代码整洁之道+代码整洁之道 程序员的职业素养+敏捷整洁之道 回归本源(京东套装3册)
¥175.9
购买
人邮君也理解有一部分小伙伴目前没有时间读书,如果没有时间系统性地学习代码整洁相关的知识,也一定要开始注意雷总说的代码逻辑问题,保证代码的逻辑性和严谨性,如果不够严谨或者逻辑有问题,那么总有一天这个bug会被触发。
墨菲定律,在软件开发上总是很有效。