admin管理员组

文章数量:1566354

前言

提示1:关注你的技艺。

如果你不关心怎么把软件开发好,那么软件开发领域就再也没什么好谈的事情了。

提示2:思考!思考你的工作。

请在做事的时候,思考一下自己正在做什么。不断地思考,即时地批判自己的工作。

1 务实的哲学

提示3:你有权选择。

总有一些原因导致开发者拒绝改变。他们缩在那里,期盼着事情会自己变好。因此,这里给出本书最重要的提示:你有权选择。

这个行业给了你一系列非凡的机遇。积极主动点,掌控这些机遇。

提示4:提供选择,别找借口。

不要说搞不定;解释一下要做些什么才能挽回这个局面。

提示5:不要放任破窗。

一扇破损的窗户,只要一段时间不去修理,建筑中的居民就会潜移默化地产生一种被遗弃的感觉——当权者不关心这幢建筑的感觉。然后,其他的窗户也开始损坏,居民开始乱丢废物,墙上开始出现涂鸦,建筑开始出现严重的结构性破坏。在一段看上去很短的时间内,建筑的损坏程度就足以打消业主们想修好它的期望,被遗弃的感觉最终变成了现实。

为何造成这样的影响?心理学家的研究表明,绝望是会传染的,就像狭窄空间中的流感病毒。无视一个明显损坏的东西,会强化这样一种观念:看来没有什么是能修好的,也没人在乎,一切都命中注定了。所有的负面情绪会在团队成员间蔓延,变成恶性循环。

不要搁置“破窗”不去修理。每发现一个就赶紧修一个。如果没有足够的时间完全修好,那么就把它钉起来。也许你可以注释掉那些糟糕的代码,显示一行“尚未实现”的信息,或用假数据先替代一下。采取行动,预防进一步的损害发生,表明一切尽在你的掌握中。

提示6:做推动变革的催化剂。

找出你合理的请求,然后不断完善。一旦有成果产出,展示给人们看,让他们大吃一惊。现在可以用上“当然了,它还可以更好,只要我们再加点......”这句话,而且要假装你并不在意。这时先坐下来,等他们开始问你要不要加些你原本想要的功能。人们都觉得,加入一个推进中的成功项目更容易一些。因为只要一窥未来,大家就能团结在一起。

提示7:牢记全景。

永远留意着大局,持续不断地审视你身边发生的事情,而不要只专注于你个人在做的事情。

提示8:将质量要求视为需求问题。

你能训练自己写出够好即可的软件——对用户、未来的维护者来说够好即可,只要好的程度能让你自己内心平静就可以。你会发现,你变得更有效率,用户也更快乐。而且,可能让你更开心的是,更短的孵化器促使你的程序实际上更好了。

对于你创建的系统,其应用领域和要达到的质量,必须作为系统需求的一部分加以讨论。

许多用户宁愿今天就用上一个毛糙的软件,也不愿意多等上一年再用那个打磨光亮、功能齐备的版本(而且,实际上他们一年后真正需要的东西可能完全不同)。

不要让过度的修饰和精炼侵蚀掉一个完好的程序。继续前行,让代码在它该有的位置驻留一段时间。它或许并不完美,不要紧的——它就算永不完美也没关系。

提示9:对知识组合做定期投资。

这里有一些建议:每年学习一门新语言、每月读一本技术书、还要读非技术书、上课、加入本地的用户组和交流群、尝试不同的环境、与时俱进。

提示10:批判性地分析你读到和听到的东西。

谁从中受益?有什么背景?什么时候在哪里可以工作起来?为什么这是个问题?

提示11:英语就是另一门编程语言。

把英语(或者你的母语是别的什么语言)看成另一门编程语言,像写代码一样用自然语言写文章。

提示12:说什么和怎么说同样重要。

除非你与世隔绝,否则必须学会交流。越是有效的交流,影响力就越大。

提示13:把文档嵌进去,而不要栓在表面。

