《实现模式(修订版)》—第3章3.1节价值观

第3章 一种编程理论
实现模式(修订版)
就算是再巨细靡遗的模式列表,也不可能涵盖编程中所遇到的每一种情况。你免不了(甚至常常)会遭遇到这种情景:上穷碧落,也找不到对应的现成解决方案。于是便需要有针对特定问题的通用解决方案。这也正是学习编程理论的原因之一。原因之二则是那种知晓如何去做、为何去做之后所带来的胸有成竹。当然,如果把编程的理论和实践结合起来讨论,内容就会更加精彩了。

每个模式都承载着一点点理论。但实际编程中存在一些更加深广的影响力,远不是孤立的模式所能概括的。本章将会讲述这些贯穿于编程中的横切概念,它们分为两类:价值观与原则。价值观是编程过程的统一支配性主题。珍视与其他人沟通的重要性,把代码中多余的复杂性去掉,并保持开放的心态,这才是我工作状态最佳的表现。这些价值观——沟通、简单和灵活——影响了我在编程时所做的每个决策。

此处描述的原则不像上面的价值观那样意义深远,不过每一项原则都在许多模式中得以体现。价值观有普遍的意义,但往往难以直接应用;模式虽可以直接应用,却是针对于特定情景;原则在价值观和模式之间搭建了桥梁。我早已发现,在那种没有模式可以应用,或是两个相互排斥的模式可以同等应用的场合,如果把编程原则弄清楚,对解决疑难会是一件好事。在面对不确定性的时候,对原则的理解让我可以“无中生有”创造出一些东西,同时能和其他的实践保持一致,而且结果一般都不错。

价值观、原则和模式,这3种元素互为补充,组成了一种稳定的开发方式。模式描述了要做什么,价值观提供了动机,原则把动机转化成了实际行动。

这里的价值观、原则和模式,是通过我的亲身实践、反思以及与其他人的讨论总结出来的。我们都曾经从前人那里吸收经验,最终会形成一种开发方式,但不是唯一的开发方式。不同的价值观和不同的原则会产生不同的方式。把编程方式用价值观、原则和模式的形式展现出来,其优点之一就是可以更加有效地展现编程方法的差异。如果你喜欢用某种方式来做事,而我喜欢另一种,那么就可以识别出我们在哪种层次上存在分歧,从而避免浪费时间。如果我们各自认可不同的原则,那么争论哪里该用大括号根本无助于解决问题。

3.1 价值观
有3个价值观与卓越的编程血脉相连,它们分别是:沟通、简单和灵活。虽然它们有时候会有所冲突,但更多的时候则是相得益彰。最优秀的程序会为未来的扩展留下充分的选择余地,不包含不相关的元素,容易阅读,容易理解。

3.1.1 沟通
如果阅读者可以理解某段代码,并且进一步修改或使用它,那么这段代码的沟通效果就很好。在编程时,我们很容易从计算机的角度进行思考。但只有一面编程一面考虑其他人的感受,我才能编写出好的代码。在这种前提下编写出的代码更加干净易读,更有效率,更清晰地展现出我的想法,给了我全新的视角,减轻了我的压力。我的一些社会性需要得到了自我满足。最开始编程吸引我的部分原因在于我可以通过编程与外界交流,然而,我不想与那些难缠又无法理喻的烦人家伙打交道。过了20年,把别人当作空气一样的编程方式才在我眼中褪尽了颜色。耗尽心神去精心搭建一座糖果城堡,于我而言已毫无意义。

Knuth所提出的文学编程理论促使我把注意力放到沟通上来:程序应该读起来像一本书一样。它需要有情节和韵律,句子间应该有优雅的小小跌宕起伏。

我和Ward Cunningham第一次接触到文学性程序这个概念以后,我们决定来试一试。我们找出Smalltalk中最干净的代码之一——ScrollController,坐到一起,然后试着把它写成一个故事。几个小时以后,我们以自己的方式完全重写了这段代码,把它变成了一篇合情合理的文章。每次遇到难以解释清楚的逻辑,重新把它写一遍都要比解释这段代码为何难以理解容易得多。沟通的需要改变了我们对于编码的看法。

在编程时注重沟通还有一个很明显的经济学基础。软件的绝大部分成本都是在第一次部署以后才产生的。从我自己修改代码的经验出发,我花在阅读既有代码上的时间要比编写全新的代码长得多。如果我想减少代码所带来的开销,我就应该让它容易读懂。

注重沟通还可以帮助我们改进思想,让它更加现实。一方面是由于投入更多的思考,考虑“如果别人看到这段代码会怎么想”所需要调动的脑细胞,和只关注自己是不一样的。这时我会退后一步,从全新的视角来审视面对的问题和解决方案。另一方面则是由于压力的减轻,因为我知道自己所做的事情是在务正业,我做的是对的。最后,作为社会性的产物,明确地考虑社会因素要比在假设它们不存在的情况下工作更为现实。

3.1.2 简单
在Visual Display of Quantitative Information一书中,Edward Tufte做过一个实验,他拿过一张图,把上面没有增加任何信息的标记全都擦掉,最终得到了一张很新颖的图,比原先那张更容易理解。

