🐳 📖

《代码大全》阅读笔记之六:系统考虑

📆 2021-05-24

来源:《代码大全》

🏷 编程阅读

🖍 从整体上,系统思考如何更好地完成项目构建。

🏂 正文 👇

这一部分主要介绍了程序规模对于构建的影响,如何管理构建,项目集成及编程工具等内容。

程序规模对构建的影响

项目工作量会随着项目规模的增长而显著增加。随着项目规模的增长,项目成员之间的交流成本也显著增加,改善交流效率的常用方法是采用正式的文档。项目的规模既会影响错误的数量,也会影响错误的类型,随着项目规模的增大,通常需求和设计犯的错误会更多。有些时候,错误仍然主要来自构建。对于小项目,影响生产率的最大因素莫过于单个程序员的技巧。随着项目规模和团队规模的增大,组织方式对生成率的影响也将随之增大。完成项目的小型团队的生产率要比大型团队高出 39%。生产率主要取决于你所从事的软件类型,人员素质,编程语言,方法论,产品复杂度,编程环境,工具支持,计算“代码行数”的方法,把非程序员的支持工作计入“每人年的代码行数”的方法,以及许多其他因素。随着项目规模的增大,构建活动在整个工作量中所占的比重将逐渐减少。构建活动的主导地位下降的原因是,随着项目增大,构建活动———详细设计,编码,调试和单元测试———将会按比例增长,但是其他很多活动增长得更快。不论项目的规模如何,有些技术总是很有价值的:有训练的编码实践,让其他开发者审查设计和代码,好的工具支持,以及使用高级语言。代码行数和团队规模并不是影响项目大小的仅有因素。另一个更敏感的影响因素是最终软件的质量和复杂度。没能认识到程序,产品,系统以及系统产品在精致度和复杂度上的区别,是导致估算出偏差的一个常见原因。随着项目规模的增长,构建活动将只占项目中工作量的一小部分。如果你完全依照构建的经验来做估算,估算误差就会增加。这里所说的估算误差,其产生原因在于你不理解“项目规模对开发大型程序所造成的影响”。各种方法论都被用于大小不同的项目。项目越大,复杂度也越大,也就越要求有意识地去关注方法论。对于大项目来说,如果不有意识地去选择方法论,就将无法完成任务。在社交场合,活动越正式,你所穿的服装就会越不舒服(高跟鞋,领带等等)。在软件开发领域里,项目越正规,你不得不写的文件的数量也会越多,用于确认你已经完成了自己的工作。在实践中最关键的是要考虑你的项目的实际规模和类型,然后找出“适量级”的方法论。

本章要点:

  • 随着项目规模的扩大,交流需要加以支持。大多数方法论的关键点都在于减少交流中的问题,而一项方法论的存亡关键也应取决于它能否促进交流。
  • 在其他条件都相等的时候,大项目的生产率会低于小项目。
  • 在其他条件都相等的时候,大项目的每千行代码错误率会高于小项目。
  • 在小项目里的一些看起来“理当如此”的活动在大项目中必须仔细地计划,随着项目规模扩大,构建活动的主导地位逐渐降低。
  • 放大轻量级的方法论要好于缩小重量级的方法论。最有效的办法是使用“适量级”方法论。

管理构建

由于代码是构建活动最主要的产出,因此,管理构建中的一个关键问题就是“如何鼓励良好的编码实践?”可以考虑制定代码标准。标准对于有些组织非常有用,而对于其他组织则用处不大。一些程序员很乐意接受标准,因为标准有助于减少项目中随意出现的诸多分歧。如果你的团队反对采用严格的标准。那么可以考虑一些其他的选择,如灵活的指导原则,一些建议(而非指导原则),或者一组能够表现最佳实践的例子。

管理构建的另一方面是配置管理。配置管理是“系统化地定义项目工件和处理变化,以使项目一直保持其完整性”的实践活动。它的另一种说法是“变更控制”。其中的技术包括评估所提交的更改,最终更改,保留系统在不同时间点的各历史版本。配置管理不是由程序员发明的,但由于编程项目是相当不稳定的,配置管理对程序员特别有用。将其应用于软件项目,配置管理也通常称做“软件配置管理”(SCM)。SCM 关注于程序的需求,源代码,文档和测试数据。SCM 虽然自身可能会有“过度控制”的问题,但是对于大型的项目是不可缺少的。对于项目中需求变更和设计变更的指导原则:

  • 遵循某种系统化的变更控制手续;
  • 成组地处理变更请求;
  • 评估每项变更的成本;
  • 提防大量的变更请求;
  • 成立变更控制委员会或者类似机构;
  • 警惕官僚主义,但也不要因为防备官僚主义而排斥有效的变更控制;

对于软件代码的变更,可以使用 git 之类的版本控制软件。养成定期备份项目的习惯。做完一个项目后,也要对该项目进行归档,把所有的东西都保存下来。

