Thoughtworks 第 29 期技术雷达——技术象限概览

2023-10-13 11:45:28 浏览数 (1)

技术象限

采纳

1. 设计系统

随着应用开发变得越来越动态和复杂,交付风格一致且好用的产品成为了一项挑战,尤其是在有多个团队参与不同产品开发的大型组织中。设计系统定义了一系列的设计模式、组件库以及良好的设计和工程实践,以确保数字产品的一致性。设计系统从过去的企业风格指南演变而来,提供易于查找和使用的共享组件库和文档。通常,设计系统的风格指南以代码的形式记录并进行版本控制,比简单的文档记录更加清晰且易于维护。设计系统已经成为跨团队和学科进行产品开发时的标准方法,每当需要新的视觉组件时,团队不用重新发明轮子,因此能够集中精力,专注解决产品本身的种种挑战。

我们的经验表明,团队在构建设计系统时很少采用产品为中心的思维方式。共享组件库和文档的主要消费者是产品开发团队。在使用产品为中心的思维方式时,设计系统所有者应该与消费者(开发团队)合作,建立共情。我们发现,许多组件库之所以受到批评,是因为所有者团队无法快速响应消费者的需求,并且无法接受来自外部的贡献。产品为中心的思维方式还要求组织思考是否应该允许和怎样向设计系统做出贡献,以及如何管理这些贡献——在这个话题上,我们推荐采用设计系统决策记录 。对我们来说,维护一个良好的设计系统或组件库不光是技术工作,也同样是社交工作。

2. 轻量级的 RFCs 方法Request for Comments (RFC) 是一种正式文档,其包含与上下文相关的设计和架构思想,以促进团队协作和决策。几乎所有数字原生和快速扩张的组织都使用 RFCs 来记录围绕设计、架构、技术和团队协作方式的决策。成熟的组织已经在自治团队中,特别是在跨团队相关的决策中使用 RFCs 来推动更好的沟通和协作。它通常被用作架构决策记录的审查和批准过程。即让受决策影响的人有机会在决策获得批准之前,参与讨论并提供意见,这一个透明的协作过程。快节奏的环境往往会导致设计决策的推理过程丢失,从而让负责实施决策的团队感到困惑。RFCs 提供了一个决策审计记录,有利于未来的团队成员查看,与此同时记录了组织技术和业务的演进过程。RFCs 可以成为促进演化架构的宝贵工具。不过,为了获得最佳效果,我们建议组织采用轻量级的 RFCs 方法。如果不限定范围并明确要点,这些文件往往会随着时间的推移而变得越来越长,类似于传统的解决方案架构文件一样最终被归档和遗忘。

试验

3. 具有可访问性意识的组件测试设计

在软件交付进程中,可访问性要求是 Web 组件测试阶段的一种考察指标。尽管诸如 chai-a11y-axe 的测试框架插件 API 已提供了基础的可访问性断言,具有可访问性意识的组件测试设计依然能够帮助测试进一步检验屏幕阅读器和其他辅助技术所需的全量语义元素。

首先,在测试验证元素时,通过 ARIA 角色或者元素的其它语义化属性查找元素,而不采用元素的 test id 或 class 属性。像 Testing Library 的一些测试库甚至已经在文档中推荐了这一实践。其次,不要仅仅测试点击交互,还要考虑不能使用鼠标或看不到屏幕的人,并考虑增加针对键盘和其他交互方式的额外测试。在我们的团队中,上述测试设计实践已十分成熟,并且我们已在不久前将其纳入测试闭环中。

4. 攻击路径分析

攻击路径分析是一种分析和评估潜在攻击路径的安全分析方式,黑客可能按照这些来自组织内系统网络的潜在攻击路径进行攻击。此前的多数安全分析策略或工具主要聚焦在特定分线领域,例如错误的配置,脆弱的容器,和常见漏洞上。这些孤立的方法意味着团队们不能看到这些风险与技术栈上其他层的弱点组合产生的危险攻击路径。尽管这一技术已提出一段时间,但是近期安全分析工具的进展能使安全团队更易使用这项技术。Orca 和 Wiz 是两个此类工具。我们建议管理复杂基础设施的团队在为组织设计安全策略或选择安全分析工具时考虑这项技术。