务实的程序员将文档视为整个开发过程的一个组成部分。为了让编写文档变得更容易一点,我们要避免重复劳动和浪费时间,让文档总是在手边——直接写在代码里。

用源码中的注释生成好看的文档非常容易,建议给模块和导出函数都加上注释,这能在其他开发者使用的时候,给他们很大的助力。

2 务实的方法

提示14:优秀的设计比糟糕的设计更容易变更。

能适应使用者的就是好的设计。对代码而言,就是要顺应变化。因此要信奉ETC原则(Easier To Change,更容易变更)——就该如此。据我们所知,无论是什么设计原则,都是ETC的一个特例。

提示15:DRY——不要重复自己。

Don't repeat yourself. 在一个系统中,每一处知识都必须单一、明确、权威地表达。

在规范、流程、开发的程序中复制知识太容易了,一旦我们动手这么做,就会招致维护的噩梦——这个噩梦在程序发布前就会开始。

提示16:让复用变得更容易。

你要努力的方向,应该是孕育出一个更容易找到和复用已有事物的环境,而不是自己重新编写。如果复用不容易,人们就不会这么做。如果你未能复用,就有重复知识的风险。

提示17:消除不相关事物之间的影响。

我们希望设计的组件自成一体:独立自主,有单一的清晰定义的意图(即内聚)。当组件彼此隔离时,你知道可以变更其中一个组件,而不必影响到其他组件。只要不去改变组件的对外接口,就可以放心,不会发生波及整个系统的问题。

提示18:不设最终决定。

假设项目开始时是一个基于浏览器的应用程序,但后来,市场营销人员认识到他们真正想要的是一个移动App。这会给你造成多大的困难呢?在理想情况下,这不应对你造成太大的影响,至少在服务器端是这样。你要做的应该是剥离出HTML呈现层并用另一套API替换掉。

错误在于认为任何决定都是板上钉钉的——而没有为可能出现的意外做好准备。

你能做的就是让修改更容易一点。将第三方API隐藏在自己的抽象层之后。将代码分解成多个组件:即使最终会把它们部署到单个大型服务器上,这种方法也比一开始做成庞然大物,然后再切分要容易得多。

提示19:放弃追逐时尚。

要让你的代码具备“摇滚”精神:顺境时摇摆滚动,逆境时直面困难。

提示20:使用曳光弹找到目标。

总结下来就是:先完成基本功能,确保能编译和运行,再添加其他功能。

提示21:用原型学习。

总结下来就是:建模。

提示22:靠近问题域编程。

务实的程序员能直接使用应用领域的语言编程,直接使用该领域的词汇、语法和语义。

提示23:通过估算来避免意外。

通过估算来避免意外。

提示24:根据代码不断迭代进度表。

先完成初始功能的编码和测试,然后将其标记为第一次迭代的结束点。基于这个过程积累的经验,可以用来提炼最初对迭代次数及每次迭代要做些什么的猜测。一次次地迭代下去,提炼出的东西会变得更好,对进度的信心也会随之增长。这种评估工作在每个迭代周期的末尾团队进行回顾时完成。

3 基础工具

提示25:将知识用纯文本保存。

我们相信,纯文本是将知识持久地存储下来的最佳格式。

大多数二进制格式的问题是,理解数据所需的上下文与数据本身是分离的。这是在人为地将数据与其含义剥离。数据可能因此被加密起来;缺少了解析它们的应用逻辑,数据变得毫无意义。然而用纯文本,就有了一种自解释的数据流,而它和创建它的应用程序是相互独立的。

提示26:发挥Shell命令的威力。

如果没有花很多时间研究所用系统的Shell命令,那么这个东西可能会让你心存畏惧。然而,投入一些精力去熟悉Shell,事情很快就会开始步入正轨。试着玩一下Shell命令,你会惊讶地发现它使工作效率提高了很多。

如果使用图形界面去完成所有工作,就会错失环境的全部能力。你将无法把常见的任务自动化,或是无法充分利用工具所能提供的强大功能。并且,你也无法通过组合你的工具来创建定制的宏工具。图形工具的好处在于WYSIWYG——所见即所得;弱势之处是WYSIAYG——所见即全部。