去掉多余的复杂性可以让那些阅读、使用和修改代码的人更容易理解。有些复杂性是内在的,它们准确地反映出所要解决的问题的复杂性。但有些复杂性的产生完全是因为我们忙着让程序运行起来,在摆弄过程中留下来的“指甲印”没擦干净。这种多余的复杂性降低了软件的价值,因为一方面软件正确运行的可能性降低了,另一方面将来也很难进行正确的改动。回顾自己做过的事情,把麦子和糠分开,是编程中不可或缺的一部分。

简单存在于旁观者的眼中。一个可以将专业工具使用得得心应手的高级程序员,他所认为的简单事情对一个初学者来说可能会比登天还难。只有把读者放在心里,你才可以写出动人的散文。同样,只有把读者放在心里,你才可以编写出优美的程序。给阅读者一点挑战没有关系,但过多的复杂性会让你失去他们。

在复杂与简单的波动中,计算机技术不断向前推进。直到微型计算机出现之前,大型机架构的发展倾向仍然是越来越复杂。微型计算机并没有解决大型机的所有问题,只不过在很多应用中,那些问题已经变得不再重要。编程语言也在复杂和简单的起伏中前行。C++在C的基础上产生,而后在C++的基础上又出现了Java,现在Java本身也变得越来越复杂了。

追求简单推动了进化。JUnit比它所大规模取代的上一代测试工具简单得多。JUnit催生了各种模仿者、扩展软件和新的编程/测试技术。它最近一个版本JUnit 4已经失去了那种“一目了然”的效果,虽然每一个导致其复杂化的决定都有我参与其中,但亦未能阻止这种趋势。总有一天,会有人发明一种比JUnit简单许多的方式,以方便编程人员编写测试。这种新的想法又会推动另一轮进化。

在各个层次上都应当要求简单。对代码进行调整,删除所有不提供信息的代码。设计中不出现无关元素。对需求提出质疑,找出最本质的概念。去掉多余的复杂性后,就好像有一束光照亮了余下的代码,你就有机会用全新的视角来处理它们。

沟通和简单通常都是不可分割的。多余的复杂性越少,系统就越容易理解;在沟通方面投入越多,就越容易发现应该被抛弃的复杂性。不过有时候我也会发现某种简化会使程序难以理解,这种情况下我会优先考虑沟通。这样的情形很少,但常常都表示这里应该有一些我尚未察觉的更大规模的简化。

3.1.3 灵活
在三种价值观中,灵活是衡量那些低效编码与设计实践的一把标尺。以获取一个常量为例,我曾经见到有人会用环境变量保存一个目录名,而那个目录下放着一个文件,文件中写着那个常量的值。为什么弄这么复杂?为了灵活。程序是应该灵活,但只有在发生变化的时候才需如此。如果这个常量永远不会变化,那么付出的代价就都白费了。

因为程序的绝大部分开销都是在它第一次部署以后才产生,所以程序必须要容易改动。想象中明天或许会用得上的灵活性,可能与真正修改代码时所需要的灵活性不是一回事。这就是简单性和大规模测试所带来的灵活性比专门设计出来的灵活性更为有效的原因。

要选择那些提倡灵活性并能够带来及时收益的模式。对于会立刻增加成本但收效却缓慢的模式,最好让自己多一点耐心,先把它们放回口袋里,需要的时候再拿出来。这样就可以用最恰当的方式使用它们。

灵活性的提高可能以复杂性的提高为代价。比如说,给用户提供一个可自定义配置的选择提高了灵活性,但是因为多了一个配置文件,编程时也需要考虑这一点,所以也就更复杂了。反过来简单也可以促进灵活。在前面的例子中,如果可以找到取消配置选项但又不丧失价值的方式,那么这个程序以后就更容易改动。

增进软件的沟通效果同样会提高灵活性。能够快速阅读、理解和修改你的代码的人越多,它将来发生变化的选择就越多。

本书中介绍的模式会通过帮助编程人员创建简单、可以理解、可以修改的应用程序来提高程序的灵活性。

时间: 2024-11-24 03:57:55

《实现模式(修订版)》—第3章3.1节价值观的相关文章

《设计模式解析(第2版•修订版)》—第2章 2.1节概览

第2章 UML2.1 概览设计模式解析(第2版•修订版)本章内容 本章将简单概述UML(统一建模语言),这是面向对象界主要使用的一种建模语言.如果你还不知道UML,阅读本章将使你具备阅读本书模型图所需的最低限度的知识. 本章中,我们将: 叙述"什么是UML"和"为什么使用UML": 阐述本书中的基本UML图,即 类图: 交互图. 本文仅用于学习和交流目的,不代表异步社区观点.非商业转载请注明作译者.出处,并保留本文的原始链接.

《设计模式解析(第2版•修订版)》—第2章 2.6节小结