5. 自动合并依赖项更新 PR

软件供应链的复杂性是一个重大风险,我们已经在一些文章中进行过讨论,例如 SBOM 与 SLSA 。对于大多数团队来说,致命弱点仍然是依赖项中存在漏洞,通常是来自于多层的间接依赖项。Dependabot 等工具可以通过创建拉取请求 (PR) 来更新依赖项。不过,团队仍然需要制定工程纪律,以确保及时处理这些 PR,尤其是对长时间不活跃的应用程序或服务提交的 PR。

如果系统具有广泛的测试覆盖范围——不仅有完善的单元测试,还包括有功能和性能测试,并且构建流水线必须运行所有这些测试以及安全扫描,我们更提倡自动合并依赖项更新 PR。简而言之,团队必须完全相信,流水线运行成功后,软件就可以投入生产。在这种情况下,依赖项更新 PR,即使它们在间接依赖项中包含主要版本更新,也应该自动合并。

6. 针对 FAIR 数据的数据产品思维

数据产品思维重视将数据消费者视为客户,确保他们在数据价值链中的无缝体验。这包括易用的数据发现、理解、信任、访问和消费。“产品思维”不是一个新概念,过去我们在运维中施用了这一概念,建立了运维产品和微服务。它伴随着构建长期的跨功能的团队在组织中拥有并分享他们的数据,通过结合数据和产品思维,我们相信组织能够使用 FAIR (可发现, 可访问, 可互通且可复用) 原则进行数据运营。我们的团队使用如Collibra 和 DataHub 的数据目录实现数据产品的可发现性,为了建立信任,我们发布数据质量和服务等级指标,比如数据产品的及时性、完整性和一致性, 并使用 Soda Core 和 Great Expectations 等工具自动化数据质量检查。 数据可观测性可同时通过Monte Carlo等平台实现。

我们已经看到数据产品随着时间的推移,演变为多个用例的可重用构建块。随着我们在识别和构建价值驱动的数据产品上的进展,后续用例的上市时间也随之加快。因此,我们的建议是,采纳针对 FAIR 数据的数据产品思维。

7. OIDC for GitHub Actions

推荐实现 CI/CD 的零信任安全的技术之一是通过使用 OpenID Connect (OIDC) 等联合身份机制对流水线进行身份验证,以访问云服务。这一重要的技术仍未被充分利用在 GitHub Actions 中,因此推荐 OIDC for GitHub Actions。通过这种方式,可以避免存储长期的访问令牌来访问云资源,同时确保流水线无法直接访问机密信息。然而,请务必谨慎地限制访问权限,以确保操作以最低权限运行。

8. 使用 Terraform 创建监控和告警

基础设施及代码(IaC) 已经是一种被广泛采纳用于定义和创建托管环境的方法。尽管这个领域的工具和技术不断发展,但 Terraform 仍然是 IaC 方式管理云原生资源的主要工具。然而,当下大多数托管环境都是云供应商原生服务、第三方服务和自定义代码的复杂组合。在这些环境中,我们发现工程师通常会使用 Terraform 处理云资源,又使用自定义脚本处理其他资源。这可能导致资源创建过程缺乏一致性和可重复性。事实上,在托管环境中常用的许多第三方服务 Terraform 都提供了相应的支持程序,可以用来创建和配置这些服务,例如 Splunk、Datadog、PagerDuty 和 New Relic。因此,我们建议团队除了云资源外,还应使用 Terraform 创建监控和告警。这将实现更模块化的 IaC,更易于理解和维护。与所有 IaC 一样,同时使用多种方式进行配置变更,会带来不一致的风险。所以,我们建议禁用通过用户界面和 API 的方式处理配置变更,确保 Terraform 代码始终是唯一的真实生效的版本。

9. ReAct 提示工程

