ThoughtWorks技术雷达:2021年一定要关注的技术趋势和选型建议

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"技术雷达是 ThoughtWorks 每半年发布一次的技术趋势报告,它持续追踪有趣的技术是如何发展的,我们将其称之为条目。技术雷达使用象限和环对其进行分类,不同象限代表不同种类的技术,而环则代表我们对其作出的成熟度评估。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"经过半年的追踪与沉淀,ThoughtWorks TAB(ThoughtWorks 技术咨询委员会)根据我们在多个行业中的实践案例,为技术者产出了第 24 期技术雷达。对百余个技术条目进行分析,阐述它们目前的成熟度,并提供了相应的技术选型建议。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/wechat\/images\/65\/6540a86403958205ad03fb225cebb9a9.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"本期四大主题"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"加速产品上市的平台团队"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"越来越多的组织正在采用平台团队的理念来开发产品,即成立一个专门团队,来创建和支持内部平台功能,并使用这些功能来加速应用程序开发,降低运维复杂性,并缩短产品上市时间。这种日趋成熟的做法值得欢迎,所以我们早在 2017 年,就将该技术引入技术雷达。但是随着成熟度的提高,我们发现组织在应用这项技术时,应避免使用一些反模式。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"例如,“用一个平台来统治一切”,可能并不是最佳选择。“构建一步到位的大平台”,可能要过数年后才能交付价值。本着“一旦建好,就有人用”的初衷,到头来可能却是巨大的浪费。相反,使用产品思维,有助于根据产品客户的需求,来弄清每个内部平台所应提供的服务。但如果让平台团队只解决技术支持工单系统中所提交的问题,那么这种做法就又产生了老式的运维孤岛团队,出现相应的需求优先级失调的弊端,如反馈和响应缓慢,以及争夺稀缺资源等的问题。此外,我们还看到一些新工具和集成模式涌现出来,以有效划分团队和技术。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"整合的便利性盖过单项最佳方案"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我们在许多平台(特别是在云领域)上看到了相应的面向开发者的工具集成。例如,工件库、源码控制、CI\/CD 流水线、wiki 以及类似的工具,开发团队通常会手工挑选这些工具并按需拼接在一起。拥有合并的工具栈可以为开发人员带来更多的便利和更少的工作,但这套工具集却很少能代表最佳的解决方案。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"太复杂以至于无法进入雷达"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在技术雷达的命名法则里,对许多复杂主题的讨论,最终状态都会是“TCTB——太复杂以至于无法进入雷达(too complex to blip)”。这意味着那些条目无法被分类,因为它们呈现出太多正反两面的特性,以及大量关于建议、工具的适用性和其他原因上的细微差别,这让我们无法用短短几句话总结它们。这些主题通常每年都会出现,包括 monorepos,分布式架构的编排指南以及分支模型等等。就像软件开发中的许多主题一样,那里存在太多权衡,难以提供清晰明确的建议。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"识别架构耦合上下文"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在软件架构中,如何在微服务、组件、API 网关、集成中心、前端等等之间确定一个适当的耦合级别,是几乎每次会议都会讨论的话题。随处可见的情况是,当两个软件需要连接在一起时,架构师和开发人员都在努力地寻找正确的耦合级别。我们需要花时间和精力去理解这些因素,然后因地制宜地做出这些决定,而不是寄希望于找到一个通用却并不恰当的解决方案。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"部分象限亮点抢先看"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/wechat\/images\/af\/af0197c1118d42d2be3f4dfced1dd69c.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"平台工程产品团队(采纳)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"正如本期雷达主题之一所指出的那样,业界在创建和支持内部平台的“平台工程产品团队”中积累了越来越多的经验。组织中的团队使用这些平台,可以加速应用程序开发,降低运营复杂性并缩短产品上市时间。随着采用率的提高,我们对于这种方法的好和坏的模式也越来越清楚。创建平台时,至关重要的是要明确定义可以从中受益的客户和产品,而不是凭空建立。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我们不仅要谨防分层平台团队,它保留了现有技术孤岛,只是贴上了“平台团队”的标签而已,还要小心工单驱动的平台运营模型。当考虑如何最好地组织平台团队时,我们仍然是团队拓扑概念的忠实拥护者。我们认为平台工程产品团队是一种标准方法,并且是高性能 IT 的重要推动者。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"云沙箱(试验)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由于云服务变得越来越常见,并且创建云沙箱变得更加容易且可大规模应用,我们的团队因此更倾向于使用完全基于云(相对本地而言)的开发环境,并以此来减少维护复杂度。我们发现用于本地模拟云原生服务的工具限制了开发者对构建和测试周期的信心,所以我们将重点放在标准化云沙箱上,而不是在开发机器上运行云原生组件。这样的方式可以使基础设施即代码实践得到更好的强制应用,并为开发人员提供沙箱环境良好的适应过程。当然这种转变也存在风险,因为它假定开发人员将完全依赖于云环境的可用性,并且可能会减慢开发者获得反馈的速度。我们强烈建议您采用一些精益治理的实践来管理这些沙箱环境的标准化,尤其是在安全、访问控制和区域部署方面。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"同态加密(评估)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"完全的同态加密 (Homomorphic encryption) 是指一类允许在加密数据上直接进行计算操作(如搜索和算数运算)的加密方法。同时计算的结果仍然以加密的形式存在,并且稍后可以对其进行解密和显示。虽然同态加密问题早在 1978 年就被提出来了,但直到 2009 年才出现解决方案。随着计算机算力的提升,和诸如 SEAL, Lattigo, HElib 和 Python 中的部分同态加密之类易于使用的开源库的出现,同态加密在现实世界的应用程序中的应用才真正地变得可行。那些令人振奋的应用场景包括在将计算外包给一个不受信的第三方时的隐私保护,例如在云端对加密数据进行计算,或使第三方能够聚合同态加密后的联邦机器学习的中间结果。此外,大多数的同态加密方案被认为是对量子计算机安全的,并且标准化同态加密的努力也正在进行之中。尽管同态加密目前在性能和可支持的计算类型上还存在诸多局限,但是它仍然是一个值得引起我们注意的技术。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/wechat\/images\/8d\/8d7c7d9a71a6467e6dd17a13c01ce6a5.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"Sentry(采纳)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Sentry 已经成了许多团队的默认选项。Sentry 提供了一些便利的功能,比如错误分组,以及使用适当的参数定义错误过滤规则,可以极大地帮助处理来自终端用户设备的大量错误。通过将 Sentry 集成到持续交付流水线中,你可以上传源码映射文件,从而更高效地调试错误,并能很容易追踪到是在哪个版本的软件中产生了这些错误。我们很欣赏尽管 Sentry 是一个 SaaS 产品,但它的源代码是公开的,这样就可以免费用于一些较小的用例和自托管中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"imgcook(评估)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"imgcook 是阿里巴巴旗下的软件即服务产品。它可以通过智能化技术把不同种类的视觉稿 (Sketch\/PSD\/ 静态图片) 一键生成前端代码。imgcook 可以生成静态代码,如果你定义了领域专用语言,它也可以生成数据绑定模块代码,该技术还没达到完美的程度,设计人员需要参考某些规范,以提高代码生成的准确性(此后仍需开发人员的调整)。我们对于魔术代码生成一直十分谨慎,因为从长远看,生成的代码通常很难维护,imgcook 也不例外。但是如果你限定它用于特定的上下文,例如一次性活动广告页,这项技术值得一试。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"AWS CodePipeline(暂缓)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"根据 ThoughtWorks 多个团队的使用经验,我们建议你谨慎使用 AWS CodePipeline。具体来说,我们发现一旦团队的需求超出简单的流水线范畴,此工具就会变得难以使用。尽管初次使用 AWS 时,像是赢得了“快速的胜利”,但我们建议你后退一步,评估 AWS CodePipeline 是否可以满足你的长期需求,例如流水线的 fan-out 和 fan-in,或者是更复杂的部署,以及具有特殊依赖关系及触发条件的测试场景。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/wechat\/images\/28\/28c9dfcf40e456e8f54a3c4073ae5fa1.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"Snowflake(试验)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"自从上次在雷达上提到 Snowflake 以来,对于它的使用,以及作为数据仓库和数据湖的替代方案的 data mesh,我们都获得了更多经验。Snowflake 在时间旅行、零拷贝克隆、数据共享及其应用市场等功能方面,继续给人留下深刻印象。Snowflake 至今还没出现任何令我们不喜欢的地方,所以相较于其他选择来说,我们的顾问会更偏爱使用它。亚马逊的数据仓库产品 Redshift 正在朝着将存储和计算进行分离的方向发展,而这一直都是 Snowflake 的强项。如果使用 Redshift 产品中的 Spectrum 特性进行数据分析,就会感觉它并非那么方便和灵活,部分原因是它受到了 Postgres 的约束(虽然我们也喜欢用 Postgres )。而进行联合查询(federated queries)可能是使用 Redshift 的原因。在操作方面,Snowflake 的操作会更简单。虽然 BigQuery 是另一种选择,且非常易于操作,但在多云的场景下,Snowflake 是更好的选择。我们已经在 GCP、AWS 和 Azure 上成功地使用了 Snowflake。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"Feature Store(评估)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Feature Store 是一个服务于机器学习的数据平台,可以解决当前我们在特征工程中所遇到的一些关键问题。它提供了三个基本功能:(1)使用托管的数据管道,以消除新数据与数据管道之间的冲突;(2)对特征数据进行编目和存储,从而促进跨模型的特征的可发现性和协同性;(3)在模型的训练和干扰过程中,持续提供特征数据。自从 Uber 公开了 Michelangelo 平台以来,许多组织和初创企业都建立了自己的特征库;例如 Hopsworks、Feast 和 Tecton。我们看到了 Feature Store 的潜力,并建议仔细对其进行评估。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"自研基础设施即代码 (IaC) 产品(暂缓)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"那些由公司或社区所支持的(至少在业界引起关注的)产品,正在不断发展。但有时组织会倾向于在现有的外部产品之上,构建框架或抽象,来满足组织内非常特定的需求,并认为这种适配会比其现有的外部产品具备更多好处。我们发现一些组织试图基于现有外部产品,创建自研基础设施即代码 (IaC) 产品。他们低估了根据其需求不断演进这些自研解决方案而所需投入的工作量。很快他们就会意识到,所基于的外部产品的原始版本要比他们自己的产品好得多。在有些情况下,构建在外部产品之上的抽象,甚至削弱了外部产品的原始功能。虽然目睹过组织自研产品的一些成功案例,但是我们仍然建议要审慎地考虑这种方式。因为这会带来不可忽视的工作量,并且需要确立长期的产品愿景,才能达到预期的结果。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/wechat\/images\/35\/359b729bc41cb5f3cc6f56acb6212218.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"Combine(采纳)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我们几年前把 ReactiveX(反应式编程开源框架中的一个系列)移到了技术雷达的“采纳”环中。2017 年,我们提到了 RxSwift,它可以将反应式编程应用到基于 Swift 的 iOS 开发中。此后,Apple 以 Combine 的形式推出了自己的反应式编程框架。对于仅支持 iOS 13 及更高版本的 App 而言,Combine 已经成为默认的选择。它比 RxSwift 更容易学习,并且与 SwiftUI 集成得很好。如果您想要将现有项目框架从 RxSwift 转换为 Combine,或者在一个项目中同时使用两者,可以了解一下 RxCombine。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"Kotlin Flow(试验)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Kotlin 协程的引入为 Kotlin 的创新打开了一扇大门——直接集成到协程库中的 Kotlin Flow 就是其中之一。Kotlin Flow 是一种基于协程的响应式流的实现。与 RxJava 不同的是,流是 Kotlin 原生的 API,与熟悉的序列 API 类似,包括 map 和 filter 方法。跟序列一样,流是“冷”的,这就意味着只有当需要使用的时候才构造序列的值。所有这些特性使多线程代码的编写比其他方法更加简单和易于理解。可以预见,通过 toList 方法将流转换成列表将会成为测试中的一种常见模式。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"River(评估)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"众多机器学习方法的核心皆在于从一组训练数据创建一个模型。一旦创建了模型,就可以反复使用它。然而世界并不是静止的,通常模型需要随着新数据的出现而改变。单纯地重新训练模型可能会非常缓慢和昂贵。增量学习解决了这个问题,它使从数据流中增量地学习成为可能,从而更快地对变化做出反应。作为额外的好处,计算和内存需求更低,而且是可预测的。我们在基于 River 框架的实现中积累了良好的经验,但到目前为止,我们需要在模型更新后增加校验,有时要手动进行。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"italic"},{"type":"strong"}],"text":"完整版技术雷达可点击以下链接:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"italic"},{"type":"strong"}],"text":"https:\/\/www.thoughtworks.com\/cn\/radar"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章