提示27:游刃有余地使用编辑器。

如果你操作编辑器游刃有余,最主要的收益来自于变得“顺畅”——不必再把心思花在编辑技巧上面。从思考到想到的东西呈现在编辑器中的整个过程,没有阻塞,一气呵成。思考变流畅,编程就会受益。

提示28:永远使用版本控制。

我们会将自己输入的所有内容都例行公事地提交到版本控制系统中。即使不是在开发项目,我们也会用一个仓库将日常事务保护起来。

提示29:去解决问题,而不是责备。

Bug是你的错还是别人的错并不重要。无论是谁的错,问题仍然要你来面对。

提示30:不要恐慌。

人们很容易陷入恐慌,尤其是当最后期限逼近,或是在老板或客户站在背后紧张凝视之下,拼命找出问题原因的时候。然而,这时非常重要的是要退后一步冷静思考。对于那些你觉得是Bug引起的症状,认真想想,到底什么会导致它们那个样子。

如果你在看到Bug或Bug报告时的第一反应是“这不可能”,那你就大错特错了。不要在“但那不可能发生”的思路上浪费哪怕一个神经元,因为很明显它会发生,而且已经发生了。

提示31:修代码前先让代码在测试中失败。

开始动手修Bug时,最好是先使其重现。毕竟,如果你不能重现它,又怎么知道它究竟是否被修复了呢?

提示32:读一下那该死的出错信息。

简单明了,无需赘言。

提示33:“select”没出问题。

操作系统、编译器或第三方产品中都可能存在Bug,但这并不是首先要考虑的。正在开发的应用程序的代码中更有可能存在Bug。通常,假定应用代码对库的调用不正确,要比假定库本身坏掉了更有利。即使问题的确是第三方的责任,在提交Bug报告之前,仍然需要排除掉你的代码的问题。

提示34:不要假设,要证明。

当面对一个“让人吃惊”的错误时,必须接受之前的一个或多个假设是错的 。不要因为“觉得”一个程序或一段代码没问题,就在它牵涉一个Bug时,对它视而不见。你需要证明它没问题,用出Bug时的上下文、同样的数据、当时的边界条件来证明它没问题。

提示35:学习一门文本处理语言。

可以选择Ruby或Python。

4 务实的偏执

提示36:你无法写出完美的软件。

完美的软件的确不存在。

既然没人能写出完美的代码,那么也包括自己在内。务实的程序员会为自己的错误建立防御机制。

提示37:通过契约进行设计。

契约式设计是一种简单但功能强大的技术,侧重于文档化(并约定)软件模块的权利和责任,以确保程序的正确性。什么是正确的程序?不多也不少,正好完成它主张要做的事情的程序。文档化及对主张进行检验是契约式设计(缩写为DBC)的核心。

在正交性中,我们建议编写“害羞”的代码。而在这里,强调的是“懒惰”的代码:在开始之前,对要接受的东西要求严格一点,并且尽可能少地对回报做出承诺。请记住,如果你订的契约是可以接受任何东西,并且承诺要回报整个世界,那么你就有很多代码要写。

提示38:尽早崩溃。

一旦代码发现本来不可能发生的事情已发生,程序就不再可靠。从这一刻开始,它所做的任何事情都是可疑的,所以要尽快终止它。一个死掉的程序,通常比一个瘫痪的程序,造成的损害要小得多。

提示39:使用断言去预防不可能的事情。

无论何时,你发现自己在想“当然这是不可能发生的”时,添加代码来检查这一点。最简单的方法是使用断言。

提示40:有始有终。

许多开发人员对于处理资源分配和释放,没有一致的计划。这个建议能简单地应用到大多数场合。简单说就是,分配资源的函数或对象,对释放资源应负有责任.。

提示41:在局部行动。

当有疑问时,缩小范围总是有好处的。

提示42:小步前进——由始至终。