ReAct 提示工程是一种用于提示大语言模型的方法,相较于思维链 (CoT)等竞争方法,ReAct 旨在提高大语言模型的响应准确性。这一方法在一份2022年的论文中首次提出,其原理是将推理和行动结合起来(因此称为ReAct)。这种方法有助于使大语言模型的响应更具解释性,相对于思维链减少了虚构性内容,从而提高了提示者获得他们想要的内容的机会。最初,LangChain 是为支持这种提示方式而开发的。基于 ReAct 的自主代理已被证明是我们团队构建的大语言模型应用中使用最广泛的一种。最近,OpenAI 在其 API 中引入了函数调用以使 ReAct 和类似的提示风格更容易实现,而无需依赖像 LangChain 这样的外部工具。我们仍然处于定义这一学科的早期阶段,但到目前为止,ReAct 及其后继方法已指引出大语言模型最令人兴奋的一些应用领域。

10. 检索增强生成

检索增强生成(RAG) 是一种结合预训练参数和非参数记忆的文本生成技术。它使你能够通过你的领域内特有的包含上下文的知识,来强化预训练模型中的现有知识。使用 RAG,你会先从非参数记忆中去检索相关文档集(一般是通过在向量数据库中的相似性搜索),再使用LLM中的参数记忆生成与检索出的文档一致的输出。我们发现 RAG 对各种需要大量知识的 NLP 任务十分有用,包括问答,总结和故事生成。

11. 基于风险的故障建模

基于风险的故障建模是一种用于了解系统发生故障的可能性、潜在影响和检测手段的方法。交付团队逐渐开始使用这种方法来设计和评估预防故障所需的控制措施。该方法源自故障模式与影响分析(FMEA)的实践。FMEA 是一种诞生于上世纪 40 年代的风险评分技术,成功运用于航空航天和汽车等建造复杂物理系统的行业中。与这些行业一样,软件故障也可能产生严重后果,例如危及人类健康和隐私。这就是为什么我们越来越需要对系统进行严格分析的原因。该方法首先识别可能的故障模式,然后对根本原因进行分析,并根据故障发生的可能性、影响的大小以及发现根本原因的概率给出评分。我们发现,当跨职能团队在系统演进过程中迭代使用该方法时效果最好。在安全方面,基于风险的故障建模可以作为威胁建模和攻击路径分析的有益补充。

12. 大语言模型半结构化自然语言输入

在使用大语言模型的各种应用中,我们在半结构化自然语言输入方面取得了成功。结构化输入,如 JSON 文档,清晰而精确,为模型提供了所寻求响应类型的指示。以这种方式限制响应有助于缩小问题空间,并且可以产生更准确的响应,特别是当结构符合领域特定语言(DSL)的语法或模式情况下。我们还发现,将结构化输入与自然语言注释或标记结合使用,比仅使用自然语言或结构化输入产生更好的响应。通常,在构建提示时,自然语言会与结构化内容简单地交织在一起。与许多大语言模型行为一样,我们不知道为什么这样做有效,但我们的经验表明,在人工编写的代码中加入自然语言注释也会改善基于大语言模型的编码助手的输出质量。

13. 追踪健康债务状况

通过将健康度评级与其他服务级目标(SLO)同等对待,并据此确定增强的优先级,而不是仅仅关注跟踪技术债务,我们不断体验到团队对其生态系统的改进。通过有效分配资源来解决与健康状况相关的最有影响的问题,团队和组织可以降低长期维护成本,更高效地发展产品。这种方法还能加强技术和非技术利益相关者之间的沟通,促进对系统状态的共同理解。尽管不同组织的衡量标准可能有所不同(请参阅本博文中的示例),但它们最终都有助于实现长期可持续性,并确保软件保持适应性和竞争力。在瞬息万变的数字环境中,专注于跟踪系统的健康状况与债务,可为维护和增强系统提供结构化的循证战略。

14. 对告警规则的单元测试

可观测性和监控对于软件团队至关重要。鉴于特定事件的不可预测性,创建具有复杂规则的准确告警机制至关重要。然而,只有当事件真实出现时,这些规则才能得到真正的验证。对告警规则的单元测试让团队通过预先、主动地测试和完善规则,来更好地定义规则,从而增加对规则的信心。这有助于减少误报,并确保报告真正的事件。Prometheus 等工具支持对规则进行单元测试。我们的团队报告它的确可以在现实环境中起到帮助作用。

15. CI/CD 的零信任保护

