我们程序员应该是工程师

我是开发人员还是程序员? 也许是代码忍者或黑客? 我在LinkedIn上的个人资料大胆地宣称我是一名"技术专家",我当时认为这是一个很酷的职业头衔,而且可能不会自动让我担任任何特定角色。 在我的职业生涯中,我花更多的时间编写代码和维护系统的时间,使我更加相信我应该依靠从工程学科的经典根源中汲取的原理和哲学。

我们程序员应该是工程师

> Photo by Dan Meyers on Unsplash

就像以前我们心爱的NYC地铁运输工程师一样,他们不会设计一个系统来关闭整个线路的电源,以替换第三部分的单个部分,软件开发人员负责创建系统,可以适应所需的更改并维持维护。如果我们使用技术不可知性和可衡量的术语(例如耦合程度)来描述风险并衡量技术债务偿还期内的风险降低,则企业领导者将我们视为专业工程师而不是忍者黑客的机会将会增加。与不存在使类或函数安全的耦合度的绝对规则几乎相同,不能保证我们经过仔细衡量的风险分析将引起关注,但我们应增强这种思想和分析的能力。它将鼓励人们理解其他未知的风险,并且随着时间的流逝,将导致更易于维护和适应的系统。对于那些由程序员转为工程师的程序员,您将更好地准备亲自接受对我们社会最终依赖的系统的影响的责任。

我已经看到"爆炸半径"一词越来越流行,主要是围绕安全性和网络体系结构(例如,每个服务模型一个云子帐户),除了它固有的暴力色彩外,我喜欢它。 当发生意外事件时,您的组织中有多少需要做出反应? 好吧,我答应过一些可衡量的项目,我认为有两个密切相关的概念将对您有所帮助:我们的好朋友传出和传出耦合。 对于我喜欢他们的东西,我总是混淆他们的定义:

传入(形容词):向内或朝某物进行或向某物进行(以循环系统的心脏为例,静脉将血液返回心脏)。

传出的(形容词):从某物向外或远离某物进行传导或传导(以循环系统的心脏为例,动脉将血液从心脏带走)。

传入耦合可以通过直接了解组件的其他类别,功能或外部过程的数量来衡量。换句话说,此功能有几个客户?更重要的是,他们是谁?我们有能力影响他们吗?如果它们是我可以轻松重构的存储库中的其他代码,那么我可以选择它们是否以及何时需要更改。如果他们暴露在我所有付费客户使用的外部Web服务API中,那么我无法控制他们何时选择请求更改。相反,传入的耦合也会受到引入组件的任何更改的影响。我们可以使用API​​版本控制来防止引入破坏性的界面更改(例如,新的强制性输入),但这不能保护客户免受故意改正错误的错误修复或更改实现(例如,缓存或不缓存)的影响。通常,传入耦合的增加之后,所需测试用例的总数将增加。

传出耦合可以通过组件知道的其他类,函数或外部进程的数量来衡量,并且您可能会想像,我们只是在发挥另一面作用。 该组件可能会受到其任何依赖项所做的任何更改,并且需要针对一个依赖项与其他依赖项的交互方式来协调所请求或要求的更改。 我们可以使用策略模式和依赖项注入来简化其中的一些需求,但是无论如何,一旦单个类的依赖项增长到超过四到五个,就很难在心理上合理化其行为。 随着传出耦合数量的增加,继承变化的可能性和频率也会增加。 通常,传出耦合的增加之后,将是适当地对组件进行单元测试所需的模拟和设置代码的数量的增加。

有许多编程语言的工具可以为您评估这些情况。这些耦合中的每一个都有一个更隐蔽的子类型,这种子类型不太容易测量,我将其称为隐式传递耦合。我认为这在静态类型的语言中可能不太常见,但是一个很好的例子是使用和突变由一个函数创建的键-值对字典,并传递给第二个以进行后续突变,然后传递给第三个消费。尽管无法直接测量,但第一个功能的字典实例化将绝对影响第三个功能的使用它的能力,同样,第三个功能的需求变化可能会影响到第一个功能的实例化。添加第一个函数的实例化代码以用于传递给多个直接传入耦合的功能,然后将复杂度增加到可能创建无法减少的错误现象实例的程度。