2.6 小结设计模式解析(第2版•修订版)本章内容 UML既能够充实设计,又能够用于设计的交流.不要太担心要"正确地"画图.要考虑的是什么方式最有利于交流设计中的概念.换句话说,如果你认为有什么东西需要说,可以用注释来表达. 如果你对一个图标或符号不太确定,必须查手册才能确定其意义,还是加一条注释来解释.毕竟,其他人有可能也不清楚它的意义.清晰为好.当然,这也意味着你应该以规范的方式使用UML--那样无法正常交流.在画图的时候,只考虑要传达的思想即可. 本文仅用于学习和交流目的,不代表

《设计模式解析(第2版•修订版)》—第1章 1.1节概览

1.1 概览设计模式解析(第2版•修订版)本章内容 本章将通过与大家都熟悉的范型--标准结构化程序设计比较异同的方式,来介绍面向对象范型. 当年,面向对象范型正是为了应对使用标准结构化程序设计遇到的诸多挑战才应运而生的.弄清楚这些挑战,我们才能够更好地看到面向对象程序设计的优点,并更好地理解这一机制. 本章无法使你成为面向对象方法的专家,甚至不会介绍所有基本的面向对象概念.但是,本章将使你为阅读本书其他部分做好准备.本书其他部分将阐释如何像专家所做的那样正确使用面向对象设计方法. 本章中,我们将

《设计模式解析(第2版•修订版)》—第1章 1.9节小结

1.9 小结设计模式解析(第2版•修订版)本章内容 本章中我说明了面向对象技术是怎样帮助我们最大程度地减少系统需求变更带来的影响,以及面向对象与功能分解的异同. 我还讨论了面向对象程序设计的许多基本概念,介绍和描述了主要术语.表1-3总结了这些概念,表1-4总结了面向对象程序设计的主要术语. 本文仅用于学习和交流目的,不代表异步社区观点.非商业转载请注明作译者.出处,并保留本文的原始链接.

《软件工程(第4版?修订版)》—第2章2.1节过程的含义

第2章 过程和生命周期的建模软件工程(第4版•修订版)本章讨论以下内容: 过程的含义:软件开发的产品.过程和资源:软件开发过程的若干模型:过程建模的工具和技术.我们在第1章中看到,软件工程既是一个创造的过程,又是一个逐步进行的过程,它涉及很多人员,这些人员生产不同类型的产品.在这一章,我们会详细分析这些步骤,讨论各种活动的组织方式,以便我们能够协调所做的各种活动以及决定什么时候进行这些活动.本章首先定义什么是过程,以便我们能够理解对软件开发建模时必须包含哪些内容.接着讨论几种软件过程模型.在理解

《团队软件过程(修订版)》—第2章2.1节项目为何失败

第2章 团队软件过程的基本原理团队软件过程(修订版)本章主要介绍TSPi,解释它如何工作以及为何有效.另外,本章还介绍了团队的概念,解释了团队如何工作,并讨论了常见的团队协作问题. 有关团队协作的资料很多,优秀团队和表现不佳的团队的例子也很多.本章不可能涵盖所有资料,只对主要问题做重点介绍.有关团队协作的进一步讨论,可以参考第16章和第17章.本章只是一个简介,在使用TSPi的过程中,你应该仔细阅读本书的每个章节,以深入了解你面对的工作所涉及的主题.本章内容安排如下. 项目为何失败.学习如何处理

《团队软件过程(修订版)》—第2章2.7节小结

2.7 小结团队软件过程(修订版)本章简要介绍了TSPi的基本原理,涵盖了团队的概念.团队的工作原理.解决团队问题的方法等内容.TSPi的设计是为了充分发挥团队的优势,尽量避免团队的弱点及其所造成的影响.TSPi过程使用了明确定义的角色.过程脚本和标准. 软件项目的失败一般是因为团队协作问题,而不是技术问题.一个重要的人员问题涉及工程师处理紧迫的进度压力的能力.TSPi通过制定详细的计划并提供结构化的开发过程,来帮助团队处理这些压力. 成功团队的标准是:团队界定清晰,任务清晰明确,团队成员能控制

《UML用户指南(第2版.修订版)》—第1章1.1节建模的重要性

第一部分 入门UML用户指南(第2版.修订版) 第1章 为什么要建模UML用户指南(第2版.修订版)本章内容建模的重要性建模的4项原理软件系统的基本蓝图面向对象建模成功的软件组织应该总是能够交付满足其用户需要的软件.如果一个软件组织能够及时并可预测地开发出这样的软件,并能够有效地利用人力和物力资源,那么这个软件组织就是可持续发展的. 在上段话里有一个重要的含义:一个开发队伍的主要产品不应该是一堆漂亮的文档.世界级的会议.伟大的口号或者几行获得普利策奖金的源代码,而应该是满足不断发展的用户及其业务

《Google软件测试之道》—第2章2.2节测试认证

本节书摘来自异步社区<Google软件测试之道>一书中的第2章2.2节测试认证,作者[美]James Whittaker , Jason Arbon , Jeff Carollo,更多章节 2.2 测试认证 Patrick Copeland在本书的序中强调了让开发人员参与测试的难度.招聘到技术能力强的测试人员只是刚刚开始的第一步,我们依然需要开发人员参与进来一起做测试.其中我们使用的一个 关键方法就是被称为"测试认证"(译注:Test Certified)的计划.现在回过头