评估项目的规模和完成项目所需的工作量是软件项目管理中最具挑战性的方面之一。平均水平的大型软件都要超时一年,并且超过预算经费 100%才能完成。在个人层面上,对预估进度表和实际进度表的调查显示,开发人员的估计值比实际值要乐观 20% ~ 30%。这既与“对项目规模和工作量的评估”不准确有关,也与开发不力有关。下面是一套评估项目的好方法:

  • 建立目标;
  • 为评估留出时间,并且做出计划;
  • 清楚地说明软件需求;
  • 在底层细节层面进行评估;
  • 使用若干不同的评估方法,并且比较其结果;
  • 定期做重新评估;

项目早期的评估结果注定不会很准确。随着项目推进,评估的准确度会越来越高。在项目进行过程中要定期地重新评估,用你在每一项活动中学到的知识去改进你对下一项活动的评估。当进度落后的情况下:

  1. 人们可能会乐观地认为自己会在后面的阶段将时间补回来。但是这种情况几乎不会发生。调查显示,越接近项目后期,延误和超支的现象就越严重。项目并不能在后期把时间补回来,而是会越来越落后;
  2. 扩充团队;在某些场合下,往延期的项目里增加人手是能够让它提速的。如果一个项目中的任务不可分割,不能各个击破,那么增加人手是无济于事的。
  3. 缩减项目范围;可以选择重新评估实现那些非重要特性的开发时间,砍掉一些优先度不是很高的功能。

度量软件项目有很多种方法。任何一种项目特征都是可以用某种方法来度量的,而且总是会比根本不度量好得多。度量会对动机产生影响。反对度量就是认为最好不要去了解项目中到底发生了什么。

一个程序员大约有 30%的时间花费在“对项目没有直接好处”的非技术活动之上。不同程序员在天分和努力程度方面有十分巨大的差别。很多研究都已表明,在编写的程序的质量,编写的程序的大小以及程序员的生产率等方面,(最好的与最坏的)都有着一个数量级的差异。不同的编程团队在软件质量和生产率上也存在着相当大的差异。好的程序员倾向于聚集在一起,差的程序员也是一样。一个由“程序员能力等级在第 15 个百分点”的人员组成的团队,其开发应用程序需要花费的工作月数是“程序员能力等级在第 90 个百分点”的人员组成的团队的 3.5 倍。80%的贡献来源于 20%的贡献者。这其中的含义对于招聘和录用来说是非常清晰的。如果你为了聘请到前 10%最优秀的程序员而需要(比雇佣后 10%最差劲的程序员)多支付报酬,那么就请欣然接受这一现实。你会因为所聘用的程序员的高品质和高生产力而迅速得到回报,而且这么做还有一个剩余效应,那就是你的组织中其他程序员的品质和生产力不会下降,因为好的程序员倾向于聚到一起。物理环境对生产率有着巨大的影响。生产力与工作场所质量之间有着很强的相关性。如果你的工作环境属于最差的那 25%,那么你有机会给生产率带来 100%的提升,办法是把环境改善为最佳的那 25%。如果你的工作环境处于平均水平,你还是可以通过把环境改善为最佳的 25%,从而把生产率提升 40%甚至更多。

本章要点:

  • 好的编码实践可以通过“贯彻标准”或者“使用更为灵活的方法”来达到。
  • 配置管理,如果应用得当,会使程序员的工作变得更加轻松。特别包括变更控制。
  • 好的软件评估是一项重大挑战。成功的关键包括采用多种方法,随着项目的开展而修缮评估结果,以及很好地利用数据来创建评估等。
  • 度量是构建管理成功的关键。你可以采取措施度量项目的任何方面,而这要比根本不度量好得多。准确的度量是制定准确的进度表,质量控制和改进开发过程的关键。
  • 程序员和管理人员也是人,在把他们当人看的时候工作得最好。🤔

集成

术语“集成”指的是一种软件开发行为:将一些独立的软件组件组合为一个完整系统。对小项目,集成也许意味着花一上午的时间就可以把一些类编织到一起。对大项目,集成也许要花数周或数月时间,把一组程序编织为一个整体。“集成”这个主题与“构建的先后次序”这个主题先后纠缠。正确的集成是非常重要的。程序集成有两种方式:阶段式集成和增量集成。阶段式集成以前一直是规范。但是这种集成方式容易在集成的过程中一下子暴露大量的问题,同时使得问题难于诊断。在增量集成中,你一小块一小块地编写并测试你的程序,然后一次一次地将它拼接起来。增量集成比传统的阶段式集成有更多的优势:

  • 易于定位错误;在阶段式集成中,你一次集成许多组件,很难知道错误在哪。错误既可能位于其中任何一个组件,也可能位于组件之间的连接处。在增量集成中,错误通常要么是在新的组件中,要么是位于新组件和系统之间的连接中。
  • 及早在项目里取得系统级的成果;
  • 改善对进度的监控;
  • 改善客户关系;
  • 更加充分地测试系统中的各个单元;
  • 能在更短的开发进度计划内建造出整个系统;