例如,我的团队正在使用Amazon的DynamoDB缓存一些我们从交易处理期间使用的第三方托管服务中获取的数据。顺便说一句:我仍然发现DynamoDB的API是拜占庭,但实际上我很喜欢使用它。缓存从本质上引入了CAP定理的权衡,但是我们决定接受这种情况下缺乏一致性。为什么?因为经过与业务和客户团队成员的讨论,我们了解到该数据通常仅在系统配置期间设置,并且一旦交易开始就不会更改,因此认为一个简单的24小时刷新周期就足够了。问题解决了……直到我们第一次真正开始设置客户。我们忘记了配置和测试系统的人员也是利益相关者,他们的周期时间比他们要建立的现实世界要快得多。他们将重用实体,更改映射,解决拼写错误,并循环进行通常一天可能存在几个月的设置。尽管这些人不是我们系统这些功能的主要利益相关者,但在我们开始满足实际业务需求之前,他们对配置环境的总体认可是绝对必要的。

如果我们想完全跳过缓存,我们系统中的爆炸半径是什么样的? 只对某些客户或某些基于请求标头的交易怎么办? 最好的情况是,我们创建缓存接口的新实现,并在factory / build函数中创建一两个IF语句,以为我们的业务交易组件提供配置。 最坏的情况是,我们将交易处理代码与直接的DynamoDB调用混为一谈,并且我们需要对其中的每一个进行更改,每次都有可能给以前无法正常测试的业务逻辑引入错误, 因为缓存命中和丢失几乎始终是流控制指标。

几年前,我有一位特别重要的经理和领导者有机会与他合作,如果有人读过这篇文章,便会确切地知道自己是谁,他试图向我解释说,那些为自己的混乱难受的罪魁祸首的软件开发人员将以失败告终。天。如今,编写不安全或明显破损的代码的责任通常在公司层面上承担,即使进行了内部根本原因分析,我也很少看到有人直接参与构建问题来自愿解释他们的参与。确实,这在很大程度上是很有意义的。交付损坏的产品需要一个以上的人,并且往往是多年来的众多错误和缺乏投资的结果,造成了不安全的环境,使这种损坏的产品一开始就成为可能。当单元测试覆盖率达到50%,不存在针对部署环境的集成测试并且没有连续交付管道时,您真的可以让开发人员对引入回归负责吗?

作为当时相对不成熟的开发人员,个人对我的工作负责的想法并不是我所接受的。作为现在不那么成熟的软件工程师,我看到了最小化测试覆盖范围和缓慢降低系统可靠性的局面,这是需要管理的现实。我将举一个极端的例子:就像我想象纽约地铁系统的工程师仍在计划升级和维护工作的方式一样,我仍然有义务在风景如画的技术领域中运用专业知识。这样做需要在可能不愿听到的人的业务决策结果上显示一些严峻的现实,并且通常最好使用一些易于理解的指标来实现,以帮助传达好系统与差系统之间的差异。在软件中,有大量的度量标准,模式和理念试图表明我们是系统的良好管家,还是我们正在缓慢地扎根针脚以创建一堆难以理解的依赖关系和无数逻辑代码路径。

我之前提到的同一位经理不仅宣讲了即将到来的游戏末日,而且还提供了一种有效的解决方法,以应对如此众多的测量范围可能引起的分析瘫痪之灾。该建议是,在构建系统,服务,子系统,组件,模块,类或功能时要把握的最重要的概念就是所解决问题的易变性。这不是可以像厘米或公斤那样普遍测量的东西,但我保证有两件事:(1)我们将在片刻内完成可测量的项目,(2)您可以轻松地发明一个任意系统来比较风险波动性和复杂性(我正在看着您,敏捷的故事要点),只要您了解所涉业务的性质。这就是我们的工程师需要在此处开始与我们的业务沟通这些概念的地方领导者了解引入某些更改的可能性,然后我们可以运行一些思维模型来适应这些更改。


(本文翻译自David Jetter的文章《We Programmers should be Engineers》,参考:https://medium.com/swlh/we-programmers-should-be-engineers-e40f774098)


分享到:


相關文章: