代码之美:如何让编程成为一门艺术?……
美丽的来源多种多样。就软件开发领域而言,简单和架构一致就能产生美感,美感和能精确地实现所需的功能以及创造性的解决问题密也是不可分。同样地,编码风格也是编写优雅代码不可或缺的一环,好的编码风格有助于降低团队沟通成本。
接下来让我们进步一探讨代码之美,以及如何让编程成为一种艺术。
从简单中寻找美
最近我读了《代码之美》的选集,其中最能引起我共鸣的一篇文章是 Jon Bentley 写的《我编写过的最漂亮的代码》 ,这篇文章的基本原则是“少即是多(less is more)” ,也就是说,一些优秀的开发人员要一次又一次地对代码进行重构、改进,以便消除冗余,使其尽可能简单易懂。
下面从书中选出的一些警句来阐述这种技巧:
设计师知道自己的设计已经达到完美,不是因为再也没有东西可以添加,而是再也没有东西可以拿掉。— Saint-Exupéry
最便宜、最快而且可靠性最高的计算机组件压根就不存在。— Gordon Bell
如果我有更多的时间,我会写更短的信给你。— Pascal
简单并不先于复杂,而是紧跟其后。— Perlis
换句话说,都在呼吁简洁。
每一行代码都需要被调试、阅读和维护。因此,如果能够在实现功能的同时能简化代码就太棒了。如果一个方法有 10 条语句,如果我们能把它减少到 5 条,出现问题的可能性就减少一半,因为可能出错、过于复杂或有问题的地方也相应的减少了。源代码不应该视为一种资产,而视为负担!当你以后想使用代码行作为生产力的度量标准时,要三思!
相关的三个哲学法则是:YAGNI(You Ain’t Gonna Need It,即我们不应该为程序编写尚未用到的功能),DRY( Don’t repeat yourself,即避免重复代码) 和 KISS(Keep It Simple, Stupid ,即简单就是美)。YANGI 原则建议如果你找不到一个某段代码存在的理由,就必须对其进行重构或剔除。避免重复代码原则提出,每一段代码都必须在系统中有唯一的明确的目的。KISS 原则传达的是:让事情变得更简单!
然而,具有讽刺意味的是,简单是一个复杂的问题。
软件中,最漂亮的代码、最漂亮的功能、最漂亮的程序根本不存在。
代码质量是程序的灵魂
开发人员很害怕听到 “bug” 这个词。人们普遍认为,代码没有 bug 的程序员就是优秀的程序员。尽管编写没有 bug 的程序是设计的要求,但是编写过程中没有 bug 是不现实的。我的意思是说,有些开发人员在编译阶段或执行程序之前就在努力编写没有错误的代码,他们更多地关注功能实现而不是代码的设计。
在开发过程中很容易忽略代码的可维护性。为了实现功能而忽略某种模式或标准,是导致灾难的重要原因(代价也会很大)。另外,程序员可能会太关注开发的效率;过早的代码优化就相当于打开了工程的潘多拉魔盒。
好的设计是能够让其他设计师因他们自己想不到该想法而怀疑自己的智商。
每个专业的软件开发人员都能编写能实现功能的代码,但是实现功能的代码和实现功能并经得起时间考验的代码之间有天壤之别。如果代码设计的足够健壮,修复错误就相当容易,因为我们很容易定位出现错误的地方!换句话说,当体系结构没有被破坏时,解决这些错误的成本更低,也不会产生太多技术债务。
所有的艺术都是从一张空白的画布开始的
开发者能够把他们的想法变成有形的东西,这就是创造力。屏幕就像一块空白的画布,等着被代码填满,等着一个独特的解决方案ーー如果这件作品不是独一无二的,那么它就只可能是“复制粘贴”的 !即使设计的软件最终外观上看起来一样,也没有两个程序员会编写完全相同的代码。作为一个程序员,每个人都有自己的特点。这点非常了不起的。根据我的经验,理解其他开发人员的代码,就像进入他们的思想,从他们的角度看世界。
编写代码的快感是很难形容的。这不仅仅是写几行代码这么简单。我们会目睹自己系统逐渐成型,当用户真正使用该系统时,开发者的想法就变成了显示。当你看到一个东西从概念到完工,不管这件事是大是小,你都能从中获得精神和情感上的满足,这都将能给你带来成就感。
在我进入下一部分之前,作为结束语,我将给出《计算机编程的艺术》(Art of Computer Programming) 系列](https://www.amazon.co.uk/Computer-Programming-Volumes-1-4A-Boxed/dp/0321751043)的作者唐纳德克努斯 (Donald Knuth) 被要求说明为啥书名中用“艺术”来描述计算机编程时的一段摘录 (对于非程序员来说,这就像是计算机科学的圣经) 。
他说:
计算机编程是一门艺术,因为它能让程序员用知识来解决问题,因为它需要技巧和创作力,特别是它能够创造出美好的东西。
复杂的终极表现形式是算法
算法为提高编程效率提供了可能。他们是编程的支柱,因为算法系统地描述了解决问题的步骤。逻辑分析属于左脑,解决问题需要创造性,就要用到我们的右脑。解决问题的关键在于控制复杂性。正如我们前面探讨的那样,复杂性会对我们的程序产生负面影响。
我所设计、评论或研究的所有最佳算法都有一个共同点: 它们通过聪明的想法来有效地处理计算任务,同时避免产生不必要的细节和复杂性。这包括:简化布尔代数、合理地组合、选择最适合的数据结构、使用简洁的正则表达式、合理利用资源以及遵循 SOLID 原则。
SOLID 原则是指设计模式的六大原则,即:
Single Responsibility Principle:单一职责原则;
Open Closed Principle:开闭原则;
Liskov Substitution Principle:里氏替换原则;
Law of Demeter:迪米特法则
Interface Segregation Principle:接口隔离原则
Dependence Inversion Principle:依赖倒置原则
然而这里有一个悖论,让创造算法成为一项复杂的任务:
没有算法可以解决创造力的问题 — Andy Hargreaves
代码风格很重要
到目前为止,我们认为好的代码都是简单易懂,设计精巧的。现在我将转向编程的美学方面: 代码布局。良好的代码风格和代码质量息息相关,很多程序员以自己能够对代码精雕细琢为荣。一个程序员不会因为他们代码被铭记,而会因为他的编码风格而被别人铭记。
程序员编写代码不仅是为了让计算机执行,也是为了让其他程序员在阅读、拓展、修复或调试之前能够理解它。因此准确编写代码并保持代码风格的一致性至关重要。
其中代码的缩进和空格的使用很关键。
最好的布局方案是能够让代码修改后也能保持风格的一致性,如修改一行代码,不会影响到其他代码。程序员的代码本身就应该有自我说明的能力,也就是说代码要有足够的注释、命名要能表达其真实意图、尽量编写简短且易于测试的纯函数等。
好的代码就是自己最好的说明文档 — S. McConnell
因此,漂亮的代码就是逻辑清晰、易于阅读和理解的代码。代码的结构、组织方式、架构都是为代码背后所要表达的意图服务的。代码的每一部分都应该相对简短并符合单一职责原则。这就像马赛克:所有的代码片段可以完美地组合到一起,但是,当其中一个代码片段需要修改时,可以很容易将其剥离出去。
参考资料
Rich Hickey 的必读佳作:因简单而更容易
Donald Knuth 的经典著作 计算机编程的艺术
程序员修炼之道:计算机编程的艺术
结束语
我们每次编写代码,都像是沿着一条不确定的道路上行走,都是在创造一个前所未有的解决方案。这是一段自我发现之旅,也是个体智能的表达,这就是艺术!
虽然我们不是那种能给别人带来视觉美感的艺术家,但是当我们热爱某样东西的时候,就应该把美融入其中。