总是采取经过深思熟虑的小步骤,同时检查反馈,并在推进前不断调整。把反馈的频率当作速度限制,永远不要进行“太大”的步骤或任务。

怎样的任务才算太大?任何大到需要“占卜”的任务。越是必须预测未来会怎样,就越有可能犯错。与其浪费精力为不确定的未来做设计,还不如将代码设计成可替换的。

提示43:避免占卜。

很多时候,明天看起来会和今天差不多,但不要指望一定会这样。

5 宁弯不折

提示44:解耦代码让改变更容易。

耦合是修改之敌,因为它将事情连接在一起,要改就得一起改。这使得修改变得更加困难:要么需要画上不少时间,弄清楚所有需要修改的地方到底有哪些,要么又会因为“仅仅只修改一处”而没有跟着改与之相耦合的地方,把时间花在想明白为什么会出问题上。

提示45:只管命令不要询问。

不应该根据对象的内部状态做出决策,然后更新该对象。这样做完全破坏了封装的优势,并且在这样做时,也会把实现相关的知识扩散到整个代码中。

提示46:不要链式调用方法。

当你访问某样东西时,尽量不要超过一个“.”。这里说的访问,也包括使用中间变量的情况。

在实践中,应用程序中的任何内容,都应该被认为是可能发生改变的。第三方库中的任何东西都应该被认为是易变的,特别是如果已知该库的维护者在版本之间修改过API。

但如果你链式调用的东西真的不太可能改变(比如语言覆盖的库可能非常稳定),那么这个规则就不适用。

提示47:避免全局数据。

全局可访问的数据是应用程序组件之间耦合的潜在来源。

全局变量给代码带来耦合有很多原因。最明显的是,修改全局变量的实现,可能会潜在地影响到系统中的所有代码。当然,在实践中影响相当有限;归根结底,问题在于你必须找到每一处需要修改的地方。

提示48:如果全局唯一非常重要,那么将它包装到API中。

任何可变的外部资源都是全局数据。如果应用程序使用了数据库、数据存储、文件系统、服务API等,那么它就有落入全局化陷阱的风险。解决方案是确保始终将这些资源包装在你所控制的代码之后。

提示49:编程讲的是代码,而程序谈的是数据。

我们需要重新把程序视为从输入到输出的一个变换。当这样做的时候,许多以前操心的细节就消失了。结构变得更清晰,错误处理更加一致,耦合下降了很多。

提示50:不要囤积状态,传递下去。

一个函数可以在任何地方使用(并重用),只要其参数与其他函数的输出相匹配。

提示51:不要付继承税。

继承就是耦合。

提示52:尽量用接口来表达多态。

接口与协议给了我们一种不使用继承的多态性。

提示53:用委托提供服务:“有一个”胜过“是一个”。

不懂。

提示54:利用mixin共享功能。

不懂。

提示55:使用外部配置参数化应用程序。

如果代码依赖某些值,而这些值在应用程序发布后还有可能改变,那么就把这些值放在程序外部。当应用程序于不同的环境中运行,而且面对不同的用户时,将和环境相关、用户相关的值放在应用之外。通过这种方式来参数化应用程序,让代码适应其运行的环境。

6 并发

提示56:通过分析工作流来提高并发性。

使用活动图分析工作流。

提示57:共享状态是不正确的状态。

任何时候,只要两个或多个代码块持有对同一个可变数据块的引用,就已经共享状态了。然而,共享状态是不正确的状态。

提示58:随机故障通常是并发问题。

作为并发性问题的根源,内存的共享备受关注。但实际上,在应用程序代码共享可变资源(文件、数据库、外部服务等)的任何地方,问题都有可能冒出来。当代码的两个或多个实例可以同时访问某些资源时,就会出现潜在的问题。

提示59:用角色实现并发性时不必共享状态。

角色是一个独立的虚拟处理单元,具有自己的本地(且私有的)状态。每个角色都有一个信箱。当消息出现在信箱中且角色处于空闲状态时,角色被激活并开始处理消息。处理完该条消息后,它将继续处理信箱中的其他信息,如果信箱是空的,则返回休眠状态。