如果没有得到正确的安全配置,运行构建和交付流水线的基础设施和工具可能成为一个大隐患。流水线需要访问关键数据和系统,如源代码、凭据和机密数据,去构建和部署软件。这让这些系统对恶意攻击者充满了吸引力。因此,我们强烈推荐为 CI/CD 流水线和基础设施引入零信任安全机制——尽可能少地信赖它们。这项机制包含一系列技术:如果可行,使用云供应商提供的联合身份校验机制,如 OIDC ,来验证流水线,而不是赋予它们直接访问机密数据的权限。实行最小权限原则去最小化个人用户和执行器账户的权限,而不是使用具有无限访问权限的万能账户。使用一次性执行器替代重复使用执行器,来减少暴露先前任务的机密数据或在受到攻击的运行器上运行任务的风险。将执行代理和执行器上的软件更新到最新版本。像监控你的生产软件一样去监控你的 CI/CD 系统的完整性、保密性和可用性。

我们不断见到有团队忘记这些实践,特别是当他们使用在内部网络中自我管理的 CI/CD 基础设施的时候。所有这些实践不仅在内部网络中很重要,当使用托管服务时,因为扩大了攻击面和影响范围,这些实践会变得更加关键。

评估

16. 通过依赖健康检查化解包幻觉风险

确保软件供应链的安全已成为交付团队普遍关心的问题,这也反映在该领域的工具和技术数量不断增加,而一些工具和技术我们在之前的雷达中也进行了介绍。在软件开发过程中使用基于 GenAI 的工具日益普及,这也引发了一种新的软件供应链攻击媒介:包幻觉。我们认为在开发过程中使用 GenAI 工具的团队需要重视这类风险。团队可以通过对依赖进行健康检查化解包幻觉风险:在选择依赖之前查看它的创建日期、下载数量、github 评论及星标数、贡献者数量、活动历史记录等。一些依赖健康检查可以在包存储仓库和 GitHub 上执行,而像 deps.dev 和 Snyk advisor等工具也可以提供帮助。尽管依赖健康不是一项新技术,但随着团队在软件开发过程中越来越多地尝试 GenAI 工具,该实践正在获得新的关注。

17. 设计系统决策记录

在迭代速度快、用户需求不断演进的产品开发环境中,设计是一个不断变化的领域。这意味着对设计决策输入的需求会一直持续下去。我们借鉴了用 ADR(架构决策记录)记录软件架构决策的思路,采用类似的格式,以设计系统决策记录来记录设计系统决策以及相应的依据、研究洞见和实验结果,这有效地传达了设计系统决策似乎已成为产品开发团队新的需求。这种轻量级的方式也被 zeroheight推荐。这一方法让我们减少了新人上手时间,推动了讨论的进行,并帮助拉通共用同一个设计系统的多个开发团队。

18. GitOps

GitOps 是一项通过控制回路模式进行应用部署的技术。Operator 能够将已部署的应用和配置(通常是 Git 仓库)保持同步。当我们上次写到 GitOps 的时候,社区对此术语的定义未能形成共识。当时,我们对该技术的常见解读抱有疑虑,因为部分解读包含不恰当的做法。例如,使用“环境分支”就可能导致雪花即代码的出现。此外,“GitOps 是持续交付的一种替代方案”这个说法也令人困惑。在那之后,四个 GitOps 原则澄清了该技术的范围和性质。当拨开炒作和混乱的迷雾,你会发现 GitOps 是一项基于 Kubernetes 集群功能的有用技术,为分离介于配置应用和实施部署流程的关注点创造了机会。我们的一些团队在他们的持续交付设置中实施了 GitOps ,并取得了良好的体验。所以我们推荐大家去评估这项技术。

19. 大语言模型驱动的自主代理

随着大语言模型的持续发展,构建自主人工智能代理的兴趣日益浓厚。AutoGPT、GPT-Engineer 和 BabyAGI 都是大语言模型驱动的自主代理的示例,它们朝着底层大语言模型理解所获得的目标方向努力。这些代理会记住目标的进展程度,使用大语言模型来思考接下来该做什么,然后采取行动,并理解何时已经实现了目标。这通常被称为思维链推理,而且实际上是可行的。我们的团队实现了一个作为自主代理的客户服务聊天机器人。如果机器人无法达成客户的目标,它会认识到自己的限制并将客户引导到人工处理。这种方法显然仍处于早期发展阶段:自主代理通常存在高失败率和高昂的 AI 服务费用,至少有一家 AI 初创公司已经从代理为基础的方法转向其他方向。

