整洁clean代码的好坏丑总结


Robert C. Martin 的《代码整洁之道》是一本开创性的编程书籍。包括我在内的整整一代开发人员都通过 Bob 大叔的建议成为了更好的程序员。但近二十年后,这本书是否仍然符合其高标准?《代码整洁之道》中的一些建议是否值得怀疑甚至错误?现在有更好的替代方案吗?

公平地说,作者本人在前言中声称“书中的一些建议是有争议的,人们可能会不同意”。在本文中,我试图反驳这一点。让我们来看看《代码整洁之道》的优点、缺点和丑陋之处。

优点
除了本书的编程指导之外,我认为本书最大的成就是创造了“干净代码”一词,并提高了人们对代码质量的普遍认识:

要想走得快,唯一的办法就是走得好——鲍勃大叔

这本书在编程界的影响是首屈一指的。突然之间,代码质量、可读性和可维护性成为开发人员关注的焦点。我坚信这会让程序员的世界变得更美好。

这本书本身充满了很棒的编程建议,主要用 Java 编写,但也适用于其他编程语言。对于刚开始编程的新程序员来说,这本书尤其有价值。您将找到有关函数和变量名称的基本提示,这些名称应该能够揭示意图并可搜索。书中还介绍了其他永恒的理念,例如DRY原则(不要重复自己)、命令查询分离和值得注意的隐喻,例如童子军规则。

此外,本书还给出了许多有用的编程实践。高级开发人员认为这些是理所当然的,但初级开发人员需要先学习它们,例如:

  • 好的命名是使用问题域名称来命名函数、类和变量。这也是 DDD 中的一个主要原则,即通用语言。
  • 良好的异常处理使用未检查异常并提供尽可能多的上下文
  • 好的单元测试应该是 FIRST(快速、独立、可重复、自我验证、及时),并且应该断言单一行为
  • 课程应遵守单一责任原则
  • 函数应该只做一件事,并且所有语句都应该具有相同的抽象级别
  • 应该优先使用没有副作用的纯函数
  • 函数应该遵循命令-查询分离模式
  • 保持代码干燥
  • 不要注释代码,删除它——有版本控制
  • 良好的界限很重要。不要过多依赖第三方库,将它们隐藏在接口后面。这将使您的代码可测试
  • 通过封装/信息隐藏实现的良好数据抽象将保留类不变量并保证抗错误和可理解的 API。
这些做法对所有程序员来说都是永恒的,无论新老。我发现自己在结对编程会议、讨论或其他类型的谈话中一遍又一遍地向团队成员提供这些建议。

本书的另一个亮点是详尽的代码异味概要,书中描述了最常见的代码异味及其相应的对策。不仅知道如何编写好的代码很重要,而且知道如何检测坏代码也很重要。

缺点
即使是一本开创性的书也不是完美的。下面,我试着描述我批评的两个主要观点。首先,虽然《代码整洁之道》仍然是软件工程的经典资源,但其中的一些内容已经过时了。例如,它过于关注 Java,对EJB和 AspectJ的依赖 限制了它在现代编程实践中的适用性。

此外,它涵盖的并发主题很浅显而且太低级,尤其是考虑到 Go 和 Rust 等一流并发语言的兴起。这些新语言提供了更健壮、更高效的并发方法。

这本书主要使用 Java 和面向对象编程示例,这可能不能充分代表当今现代编程风格的多样性。特别是它缺乏对函数式编程概念的全面探讨,包括不变性、引用透明性、高阶函数以及对避免副作用的强调。这些原则偶尔会被提及,但并未始终如一地应用。

其次,本书对编码原则的教条式介绍可能是一把双刃剑。虽然它提供了宝贵的建议,但缺乏细致入微的解释和背景可能会导致误解,尤其是对于新开发人员而言。过分热衷于遵守“小函数”或“DRY 原则”等规则而不考虑成本,对代码质量有害。

例如,盲目应用“DRY 原则”可能会导致过度抽象,从而导致微小、过于复杂的类的泛滥。这会使代码更难理解和维护。更好的方法是认识到有时重复是可以接受的,以提高可读性或性能,这对于有效的软件开发至关重要。

更重要的是,我们不应该将战术编码实践置于更高的设计原则之上,例如耦合、内聚、信息隐藏等。书中的一些引文:

函数的第一条规则是它们应该很小。函数的第二条规则是它们应该比函数小。—— 《代码整洁之道》,第 3 章,第 34 页

每次你在代码中看到重复,就代表着错过了一次抽象的机会。—— 《代码整洁之道》,第 17 章,第 289 页

这种写作风格也会导致“货物崇拜”编程,即开发人员盲目遵循规则而不了解其根本原因。由于人们坚持自己对书中建议的解释而不考虑其具体项目背景,因此这种写作风格往往会导致激烈的争论和误解。

我承认,人们无法判断自己的处境并不是这本书的错,但这种咒语般的写作风格并没有真正鼓励人们进行更深入的推理。有趣的是,这本书有时会偏离这种写作风格并谴责教条主义:

为了使类和方法更小,我们可能会创建太多小类和方法。因此,这条规则建议我们也将函数和类的数量保持在较低水平。

高等级和高方法论有时是毫无意义的教条主义的结果​​。

有没有一套简单的做法可以取代经验呢?显然没有。

《清洁代码》,第 12 章,第 176 页


这些段落很少见,我希望这本书能包含更多这样的认真陈述,以触发读者的思考过程并促使他运用自己的判断力。重要的是要记住,软件开发不是一项千篇一律的努力。优秀的开发人员不仅了解《代码整洁之道》中概述的原则,而且还具备判断力,可以在不同情况下适当地应用它们。好的建议和做法总是伴随着权衡。这些权衡必须是透明和已知的,否则就不可能充分利用它们。

规则和指南只是我们工具箱中的工具,但我们需要针对每个问题重新推理和判断它们。

这就是我如此喜欢 Kent Beck 的名言的原因:

这得看情况 ——肯特·贝克
(Context is King)

基本上,Kent 的这句小话概括了软件工程的灵魂。这也是我在工作中最常用的一句话.

丑陋
书中的示例,尤其是臭名昭著的素数生成器,经常与其提供的建议相矛盾。这些示例优先考虑冗长而不是清晰,使其难以理解,尤其是对于初学者而言。它们经常依赖于 Java 特定的框架,如 FitNesse和JUnit 内部结构,为不熟悉这些工具的程序员设置了障碍。

此外,一些示例(如参数解析器)长达数十页,让读者不知所措。过分强调教条导致代码错综复杂,阻碍了“程序员熟练工”(本书的目标读者)的学习过程。这就是为什么代码示例是这本书的丑陋部分


结论
我会向新程序员推荐《代码整洁之道》吗?是的,但不再是第一本软件工程书籍了。在我看来,有更好的选择:

上述书籍包含伟大的工程智慧,在我看来,它们以开放的心态写成。读者可以自由思考。这些书提供了更多关于实践、权衡利弊以及 这些实践为何有用的背景信息。虽然它们没有朗朗上口的名字,但《代码清洁》是无与伦比的。

然而,《代码清洁》是一本经典著作,仍然是必读之作,因为它包含永恒的建议。只要确保你不要盲目地、不加判断地应用这些实践即可。