遇什么结构 我常遇到的三种技术债务:代码、数据和架构

栏目:教育 2021-09-16 01:30:11
分享到:

作者|尼古拉斯·查里埃

翻译|王强

规划|小旭

本文原发表于作者个人博客,经授权由InfoQ中文网站翻译分享。

在软件工程中,我们经常面临各种权衡,从长远来看,用最好的技术选择来换取短期的速度提升。借用金融术语的一种常见方式是称之为承担技术债务。

在本文中,我不会处理偶然和有意的技术债务,也不会给出任何决策框架。都是独立的话题,要详细分析。

这篇文章是关于一个思维框架,我认为它可以应用于不同的团队、代码库和系统。我把技术债务分为三类:代码、数据和架构。现在我们将通过一些例子详细回顾这些类别。

一个

代码技术债务

这大概是最常见的一个,也是大家能想到的第一个。这种形式的债务是我们提交的次优代码。一些例子包括:

先复制粘贴一些代码,稍后再重新构建

写一个可以做任何事情的大函数

导入一个巨大的库,但仅用于一个小的功能需求

扩展函数签名以管理边缘条件

每个人可能都见过很多这样的代码:

代码技术债往往最容易被提及,因为在查看别人的代码或浏览代码库时,可以很容易地看到它们。它是三个类别中最“显眼”的。它也很容易修复,因为您可以通过测试和重构来打包您的逻辑,在一次代码更改中修复它,或者通过几次手术来处理它。不管用哪种方式修复,都要处理的是代码,所以这个技术债没有太大的负担去承担和偿还。很多时候,人们在谈论“技术债”的时候,其实是在思考这个分类。但我希望不是这样,因为这一类危害最小!

2

建筑技术债务

这是软件项目承担的一种不常见但关键的债务形式。它与系统架构、运行时选择、接口、服务设计、存储决策和其他设计考虑有关。

一些例子:

这个过程在什么运行时运行?

我们如何在流程/服务之间传递消息?

我们是采用单一策略、共享库还是面向微服务的架构?

这应该是离线工作还是在线服务?

这些工作人员应该是无状态还是有状态的?

我们应该采用轮询模型、触发器还是事件驱动模型?

这些架构决策可以将项目推向完全不同的方向。以上面的例子为例,在流量平滑、QPS低的情况下使用中间发布/订阅队列,可能会以维护和调试的形式增加架构债务。然而,如果流量陡峭,服务B无法处理峰值负载,推送模型将在该领域产生最多的债务。

结构性债务的偿还通常需要更长的时间。长反馈循环更难学,这种结构性债务很容易被忽视。SWE在硅谷的平均任期是18个月,但是在早期的架构决策中发现问题可能需要更长的时间!当优步发展到1000个微服务和2000个工程师时发生的事情就是一个完美的例子。走微服务路线确实在短时间内提高了他们的速度,但后来这条路线给整个系统带来了调试和延迟的债务。

架构债务可能比代码债务更昂贵、更难偿还。对您正在处理的系统进行深入分析,了解项目做出的影响服务特性的关键决策,在任何时候都是非常有价值的行动。其中一些决定可能是有意做出的,结果很有趣。

最后,即使当人们试图避免结构性技术债务时,这些债务也可能会秘密增加。过早的优化通常会导致我们最终负债累累。一个例子是为10k QPS设计的Web服务,它仅用于处理1/100的流量。许多架构决策可能会相互冲突,并且由于不必要的复杂性很容易产生债务。

数据和建模技术债务

数据建模似乎没有以前那么普遍了。有一段时间,大多数工程师都定期参与数据建模。如今,人们通常将其委托给一个特殊的团队,或者使用一些工具来允许他们完全忽略这样的问题。

数据建模的影响存在于短期和长期范围内。从短期来看,在模型和类型上花费大量时间会让人觉得成本很高,所以人们很容易选择一些非常灵活的东西来优化早期迭代和灵活性。然而,我看到这是错误的方式。最后,我们将在回填、数据完整性修复和重建方面做大量工作。好的数据建模对代码和系统架构有积极的影响,这意味着这三类技术债务实际上是相互关联的。然而,数据是最难做对的事情之一,也是最难改变的事情之一。因此,数据技术债务应该得到认真对待、积极识别和正确处理。事实上,当您想要更改数据模型时,这种更改的依赖关系图通常非常模糊。它需要涉及代码更改、数据库迁移和回填,所有这些都可能有复杂的依赖关系,并可能影响多个系统、团队或服务。

个人认为这个技术债类是最有偶然性的。了解读写模式和数据模型之间的关系,可以帮助你有效防止这种负债方面,或者至少有意识地承担。预测哪里需要灵活性,哪里不应该存在灵活性,这是一个非常微妙的问题。随着时间的推移,人们在处理这类问题时会更有经验,但必须有意识地处理。

摘要

我们在代码、数据和架构类别中提到了技术债务。下一次你做设计决定或审查代码时,你可以试着找出你的债务,并对它们进行明确的讨论:这些债务可能会产生什么后果?什么时候解决?在日常的开发工作中,架构和数据的技术债务是最难注意到的,但它们在未来的消化成本是最高的,值得你认真应对。

最后,我想强调的是,技术债并不总是坏事。使用MongoDB来原型化想法或编写一个丑陋的函数来解决关键错误可能是合理的,也可能是最好的解决方案。问题是不要刻意做一些增加技术债务的事情。

https://bytesizetheories.com/posts/3-kinds-of-tech-debt/