在处理消息的过程中,一个角色可以创建其他角色,可以向其他认识的角色发送消息,也可以创建一个新的状态,用来在处理下一条消息时作为当前状态。

提示60:使用黑板来协调工作流。

工作流系统可能很复杂,而且需要大量的程序员。随着规则的变化,工作流必须重新组织:人们可能不得不修改过程,并且硬编码的部分可能不得不重写。

采用黑板,是解决这些困难的一种优雅的方案。数据到达的顺序无关紧要:当发布一个事实时,可以触发适当的规则。反馈也很容易处理:任何一组规则的输出都可以发布到黑板上,从而触发更多适用的规则。

7 当你编码时

提示61:倾听你内心的蜥蜴。

作为一名开发人员,你已经尝试过很多东西,并已了解哪些是有效的,哪些是无效的。你一直在积累经验和智慧。如果能感到一种挥之不去的疑虑,或在面对一项任务时感觉有些不情愿,那可能是那些经验试图和你说些什么——要注意听。你可能无法确切地指出哪里出了问题,但经过一段时间后,疑虑可能会变得实在,变成可以确定的东西。让直觉来提高你的绩效。

听从直觉同样适用于更宽泛的领域。有时候,如果一个设计让你感觉不妥,或是一些需求让你觉得不爽,就停下来去分析这些感觉。如果你身处一个支持性环境,那就大声说出这些感觉。探索下去,很可能在某个黑暗的门口潜伏着什么东西。听从你的直觉,在问题跳出来之前加以避免。

提示62:不要依赖巧合编程。

找到恰好能用的答案和找到正确的答案不是一回事。

你能向一个更初级的程序员详细解释一下代码吗?如果做不到,也许正在依赖某个巧合。

提示63:评估算法的级别。

即评估算法复杂度。

提示64:对估算做测试。

做完所有的估算后,只有在生产环境中用真实的数据跑一遍,得到的计时结果才算数。

如果获得精确的计时结果比较困难,可以用代码分析器统计算法中不同步骤运行的次数,然后再根据输入的数据大小绘制出图表。

提示65:尽早重构,经常重构。

重构是指重组现有代码实体、改变其内部结构而不改变其外部行为的规范式技术。

重构并不是一种特殊的、隆重的、偶尔进行的活动。重构是一项日复一日的工作,需要采取低风险的小步骤进行。这是一种有针对性的、精确的方法,有助于保持代码易于修改,而不是对代码库进行自由的、大规模的重写。

为了保证外部行为没有改变,你需要良好的自动化单元测试来验证代码的行为。

当你学到一些东西时,当你比去年、昨天甚至十分钟前更了解某事时,你会重构。也许是由于代码已经不太合适,让你遇到一个绊脚石,或是注意到有两件事情的确需要合并,又或是被其他什么事情触动而心生悔意,不要犹豫,去改掉它。此时不做,更待何时。无论问题是多是少,都有可能促使我们对代码进行重构。

时间压力常常被用作不重构的借口。但是这个借口根本站不住脚:如果现在不进行重构,那么以后就需要投入更多的时间来解决问题——因为需要处理更多的依赖关系。到时会有更多的时间吗?不可能有。

提示66:测试与找Bug无关。

我们相信,测试获得的主要好处发生在你考虑测试及编写测试的时候,而不是在运行测试的时候。

提示67:测试是代码的第一个用户。

测试所提供的反馈至关重要,可以指导编码过程。

在你能对一个东西做测试之前,必须先理解它。虽然听起来很傻,但现实中我们开始编写代码,都只能基于对必须要做的事情的模糊理解。我们打算边干边解决。哦,稍后还会添加支持边界条件的所有代码。哦,还有错误处理要完成。这样进行下去,代码会比它应有的长度长五倍,因为它充满了条件逻辑和特殊情况。但是,如果用测试先探照一下代码,事情就会变得更清楚。如果你在开始编写代码之前,就考虑过测试边界条件及其工作方式,那就就很可能会发现简化函数的逻辑模式。如果你考虑过需要测试的错误条件,那么就会相应地去构造这个函数。

