写点什么

从整体组织的角度看待技术债,避免技术破产

作者:Einar Høst

  • 2022-01-12
  • 本文字数:3689 字

    阅读完需:约 12 分钟

从整体组织的角度看待技术债,避免技术破产

随着软件系统的不断发展,它们往往会变得不那么灵活,也更难使用。我们通常把这种情况归咎于猖獗的“技术债”,但却没有讨论导致技术债的原因。


笨拙的编程不是造成技术债的主要原因,因此我们不能指望仅依靠更熟练的编程就能解决技术债。相反,技术债是沟通不畅的三阶效应。这是缺乏适当抽象的症状,而这反过来又源于对问题领域建模的不足。这意味着没有进行充分的沟通;为解决歧义并做出明智的权衡而进行的讨论和决策已经被掩盖了。


我们所观察到并被标记为“技术债”的是这一功能失调开发过程的副产品:代码中缺乏解决方案的具体化。为了解决不断积累的技术债问题,我们需要修复这个被破坏的过程。

造成技术债的主要原因

技术债的比喻是由 Ward Cunningham 引入的,它用来描述开发人员有意识地决定将具有已知限制的代码交付到生产环境中的过程。提前交付的目的有两个:快速进入市场,以及实现从生产到进一步开发和改进的反馈循环。它很快就流行起来了,因为它允许开发人员通过技术解决方案将“看不见的”问题传达给管理层和其他利益相关方。


然而,在技术债这个比喻变得广泛而流行的过程中,它的含义也被稀释了。在生产环境中运行的任何有局限性或者存在质量问题的代码都可能会被贴上技术债的标签。这是不幸的,因为它破坏了比喻的实用性和丰富性。很多被认为是技术债的东西都是随着时间的推移而无意中产生的,并且没有明确的偿还策略。

技术破产

令人遗憾的是,技术债这个比喻的含义已经被以这种方式稀释了,但是在语言中,就像在生活中一般,实用主义胜过意图。这就是我们的处境:所谓的“技术债”在很大程度上只是正常软件开发的副产品。当然,没有人希望代码问题以这种方式累积,因此问题就变成了:为什么我们似乎总会无意中导致如此多的技术债呢?我们进行软件开发的方式是什么样的,它为什么会导致这种我们不想要的结果呢?


这些问题很重要,因为如果我们陷入了技术债,那么我们就会在技术上资不抵债并在技术上破产。事实上,这似乎是许多软件开发工作中正在发生的事情。Ward Cunningham 指出,“整个工程组织可能会因为未整合实施的债务负担而停滞不前”。这种停滞就是技术性的破产。这意味着你的组织无法再继续前进了。


对软件进行合理的变更需要花费不合理的时间来实现。质量问题就成了永久性的问题;如果没有引入新 bug 的机会,就无法修复 bug,从而导致问题之间的某种共振。

实践中的技术债

如果我们要理解无意中导致技术债积累的力量,我们必须要看下代码,并看看“技术债”是如何体现出来的。


我的观察结果是,代码中往往有很多的“如果”和“但是”,但很少能传达意图并帮助理解。我的意思是,代码中有许多 ifelse 分支,还有大量的布尔标志来控制这些分支之间的执行流。缺少的是能理解这一切的有用抽象和边界。这使得隔离出与单个功能相关的代码变得十分困难,因为该功能的代码在任何意义上(或明显意义上)来说都不是孤立的。很难预测变更后的影响,因为变更某个布尔标志可能会在整个代码库中产生连锁反应。


当我们对我们试图用软件来解决的问题有了一个不成熟且不充分的心智模型时,代码的结果是这样的。软件肮脏的秘密在于,我们可以对我们无法清晰表达的问题实施解决方案。如果我们的软件是“错误的”,那么正确的行为总是只需一个 if 分支。我们只需要用某种方法来注入正确的标志,就可以在执行流中转向正确的行为,而非错误的那个。在实现中,我们确实可以通过使用 if 分支来补偿我们糟糕的领域模型。但这正是我们因疏忽而造成技术债问题的原因:随着时间的推移,我们把自己逼到了绝境。它使软件变得难以理解了——技术破产。


在不破坏现有功能的情况下,我们不能再以这种方式添加功能了。

修复模式,而不是代码

如果我们的头脑中没有正确的概念,就很难写出简单而又精确的代码。我们不仅需要这些概念来构建我们的解决方案,而且需要在一开始时就能清楚地思考这个问题。只要我们缺乏正确的概念,我们的思维以及我们与他人的交流就会变得笨拙而迂回。想象一下,在不知道狗(dog)这个单词或者甚至不知道动物(animal)这个单词的情况下,试图给某人讲一个关于狗的故事。“它是一种急切的、摇尾巴的、有四条腿的生物”。这听起来很傻,但我在项目中多次遇到这种情况。