使用阶段式集成时,你无须安排项目中个组件的构建顺序。但是使用增量集成时,就得仔细计划了。集成顺序的策略有多种多样的形状和规模,没有哪一种对所有情况而言都是最佳的。最佳集成步骤随项目不同而变化,最佳解决方案总是为了满足特定项目的特定需求而制定的。总的来说有如下一些集成策略:

  • 自顶向下集成;
  • 自底向上集成;
  • 三明治集成;
  • 风险导向的集成;
  • 功能导向的集成;
  • T-型集成;

这些集成策略就像软件设计方法一样,更多的是启发而非算法。请不要教条的遵循,而应该为特定项目剪裁一套独一无二的策略。

无论你选用哪种集成策略,daily build 和冒烟测试都是软件集成的好方法。每天都将各个(源)文件编译,链接并组合为一个可执行程序,然后对这个程序进行冒烟测试,既执行一种相对简单的检查,看看产品在运行时是否“冒烟”。它有若干的优点:降低了低质量的风险,通过每天对所有代码进行冒烟测试,可以防止质量问题遍布(占领)整个项目;便于诊断缺陷;提高士气,看到产品的工作成果能极大地提高士气。daily build 有规则地将工作均匀分散在项目的整个生命周期中,项目的开发团队自始至终对工作的速度有了更准确的图景。下面是使用 daily build 的一些详情:

  • 每日构建;最关键的部分是“daily”,可以把 daily build 视为项目的脉搏。
  • 检查失败的 build;
  • 每天进行冒烟测试;
  • 让冒烟测试与时俱进;
  • 将 daily build 和冒烟测试自动化;
  • 成立 build 小组;
  • 仅当有意义时,才将修订(revisions)加入 build 中;
  • 要求开发人员在把他的代码添加到系统之前,进行冒烟测试;
  • 为即将添加到 build 的代码准备一块暂存区;
  • 惩罚破坏 build 的人;
  • 在早上发布 build;
  • 即使有压力,也要进行 daily build 和冒烟测试;

本章要点:

  • 构建的先后次序和集成的步骤会影响设计,编码,测试各类的顺序;
  • 一个经过充分思考的集成顺序能减少测试的工作量,并使调试变容易;
  • 增量集成有若干变形,而且———除非项目是微不足道的———任何一种形式的增量集成都比阶段式集成好。
  • 针对每个特定的项目,最佳的集成步骤通常是自顶而下,自底而上,风险导向及其他集成方法的某种组合。T-型集成和竖直分块集成通常都能工作得很好。
  • daily build 能减少集成的问题,提升开发人员的士气,并提供非常有用的项目管理信息。

编程工具

现代化的编程工具减少了构建所需的时间。使用最前沿的工具集———并熟悉你所用的工具———能使生产力增加 50%还不止。20%的工具往往占据了 80%的工具使用量。如果你错过了某款更有用的工具,那么你就是错过了一种原本可能大量使用的东西。一个程序员可能工作了许多年,但也没有发现并使用某些最有价值的工具。本章的任务就是纵览目前可用的工具,看看你有没有忽视了某些可能非常有用的工具。
。。。许多工具。
每个新工具开始证明它对生产率有增益的时候,某些鼓吹者就会将这些增益外推至无穷大,设想这些增益最终能“消除对编程的需求”。但是无论如何,一旦了解了这些基本工具的概念,获得更大的增益的办法就是去除一些偶然性的困难,消除这些偶然性的困难并不能从本质上提高生产率。那些更强大的工具并不像它们宣称的那样能“消除编程”,更多的是改变了编程的方法。出现这一对抗性态势的原因在于,就本质而言,编程从根本上说就是困难的———即使有好的工具支援。无论能用到哪些工具,程序员都必须与凌乱的真实世界较力;我们须得严密地思考前后次序,依赖关系,异常情况;而且我们还要与无法说清楚自己想法的最终用户交往。我们始终要应对连接到其他软件或硬件的定义不清的接口,还要解决规章制度,业务规则以及其他复杂性之源,这些复杂性来自计算机编程之外的世界。始终需要人来填补真实世界里需要解决的问题和准备用来解决问题的计算机之间的鸿沟。这些人将会被称做程序员,无论他是以汇编语言操控机器寄存器,还是用 VB 操控对话框。只要有计算机,就需要能告诉计算机该去做什么的人,这一活动将会被称做编程。

本章要点:

  • 程序员有时会在长达数年的时间里忽视某些最强大的工具,之后才发现并使用之。
  • 好的工具能让你的日子过得安逸得多。
  • 下面这些工具已经可用了:编辑,分析代码质量,重构,版本控制,除错,测试,代码调整。
  • 你能打造许多自己用的专用工具。
  • 好的工具能减少软件开发中最单调乏味的工作的量,但它不能消除对“编程”的需要,虽然它会持续地重塑“编程”的含义。

👐 The End 🎉

🏠下一篇《代码大全》阅读笔记之五:代码改善 

👇 💬