提示68:既非自上而下,也不自下而上,基于端对端构建。

我们坚信,构建软件的唯一方式是增量式的。构建端到端功能的小块,一边工作一边了解问题。应用学到的知识持续充实代码,让客户参与每一个步骤并让他们指导这个过程。

提示69:为测试做设计。

你编写的所有软件最终都将被测试——如果不是由你和你的团队做测试,那么就将由最终的用户去测试——所以不妨计划好进行彻底的测试。稍微提前考虑一下,就能大大降低维护成本,减少求助电话。

提示70:要对软件做测试,否则只能留给用户去做。

毫无疑问,测试是编程的一部分,不该留给其他部门的人去做。

提示71:使用基于特性的测试来校验假设。

我们倾向于让计算机来做一些测试,它不会受你的先入之见的影响。

我们把契约和不变式放在一起并称为特性。

    契约:当你的输入满足条件时,它会对输出做出一定的保证。

    不变式:在通过一个函数后,某部分的状态保持为真。例如,如果对列表进行排序,结果将具有与原始列表相同的元素数量——长度就是一个不变式。

使用特性来自动化我们的测试。

提示72:保持代码清洁,让攻击面最小。

系统攻击面的面积指,攻击者可以在其中输入数据、提取数据或调用服务执行的所有访问点的总和。

    代码越简单越好。更少的代码意味着更少的Bug,更少机会出现严重安全漏洞。

    永远不要信任来自外部实体的数据,在将其传递到数据库、呈现视图或其他处理过程之前,一定要对其进行消毒。

    做好身份认证,将授权用户的绝对数量保持在最小值,要淘汰不使用的、旧的或过时的用户和服务。

    不要泄露信息,并确保所通报的数据适合用户的权限。

    要确保任何“测试窗口”和运行时异常报告都已受到保护,不会被间谍看见。

提示73:尽早打上安全补丁。

历史上最严重的数据泄露是由系统更新滞后造成的,别让这种事发生在你身上。

提示74:好好取名;需要时更名。

在计算机科学中只有两件难事:缓存失效、命名。

8 项目启动之前

提示75:无人确切知道自己想要什么。

许多书籍和教程都将采集需求放在项目的早期阶段。“采集”一词似乎隐喻着,一群快乐的分析师,他们在周遭的土地上寻找智慧的金块,而背景音乐正在轻柔地演奏者田园交响曲。“采集”意味着需求已经在那里了——你只需要找到它们,将其放在篮子里,然后愉快地上路。

但事实并非如此。需求很少停留在表面。通常情况下,它们被埋在层层的假设、误解和政治之下。更糟糕的是,需求通常根本不存在。

提示76:程序员帮助人们理解他们想要什么。

现实世界是混乱的、矛盾的、未知的。在现实世界中,得到任何事物的精确规范,即使不是完全不可能,也是非常罕见的。这就是我们程序员的用武之地。我们的工作是帮助人们了解他们想要什么。事实上,这可能是我们最有价值的属性。

提示77:需求是从反馈循环中学到的。

坦白说,有时候你对该领域的具体情况真的所知甚少。

在这种情况下,务实的程序员藉由“你是不是这个意思”这样的客户访谈来得到反馈。我们制造出展示模型和产品原型,并让客户先用用看。理想情况下,我们生产的东西足够灵活,经得起在与客户讨论过程中的修改;该我们对客户反馈的“这不是我的意思”做出回应了,就用这一句——“是不是更像这样”。

务实的程序员将所有项目视为采集需求的练习。这就是为什么我们更喜欢那种较短的迭代过程:每次迭代都以客户的直接反馈结束。这样可使我们走上正轨,并确保如果走错了方向,损失的时间是最少的。

提示78:和用户一起工作以便从用户角度思考。

在了解系统真实使用方式的同时,你还会惊讶于一个小小请求的实际效果——“你工作的时候我可以在旁边坐一个星期吗”。它既有助于建立信任,也为我们与客户的沟通奠定了基础。但要记住不能碍事!