20. 平台编排

随着平台工程的广泛采纳,我们看到了新一代的工具,它们超越了传统的平台即服务(PaaS)模型,为开发人员和平台团队之间提供了公开的合约。这个合约可能涉及在不同环境中提供云环境、数据库、监控、身份验证等功能。这些工具强制执行组织标准,同时允许开发人员通过配置自主访问多种环境。这些平台编排系统的案例包括 Kratix和 Humanitec Platform Orchestrator。我们建议平台团队考虑这些工具,作为自己的脚本、本地工具和基础设施即代码(infrastructure as code,IaC)的独特集合替代方案。我们还注意到,与开放应用模型(OAM)及其参考编排器 KubeVela 有相似之处,尽管 OAM 声称更加面向应用程序而不是工作负载为中心。

21. 自托管式大语言模型

大语言模型(LLMs)通常需要大量的 GPU 基础设施才能运行,但目前有强烈的推动力使它们可以在更简单的硬件上运行。对大语言模型进行量化可以减少内存需求,使高保真度模型可以在成本更低廉的硬件甚至是 CPU 上运行。像 llama.cpp 这样的工作使大语言模型可以在包括树莓派、笔记本电脑和通用服务器在内的硬件上运行成为可能。

许多组织正在部署自托管式大语言模型。这往往是出于安全或隐私方面的考虑,有时是因为需要在边缘设备上运行模型。开源示例包括 GPT-J、GPT-JT 和 Llama。这种方法提供了更好的模型控制,以进行特定用途的微调,提高了安全性和隐私性,以及离线访问的可能性。尽管我们已经帮助一些客户自托管开源大语言模型用于代码生成,但我们建议在决定自托管之前仔细评估组织的能力和运行这类大语言模型的成本。

暂缓

22. 忽略 OWASP 十大安全风险榜单

OWASP 十大安全风险榜单长期以来一直是 Web 应用程序最关键的安全风险参考。尽管众所周知,我们曾写过它在软件开发过程中未得到充分利用,并警告不要忽略 OWASP 十大安全风险榜单。

但鲜为人知的是 OWASP 也在其他领域发布了类似的十大榜单。在八月初发表了第一个主要版本的 OWASP LLM 十大安全风险榜单 强调了提示注入、不安全的输出处理、训练数据投毒以及其他个人和团队构建 LLM 应用程序时最好注意的风险。OWASP 近期也发布了 OWASP API 十大安全风险榜单的第二版。鉴于 OWASP 十大安全风险榜单的覆盖范围(Web 应用程序、API、LLM 及其他)、质量以及与持续变化的安全形势的相关性,我们继续向团队警告不要忽略 OWASP 十大安全风险榜单。

23. 用于服务端渲染(SSR)web 应用的 web 组件

自从我们在2014年首次提到它们以来,Web 组件已经变得流行起来,总体而言,我们对其的看法是积极的。同样地,我们通过对采用默认选择 SPA 发出警告以及将如 Next.js 和 HTMX 等框架与传统的服务器端框架一起列入,来表达对在服务器上来渲染 HTML 的支持。然而,尽管可以将两者结合使用,也还是可能造成深层次的问题;这就是为什么我们建议避免服务器端渲染(SSR)的 Web 应用中使用 Web 组件。作为一种浏览器技术,要在服务器上使用 Web 组件并不容易。已经出现了一些框架来简化这一过程,甚至一些框架中还使用了浏览器引擎,但复杂性仍然存在。比开发人员体验更糟糕的是用户体验:当必须在浏览器中加载和构建自定义 Web 组件时,页面加载性能会受到影响,即使在预渲染和精心调整组件的情况下,也几乎无法避免“无样式内容闪烁”或某些布局变化。放弃使用 Web 组件的决定可能会产生深远的影响,正如我们的一个团队曾经不得不将其基于 Web 组件的设计系统 Stencil 进行迁移。

0 人点赞