在我参与的一个项目中,我们在处理信用卡模块时遇到了困难。代码复杂且难以理解,而且每当我们谈到这个模块时,我们的讨论效率就会变得很低且令人沮丧,但我们无法真正弄清楚原因。直到我们意识到我们缺乏一个概念来描述信用卡是如何与信用卡交易相关联的(一种“关联机制”),才使得一切变得合理。突然间,我们的头脑清醒了,我们的讨论也清晰了,而且我们可以非常直接地实施它。我们删除了我们之前所编写的所有笨拙的代码,并代之以一些简单易懂的代码。


这一经验为处理复杂代码提供了一种启发式的方法;为那些往往会在一段时间后被贴上“技术债”标签的代码寻找缺失或尴尬的概念。在团队的设计讨论中寻找受挫的模式。可能是领域想告诉你一些事情。试图“修复”没有正确概念的代码很可能会失败,因为错误的概念没有优雅或干净的组织。


我想说的是,我们的问题是源于我们试图用软件来解决的问题具有不成熟且不充分的心智模型。对于团队协作开发的软件来说(也就是大多数的软件),该心智模型需要在软件开发人员之间共享。不然的话,毫无疑问,不一致和极端情况就会咬着我们不放。如果我们没有就问题和建议的解决方案达成一致的话,那么我们应该期望看到这些对齐失败的后果能在代码中体现出来。我们也确实是如此。


开发一个足够丰富且灵活的共享心智模型的关键是沟通和协作。当软件被技术债压得喘不过气来时,这表明开发软件的组织可能需要查看其沟通和协作模式了。

业务与 IT 之间的分歧

Ward Cunningham 发明了“技术债”这个比喻,使得开发人员能够与业务人员交流一些前者看得见、后者看不见的东西;虽然我们现在发布的代码满足了业务需求,但我们在这方面做得太多了。这样做让我们失去了平衡,我们需要花一些时间来恢复这种平衡。否则我们最终会摔倒,很难再爬起来。但从某种意义上说,这是一个很容易解决的问题:可以说,慷慨地给开发人员一点时间,让他们时不时地打扫一下自己的房子。业务人员所需要的只是一点等待开发人员迎头赶上的耐心。


不幸的是,我认为这不会奏效。如果我的观点是正确的,即我们所说的技术债实际上是源于业务领域建模的不足,并且最终是由沟通和协作问题引起的,那么这不是开发人员可以自行解决的问题。事实上,认为开发人员能够并且应该单独处理技术债是导致技术债的另种思维症状。对于开发人员和业务人员来说,这都是一个令人不安的观点。对于业务人员来说,将技术债视为 IT 需要处理的事情是很方便的,而对于开发人员来说,认为他们所需要的只是一点时间来把事情做好就更舒服了。但如果我们要解决技术债的根本原因,这是一种我们无法承受的便利和安慰。

减少技术债

对于一个发现自己正接近技术破产的软件组织来说,主要的问题不是债务本身,而是该组织在其当前状态下无意中产生了大量难以管理的复杂代码。如果我们继续以与以前相同的速度产生新的债务,那么削减已发生的债务几乎没有任何用处。试图理清濒临破产的代码可能是非常昂贵、耗时和冒险的。通常,最好是找到某种方法,用其他以更健康的方式生成的代码来替换债务繁重的代码。我能给出的最好的建议是尽量减少我们目前的债务,也就是说,首先要减少我们必须要减少的技术债。


随着时间的推移,减少我们所谓的“技术债”的最佳方法是解决根本原因,那就是我们如何共同协作的方式。改变软件组织的文化可能很困难。自上而下的举措往往会遇到困难,因为它们无法解决实地出现的问题。也许最好的自上而下的举措是给那些处于底层的人留出余地和自主权,因为我相信自下而上是有可能带来积极改变的。


我的经验是,作为一个团队进行软件开发(即集成编程)不仅可以更快地为问题提供更好的设计解决方案,而且还可以创造一种向更开放、更具同理心和更坦诚的沟通文化的转变。这反过来意味着,随着时间的推移,进行集成编程的团队不太可能会陷入技术债的泥潭中。此外,在经历了团队内部沟通的改善之后,团队成员也不太可能适应跨团队边界或组织中不同角色的人员之间的沟通不畅。如果这是真的,那么团队合作可以对组织的沟通模式产生积极的连锁反应。

结论

