我们一起来读书吧 关注:111贴子:1,393
  • 0回复贴,共1

第一章对于软件工程是什么

只看楼主收藏回复

在序言中软件工程是随时间变化的编程"软件工程 "不仅包括编写代码的行为,还包括一个组织用来长期构建和维护代码的所有工具和流程。一个软件组织可以采用哪些做法来使其代码长期保持最佳价值?工程师们如何才能使代码库更具有可持续性,并使软件工程学科本身更加严格?我们没有这些问题的最终答案,但我们希望谷歌在过去20年的集体经验能够为寻找这些答案的提供可能。本书强调了三个基本原则,我们认为软件组织在设计、架构和编写代码时应该牢记这些原则: 时间和变化代码如何在其生命周期内进行适配。 规模和增长一个组织如何适应它的发展过程。 权衡和成本一个组织如何根据时间和变化以及规模和增长的经验教训做出决策。当然这也是第一章将要阐述的理论。第一章分为了三部分。第一部分讲时间与变化第二部分讲规模与效率第三部分讲权衡和成本第一部分:时间与变化短期目标与长期目标所产生的代码是不一样的。对于短期目标的代码,完成功能为第一目标,而长期目标的代码是有重构以及长期维护的,方便后来者或其他人更轻松的工作。比如说项目中的质量管理再解crash的过程中,crash率是我们关注的第一个目标,短期目标是解决crash,但长期目标不是,优化代码效率,这就涉及到是用数据库或是缓存的过程。另一个,随时间变化的不一定是代码,也有可能是crash, 每一个迭代,crash都是变化的,有些是新增长的,有些是旧的。对于我们的目标是不是也是变化的呢。短期编程与生成预期生命周期更长的代码有何不同?随着时间的推移,我们需要更多地意识到“正常工作”和“可维护”之间的区别。识别这些问题没有完美的解决方案。这是不幸的,因为保持软件的长期可维护性是一场持久战海勒姆定律*当一个 API 有足够多的用户的时候,在约定中你承诺的什么都无所谓,所有在你系统里面被观察到的行为都会被一些用户直接依赖。*它指的是: “当你依赖于一个API 的时候,你实际上也依赖于这个API 的实现细节。” 换句话说,即使一个API 已经被定义和文档化了,但由于实现的方式可能存在多种选择,所以你在使用这个API 的时候也要考虑到其实现的细节,而不仅仅是其所声明的功能海勒姆定律代表了一种实践知识,即使有最好的规划、最好的工程师和可靠的代码评审实践,我们也不能假设完全遵守已发布的契约或最佳实践。作为API所有者,通过明确地接口约定,你将获得一定的灵活性和自由度,但在实践中,给定更改的复杂性和难度还取决于用户对你的API的一些可观察行为的有用程度。如果用户不能依赖这些东西,那么你的API将很容易更改。如果有足够的时间和足够的用户,即使是最无害的变更也会破坏某些东西;你对变更价值的分析必须包含调查、识别和解决这些缺陷的难度。没有对可持续性的长期项目进行投入是存在巨大风险。我们必须能够应对这些问题,并利用好机会,无论它们是否直接影响我们,或者仅仅表现为我们所建立的技术的过渡性封闭中。变化本质上不是好事。我们不应该仅仅为了改变而改变。但我们确实需要有能力改变。如果我们考虑到最终的必要性,我们也应该考虑是否加大投入使这种能力变得简单易用(成本更低)。正如每个系统管理员都知道的那样,从理论上知道你可以从磁带恢复是一回事,在实践中确切地知道如何进行恢复以及在必要时需要花费多少钱是另一回事。实践和专业知识是效率和可靠性的重要驱动力。第二部分:规模和效率不可扩展的策略如何定义不可扩展策略:最常见的情况是,可以通过考虑施加在单个设计并想象组织规模扩大10倍或100倍。当我们的规模增大10倍时,我们会增加10倍的工作量,而我们的工程师能跟得上吗?我们的工程师的工作量是否随着组织的规模而增长?工作是否随着代码库的大小而变多?如果这两种情况都是真实的,我们是否有机制来自动化或优化这项工作?如果没有,我们就有扩展问题。开发了一个新的小组件。决定是每个人都应该使用新的,停止使用旧的。为了激发这一点,项目负责人说:“我们将在8月15日删除旧的小组件;确保你已转换为新的小组件,这种方法可能适用于小型软件项目。规模化策略随着公司的发展,什么样的策略会带来更低的成本?或者,最好是,随着组织化的发展,我们可以制定什么样的策略来提供超高的价值?我们发现,随着组织规模的扩大,专业知识和共享交流论坛提供了巨大的价值。随着工程师在共享论坛中讨论和回答问题,知识往往会传播。新的专家人数不断增加。如果你有100名工程师编写Java,那么一位愿意回答问题的友好且乐于助人的Java专家很快就会产生一个数百名工程师编写更好的Java代码。知识是病毒,专家是载体,扫除工程师常见的绊脚石是非常有价值的编译器升级:你更改基础设施的频率越高,更改就越容易。我们发现,在大多数情况下,当代码作为编译器升级的一部分进行更新时,它会变得没那么脆弱,将来更容易升级。大多数代码都经历了几次升级的一个系统中,它的停止取决于底层实现的细微差别。相反,它取决于语言或操作系统所保证的抽象。无论你升级的是什么,代码库的第一次升级都比以后的升级要复杂得多,甚至可以控制其他因素。左移:[图片]在提交之前通过静态分析和代码审查发现的bug要比投入生产的bug成本更低。在开发过程的早期提供高质量、可靠性和安全性的工具和实践是我们许多基础架构团队的共同目标。没有一个过程或工具是完美的,所以我们可以采取纵深防御的方法,希望尽早抓住图表左侧的缺陷第三部分权衡和成本:成本的定义:我们所说的成本是什么呢?我们这里不仅仅是指金钱。“成本”大致可以转化为努力的方向,可以包括以下任何或所有因素财务成本(如金钱)资源成本(如CPU时间)人员成本(例如,工作量)交易成本(例如,采取行动的成本是多少?)机会成本(例如,不采取行动的成本是多少?)社会成本(例如,这个选择将对整个社会产生什么影响?)权衡:当我们评估成本时,我们需要牢记之前列出的所有成本:一个组织的健康不仅仅是银行里是否有钱,还包括其成员是否感到有价值和有成就感。在软件等高度创新和利润丰厚的领域在工程设计中,财务成本通常不是限制因素,而人力资源是。保持工程师的快乐、专注和参与所带来的效率提升会成为主导因素,仅仅是因为专注力和生产力变化大,会有10-20%的差异很容易想象。第一点:记号笔:结论:优化无障碍头脑风暴要比防止有人拿着一堆记号笔走神重要得多。数据驱动中,如果没有数据。即使没有数据,也会有证据、先例和论据。做出好的工程决策就是权衡所有可用的输入,并就权衡做出明智的决策。有时,这些决策是基于本能或公认的最佳实践,但仅是一种假设之后,我们用尽了各种方法来衡量或估计真正的潜在成本。最后,工程团队的决策应该归结为几件事:我们这样做是因为我们必须这么做(法律要求、客户要求)。我们之所以这样做,是因为根据当前证据,这是我们当时能看到的最佳选择(由一些适当的决策者决策)。第二点:决策的输入对于有数据的支持(所有涉及的数量都是可测量的或至少可以预估的)我们是可以评估的,但是对于没有数据的支持(我们不知道这需要多少工作量”。有时甚至更模糊:如何衡量设计拙劣的API的工程成本?或产品导致的社会影响?)没有简单的答案。我们依靠经验、领导作风和先例来协商这些问题。第三点: 分布式构建我们需要重新认识系统的目标和约束以及我们的使用方式,确定最佳实践(小型依赖项、依赖项的机器管理),并为新生态系统的工具和维护提供资金。即使是相对简单的 "我们花美元购买计算资源以收回工程师时间 "的权衡,也会产生不可预见的下游影响。第四点:在时间和规模之间做决定与大多数软件工程决策一样,对于这种情况并没有一个一刀切的答案。如果你的项目生命周期很短,那么fork的风险较小。 如果有问题的分支被证明是范围有限的,那是有帮助的,同时也要避免分支那些可能跨越时间段或项目时间界限的接口(数据结构、序列化格式、网络协议)。一致性有很大的价值,但通用性也有其自身的成本,你往往可以通过做自己的事情来赢得胜利——如果你仔细做的话。第五点:重审决策,标记错误致力于数据驱动文化的一个不明显的好处是承认错误的能力和必要性相结合。在某个时候,将根据现有的数据做出决定——希望是基于准确的数据和仅有的几个假设,但隐含的是基于目前可用的数据。随着新数据的出现,环境的变化,或假设的不成了,可能会发现某个决策是错误的,或在当时是有意义的,但现在已经没有意义了。这对于一个长期存在的组织来说尤其重要:时间不仅会触发技术依赖和软件系统的变化,还会触发用于驱动决策的数据的变化。我们坚信数据能为决策提供信息,但我们也认识到数据会随着时间的推移而变化,新数据可能会出现。这意味着,本质上,在相关系统的生命周期内,需要不时地重新审视决策。对于长期项目而言,在做出初始决策后,有能力改变方向通常是至关重要的。更重要的是,这意味着决策者需要勇气承认错误。与人的直觉相反,勇于承认错误的领导人受更多的尊重小结:软件工程”与“编程”在维度上不同:编程是关于编写代码的。软件工程扩展了这一点,包括在代码的生命周期内对其进行维护。短期代码和长期代码的生命周期之间至少有100,000倍的系数。假设相同的最佳实践普遍适用于这一范围的两端是愚蠢的。在预期的代码生命周期内,当我们能够响应依赖关系、技术或产品需求的变化时,软件是可持续的。我们可能选择不改变事情,但我们需要有能力。海勒姆定律:当一个 API 有足够的用户的时候,在约定中你承诺的什么都无所谓,所有在你系统里面被观察到的行为都会被一些用户直接依赖。你的组织重复执行的每项任务都应在人力投入方面具有可扩展性(线性或更好)。策略是使流程可伸缩的好工具。流程效率低下和其他软件开发任务往往会慢慢扩大规模。小心煮青蛙的问题。当专业知识与规模经济相结合时,回报尤其丰厚。“因为我说过”是做事的可怕理由。数据驱动是一个良好的开端,但实际上,大多数决策都是基于数据、假设、先例和论据的混合。最好是客观数据占这些输入的大部分,但很少可能是全部。随着时间的推移,数据驱动意味着当数据发生变化时(或假设消除时),需要改变方向。错误或修订的计划不在表中。总结:本书讨论了所有这些主题:一个组织和一个程序员的策略,如何评估和改进你的最佳实践,以及用于可维护软件的工具和技术。谷歌一直在努力打造可持续的代码库和文化。我们不认为我们的方法是做事情的唯一正确方法,但它确实通过例子证明了它是可以做到的。我们希望它将提供一个有用的框架来思考一般问题:你如何维护你的代码,让它正常运行。


IP属地:北京来自iPhone客户端1楼2024-05-20 09:46回复