提示79:策略即元数据。

如果需求被声明为“只有主管和人事可以查看员工记录”,那么开发者可能会为应用程序每次访问该数据编写一个显式的测试。但是,如果声明是“只有授权用户才能访问员工记录”,那么开发者可能会设计并实现某种访问控制系统。当策略改变时(往往会变的),只需要更新该系统的元数据。以这种方式采集需求,自然会导向一个通过良好分解来支持元数据的系统。

提示80:使用项目术语表。

一旦开始讨论需求,用户和领域专家就会使用对他们各自来说有特定意义的特定术语。例如,可能“客户”和“消费者”是有区别的,在系统中随意混用这两个词就是不合适的。

创建并维护一张项目术语表,在上面记录项目中所有特定术语和词汇的定义。项目所有的参与者,包括最终用户和支持员工,都应该使用同一张术语表来确保一致性。这意味着术语表必须随处可访问,同时也说明了为什么需要在线文档。

提示81:不要跳出框框思考——找到框框。

当面对一个棘手的问题时,把你面前所有可能的解决途径都列举出来。不要忽略任何东西,无论听起来多么无用或愚蠢。现在遍历列出的清单并逐条解释为什么不能选择这条路。你确定吗?你能证明吗?

解决谜题的关键是,认识到你所受到的约束和你所拥有的自由度,因为认识到这些就会找到答案。这就是为什么有些谜题如此有效——我们太容易忽视潜在的解决方案。

提示82:不要一个人埋头钻进代码中。

如果你目前在个人独立编程,可以尝试一下结对编程。在需要集思广益、想出新点子,或诊断出棘手问题的时候,不妨尝试做一次群体编程。

提示83:敏捷不是一个名词;敏捷有关你如何做事。

敏捷软件开发宣言中的价值观:

    我们一直在实践中探寻更好的软件开发方法,身体力行的同时也帮助他人。由此我们建立了如下价值观:

        个体和互动高于流程和工具。

        工作的软件高于详尽的文档。

        客户合作高于合同谈判。

        响应变化高于遵循计划。

    也就是说,尽管右项有其价值,我们更重视左项的价值。

事实上,无论什么时候有人说,“这么干,你就敏捷了”,显然都是错的。

9 务实的项目

提示84:维持小而稳定的团队。

成为一个务实的人,有很多优势,但是如果这样的个体能在一个务实的团队中工作,优势会成倍增加。

在我们看来,团队是小而稳定的实体。50个人就不算是团队,那是部落。如果团队的成员经常被分配到其他地方,相互之间缺乏了解,那么这也不是一个团队,他们只是暂时同在一个公交车站躲雨的陌生人。

务实的团队很小,充其量也就10-12人左右。成员很少进出。每个人都很了解彼此,相互信任,互相依赖。

提示85:排上日程以待其成。

如果团队对改进和创新是认真的,那么就需要将其排入日程表。“只要有空闲时间”就去做,意味着这件事永远不会发生。

提示86:组织全功能的团队。

一个项目团队必须在项目的不同领域完成许多不同的任务,涉及许多不同的技术。理解需求、设计架构、为前端和服务器编码、测试,所有这些都必须进行。但有一个常见的误解是,这些活动和任务可以单独发生、相互隔离。不,这做不到。

有些方法论提倡在团队中设立各种不同的角色和头衔,或是创建完全隔离的专用团队。而这种方法的问题是,引入了门槛和交接。原先从团队到部署的平稳流程,现在必须中断,因为被人为设置了各种门槛,诸如确认后才能进行的交接,以及批准和文书工作。精益人士认为这是一种浪费,并在积极努力地加以消除。

提示87:做能起作用的事,别赶时髦。

怎样才能知道“什么能起作用”?有一个最基本的实用技巧可以依靠,那就是:

    试一试。

提示88:在用户需要时交付。