在软件行业中,无意中不断积累不受控制的技术债是一种普遍现象。造成这种趋势的根本原因是我们的沟通模式不够完善。这导致了心智模型的不成熟,开发人员通过堆积布尔标志和分支控制流来近似解决表达和理解欠佳的问题。


随着时间的推移,以这种方式构建的软件变得难以理解。打破这种趋势的方法是改变我们构建软件的方式:通过更好的协作和交流。正在集成的工作可能会朝着正确方向迈出一大步,因为它将协作和沟通置于软件开发的核心了。

作者介绍

Einar W. Høst 是挪威公共广播公司 NRK 的软件开发人员,在该公司,他帮助建立了电视流媒体服务。他的主要兴趣是领域建模、API 设计和计算机编程。他拥有奥斯陆大学计算机科学博士学位。你可以在推特上@einarwh找到他,或者读他的博客


原文链接:


https://www.infoq.com/articles/avoiding-technical-bankruptcy/

2022-01-12 09:426633

评论 1 条评论

发布
用户头像
不知道翻译的问题还是描述的问题,总感觉磕磕绊绊,不顺畅。
2022-01-20 10:08
回复
没有更多了
发现更多内容

OceanBase 第六期技术征文活动|小鱼还能“更快”吗?你来试试

OceanBase 数据库

数据库 oceanbase

k8s 探测方法总结

Geek_f24c45

#k8s

FL Studio编曲2023最新水果中文版本功能介绍

茶色酒

FL Studio 21

写入性能:TDengine 最高达到 InfluxDB 的 10.3 倍,TimeScaleDB 的 6.74 倍

TDengine

大数据 tdengine 性能测试 时序数据库 国产数据库

OceanBase 4.0 解读:全链路追踪要解决什么问题?从一条慢SQL说起

OceanBase 数据库

数据库 oceanbase

程序调试利器——GDB使用指南

京东科技开发者

c++ debug gdb 企业号 3 月 PK 榜 程序检测

走进RocketMQ(四)高性能网络通信

白裤

Java RocketMQ io RocketMQ网络通信

更人性化的无阈值监控不再为无效告警烦恼

观测云

运维 可观测性 监控告警 观测云 可观测性用观测云

「资源广场」上线|以开发者为中心,打造开放资源共享平台

Jianmu

jenkins CI/CD 镜像仓库 容器镜像 建木

数据基础设施 NFTScan 新增支持 Gnosis 网络

NFT Research

NFT 区块链、

打造成熟产品矩阵,瓴羊Quick BI数据可视化获认可

小偏执o

详解基于 Celestia、Eclipse 构建的首个Layer3 链 Nautilus Chain

威廉META

开源即时通讯IM框架 MobileIMSDK:快速入门

JackJiang

网络编程 即时通讯 IM

A/B实验避坑指南:为什么不建议开AABB实验

字节跳动数据平台

大数据 云服务 数据产品 AB testing实战

详细剖析|袋鼠云数栈前端框架Antd 3.x 升级 4.x 的踩坑之路

袋鼠云数栈

前端‘’

CDR2023下载安装图文教程coreldraw23

茶色酒

CorelDraw2023

详解基于 Celestia、Eclipse 构建的首个Layer3 链 Nautilus Chain

股市老人

敏捷开发工具leangoo时间线视图管理项目

顿顿顿

Scrum 敏捷开发 甘特图 敏捷开发管理 时间线

类加载机制

Apache IoTDB

IoTDB

Apache Flink 1.16 功能解读

Apache Flink

大数据 flink 实时计算

Mac应用程序无法打开提示不明开发者或文件损坏的处理方法

理理

Mac软件打不开

Deploy Workshop|DIY部署环境,让OceanBase跑起来

OceanBase 数据库

数据库 oceanbase

mac无损音乐播放器软件:Audirvana使用设置技巧

理理

Audirvana

【云图说】 | 第268期 初识开天企业工作台MSSE

华为云开发者联盟

云计算 后端 华为云 华为云开发者联盟 企业号 3 月 PK 榜

你也能成为“黑客”高手——趣谈Linux Shell编程语言

京东科技开发者

Linux 系统架构 操作系统 开发 企业号 3 月 PK 榜

详解基于 Celestia、Eclipse 构建的首个Layer3 链 Nautilus Chain

鳄鱼视界

初识VUE响应式原理

京东科技开发者

Vue 系统架构 Proxy 企业号 3 月 PK 榜 响应系统

面对“中国式报表”需求, 瓴羊 Quick BI的电子表格优于Tableau?

夏日星河

如何使用 Apache IoTDB 中的 UDF

Apache IoTDB

UDF IoTDB

从整体组织的角度看待技术债,避免技术破产_文化 & 方法_InfoQ精选文章