《Software Engineering at Google》 笔记 01:软件工程是什么?

软件工程可以被认为是 「随着时间推移而整合的编程」

本书强调了三个基本原则,我们认为软件组织在设计、架构和编写代码时应该牢记这些原则:

  • 时间和变化 ​代码如何展期生命周期内进行适配。

  • 规模和增长 ​一个组织如何适应它的发展过程。

  • 权衡和成本 ​一个组织如何根据时间和变化以及规模和增长的经验教训做出决策。 编程和软件工程之间有三个关键的区别:时间、规模和权衡取舍。

在一个软件工程项目中,工程师需要更多关注时间成本和需求变更。在软件工程中,我们需要更加关注规模和效率,无论是对我们生产的软件,还是对生产软件的组织。最后,作为软件工程师,我们被要求做出更复杂的决策,其结果风险更大,而且往往是基于对时间和规模增长的不确定性的预估。

了解时间对程序的影响的一种方法是思考「代码的预期生命周期是多少?」

  • 通常,周期短的代码不受时间的影响。对于一个只需要存活一个小时的程序,你不太可能考虑其适应基础库、操作系统(OS)、硬件或语言版本的新版本。这些短期系统实际上“只是”一个编程问题,就像在一个维度中压缩得足够扁的立方体是正方形一样。随着我们扩大时间维度,允许更长的生命周期,改变显得更加重要。在十年或更长的时间里,大多数程序依赖关系,无论是隐式的还是显式的,都可能发生变化。这一认识是我们区分软件工程和编程的根本原因。

  • 如果在软件的预期生命周期内,你能够对任何有价值的变化做出反应,无论是技术还是商业原因,那么你的项目是可持续的。重要的是,我们只关注能力——你可能因为缺乏价值或其他优先事项而选择不进行特定的升级。当你基本上无法对基础技术或产品方向的变化做出反应时,你就把高风险赌注押在希望这种变化永远不会变得至关重要。对于短期项目,这可能是一个安全的赌注。几十年后,情况可能并非如此。

另一种看待软件工程的方法是考虑规模。有多少人参与?随着时间的推移,他们在开发和维护中扮演什么角色?

团队协作带来了新的问题,但也提供了比任何单个程序员更多的潜力来产生有价值的系统。

软件工程与编程的不同之处在于需要做出的决策的复杂性及其风险。在软件工程中,我们经常被迫在几个路径之间做评估和权衡,有时风险很高,而且价值指标不完善。软件工程师或软件工程负责人的工作目标是实现组织、产品和开发工作流程的可持续性和管理扩展成本为目标。考虑到这些投入,评估你的权衡并做出理性的决定。有时,我们可能会推迟维护更改,甚至接受扩展性不好的策略,因为我们知道需要重新审视这些决策。这些决策应该是明确的和清晰的递延成本。

Hyrum’s Law 海勒姆定律:「当一个 API 有足够多的用户的时候,在约定中你承诺的什么都无所谓,所有在你系统里面被观察到的行为都会被一些用户直接依赖。」

对随时间变化和维护的讨论必须了解海勒姆定律,正如对效率或热力学的讨论必须注意熵一样。仅仅因为熵从不减少并不意味着我们不应该努力提高效率。在维护软件时,海勒姆定律会适用,但这并不意味着我们不能对它进行规划或试图更好地了解它。我们可以减轻它,但我们知道,它永远不可能被根除。 海勒姆定律代表了一种实践知识,即使有最好的规划、最好的工程师和可靠的代码评审实践,我们也不能假设完全遵守已发布的契约或最佳实践。作为 API 所有者,通过明确地接口约定,你将获得一定的灵活性和自由度,但在实践中,给定更改的复杂性和难度还取决于用户对你的 API 的一些可观察行为的有用程度。如果用户不能依赖这些东西,那么你的 API 将很容易更改。如果有足够的时间和足够的用户,即使是最无害的变更也会破坏某些东西;你对变更价值的分析必须包含调查、识别和解决这些缺陷的难度。

依赖其依赖性的脆弱和未发布特性的代码可能被描述为「黑客」或「聪明」遵循最佳实践并为未来规划的代码更可能被描述为「干净」和「可维护」。两者都有其目的,但你选择哪一个关键取决于所讨论代码的预期生命周期。我们常说,「如果『聪明』是一种恭维,那就是程序,如果『聪明』是一种指责,那就是软件工程。」

最初的设计可能完全符合逻辑,并遵循合理的最佳实践。只有在向后兼容的变化演变之后,新的、更有效的选择才变得重要。虽然没有犯错误,但随着时间的推移,变化仍然是有价值的。

我们的工程师的工作量是否随着组织的规模而增长?工作是否随着代码库的大小而变多?如果这两种情况都是真实的,我们是否有机制来自动化或优化这项工作?如果没有,我们就有扩展问题。 自动化(这样一个人就可以做到更多)、整合/一致性(这样低级别的更改影响有限的问题范围)和专业知识(以便少数人就可以做得更多)。

如果安全问题是在产品投入生产后才发现的,修复的成本就非常高。如果在部署到生产之前就发现了安全问题,那也需要花费大量的工作来检测和修复问题,但成本更低些。如果你能够在最初的开发之前发现安全问题,将缺陷提交到版本控制就被发现,修复的成本更低:他们已经了解该功能;根据新的安全约束规范进行开发,要比提交代码后再让其他人分类标识并修复它更简单。

我们看到的一个普遍真理是,在开发人员的工作流程中发现的问题,通常可以降低成本。考虑开发人员工作流程的时间表,从左到右,从概念和设计开始,通过实施、评审、测试、提交、金丝雀和最终的生产部署来进行。在此时间线之前,将问题发现转移到“左侧”会使修问题解决成本更低

“成本”大致可以转化为努力的方向,可以包括以下任何或所有因素:

  • 财务成本(如金钱)

  • 资源成本(如CPU时间)

  • 人员成本(例如,工作量)

  • 交易成本(例如,采取行动的成本是多少?)

  • 机会成本(例如,不采取行动的成本是多少?)

  • 社会成本(例如,这个选择将对整个社会产生什么影响?)

工程团队的决策应该归结为几件事:我们这样做是因为我们必须这么做(法律要求、客户要求)。我们之所以这样做,是因为根据当前证据,这是我们当时能看到的最佳选择(由一些适当的决策者决策)。

杰文斯悖论(Jevons Paradox):「一种资源的消耗可能会随着使用效率的提高而增加。」

时间不仅会触发技术依赖和软件系统的变化,还会触发用于驱动决策的数据的变化。

本质上,在相关系统的生命周期内,需要不时地重新审视决策。对于长期项目而言,在做出初始决策后,有能力改变方向通常是至关重要的。更重要的是,这意味着决策者需要勇气承认错误。与人的本能相反,勇于承认错误的领导人受更多的尊重。

我们认为,区分相关但不同的术语「编程」和「软件工程」是很重要的。这种差异很大程度上源于随着时间的推移对代码的管理、时间对规模的影响以及面对这些想法的决策。编程是产生代码的直接行为。软件工程是一组策略、实践和工具,这些策略、实践和工具是使代码在需要使用的时间内发挥作用,并允许整个团队的协作。

Subscribe to IGAOZP
Receive the latest updates directly to your inbox.
Mint this entry as an NFT to add it to your collection.
Verification
This entry has been permanently stored onchain and signed by its creator.