我们的目标当然不是“使用Scrum”、“进行敏捷”、“做到精益”或诸如此类的事情。我们的目标是交付可以工作的软件,让用户马上能获得新的功能。不是几周、几个月或几年以后,而是现在。

提示89:使用版本控制来驱动构建、测试和发布。

构建、测试和部署通过提交或推送给版本控制来触发,并在云容器中完成创建。发布到交付阶段,还是生产阶段,可以通过在版本控制系统中打标记来指定。这样,发布就不再有那么强的仪式感,变成了日常生活中的一部分——这是真正的持续交付,没有绑定到任何一台构建机器或开发人员的机器上。

提示90:尽早测试、经常测试,自动测试。

一旦代码写出来了,就要尽早开始测试。我们要写单元测试,写很多很多单元测试。

事实上,好项目的测试代码可能会比产品代码更多。生成这些测试代码所花费的时间是值得的。从长远来看,最终的成本会低得多,而且你实际上有机会生产出几乎没有缺陷的产品。

另外,知道通过了测试,可以让你对代码已经“完成”产生高度信心。

提示91:直到所有的测试都已运行,编码才算完成。

构建可能包括几种主要的软件测试类型:单元测试、集成测试、确认和验证,以及性能测试。

提示92:使用破坏者检测你的测试。

如果你对测试非常认真,那么可以从源码树中分出一个单独的分支,有目的地引入Bug,并验证测试是否能够捕获到。

提示93:测试状态覆盖率,而非代码覆盖率。

探索代码如何处理意外状态的一个好方法是,让计算机生成这些状态。

使用基于特性的测试技术,根据被测代码的契约和不变式生成测试数据。

提示94:每个Bug只找一次。

一个Bug一旦被人类测试员发现,这就应该是它被该人类测试员发现的最后一次。要立即修改自动化测试,以便这个特定的Bug,从此往后每次都被检查到——不能有任何例外,无论它多么琐碎,也无论开发者有多少抱怨,或是不停唠叨“哦,永远不会再发生了”。

提示95:不要使用手动程序。

人不像电脑那样具有可重复性。我们也不应对此抱有期望。

一切都要依赖于自动化。除非构建完全自动化,否则无法在匿名云服务器上构建项目。如果涉及手动步骤,则无法自动部署。一旦你引入了手动步骤,就打破了一扇非常大的窗户。

提示96:取悦用户,而不要只是交付代码。

用户真正要的不是代码,他们只是遇到某个业务问题,需要在目标和预算范围内解决,他们的信念是,通过与你的团队合作,能够做到这一点。

如果你想取悦客户,就和他们建立起某种关系,这样即可积极地帮助他们解决问题。或许你的头衔只是“软件开发者”或“软件工程师”的某种变体,而事实上这个头衔应该是“解决问题的人”。这就是我们所做的,也是一个务实的程序员的本质。

我们在解决问题。

提示97:在作品上签名。

过去的工匠很自豪地为他们的作品签名。你也应该这样。

我们想看到你对所有权引以为豪——“这是我写的,我与我的作品同在”。你的签名应该被认为是质量的标志。人们应该在一段代码上看到你的名字,并对它是可靠的、编写良好的、经过测试的、文档化的充满期许。这是一件非常专业的工作,出自专业人士之手。

一个务实的程序员。

提示98:先勿伤害。

人无完人,每个人都会时不时地忘记一些事情。但如果你不能满怀信心地声明自己已尽力列出所有后果,并确信能保护用户不受其影响,那么当事情变糟时,就难辞其咎。

提示99:不要助纣为虐。

有一些创造性的想法,开始打道德行为界限的擦边球,如果你参与了这类项目,就和出资者一样负有责任。

提示100:你要为自己的人生做主。精心营造,与人分享,为之喝彩。好好享受吧!

想象你要的未来。

当你做的事情违背了这个理想时,要敢于承认,并有勇气说“不!”对可以拥有的未来充满憧憬,才有动力去创造它。即使是空中楼阁,也要每天为它添砖加瓦。

我们都有精彩的人生。

本文标签: 之道程序员读书笔记