AI 年度盘点与2025发展趋势展望,50+案例解析亮相AICon 了解详情
写点什么

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

作者: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:426611

评论 1 条评论

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

免费的苹果手机投屏到电脑mac软件AIrserver7

茶色酒

AIrserver7

2023-02-11:给你两个整数 m 和 n 。构造一个 m x n 的网格,其中每个单元格最开始是白色, 请你用 红、绿、蓝 三种颜色为每个单元格涂色。所有单元格都需要被涂色, 涂色方案需要满足:

福大大架构师每日一题

算法 rust 福大大

springboot自动配置原理

喝水不抬头

架构训练营 - 模块四作业

Sam

架构实战营

软件测试/测试开发 | Web测试方法与技术实战演练

测试人

软件测试 自动化测试 测试开发 Web自动化测试

大家心心念念的RocketMQ5.x入门手册来喽

中间件兴趣圈

RocketMQ rocketmq5

如何做总架构师

agnostic

总架构

软件测试/测试开发 | Web自动化之Selenium安装

测试人

软件测试 自动化测试 测试开发 Web自动化测试 selenium

使用开源实时监控系统 HertzBeat 5分钟搞定对 Mysql 数据库监控告警

TanCloud探云

Java 数据库 GitHub 开源 数据库监控

2023年金三银四必问的 1400 道 Java 面试题及答案整理,让你面试少走99%的弯路!

架构师之道

编程 程序员 java面试

Python 发展趋势:与 Rust 深度融合、更易于编写 Web 应用

Python猫

Python

极客时间架构训练营模块七-王者荣耀商城异地多活架构设计

张Dave

NodeJS 实战系列:DevOps 尚未解决的问题

光毅

DevOps nodejs

怎样做新人培训

Joseph295

四点原因,Zoom裁员15%,视频会议甜蜜期结束

B Impact

【SpringBoot】SpringBoot常用注解

No8g攻城狮

Spring Boot 2 #面试

湖仓一体电商项目(二十):业务实现之编写写入DM层业务代码

Lansonli

湖仓一体电商项目

Kubernetes环境cert-manager部署与应用

Galen Suen

Kubernetes TLS cert-manager Certificate Let's Encrypt

设计模式-值类型与引用类型、深拷贝与浅拷贝、原型模式详解

C++后台开发

数据结构 设计模式 后端开发 Linux服务器开发 C++开发

软件测试/测试开发 | Web测试方法与技术之CSS讲解

测试人

软件测试 自动化测试 测试开发 Web自动化测试 web测试

状态机设计举例

timerring

FPGA

ChatGPT十问十答 | 图解ChatGPT

涛哥 数字产品和业务架构

人工智能 ChatGPT

New Bing 内测,革搜索的命

冯骐

openai GPT ChatGPT New Bing 对话模型

贝叶斯AB测试

俞凡

最佳实践 ab测试

Camtasia2023Mac/win电脑屏幕录制编辑软件

茶色酒

Camtasia2023

Dromara HertzBeat 开源社区新晋两位 Committer

TanCloud探云

Java GitHub 开源 后端 开源社区

运维训练营第十三课作业

好吃不贵

支撑MVP,架构师需要做什么

agnostic

MVP

开源ChatGPT要来了;软件2.0智能革命;GLM、Diffusion模型大加速

OneFlow

人工智能 深度学习

2023最新Python阅读书籍推荐

kcodez

Python

ThreadLocal源码分析及避坑指南

喝水不抬头

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