Salesforce-反模式-全-
Salesforce 反模式(全)
原文:
annas-archive.org/md5/0b2a0f4d4219209f43dce3a5bbbeb4ca
译者:飞龙
前言
Salesforce 是全球领先的企业系统平台。这一地位是在过去十年中逐步建立的,其业务范围已从销售和客户服务的根基扩展到涵盖广泛的业务领域。
然而,随着 Salesforce 的增长,承载它的技术环境的复杂性也在增加。伴随这种复杂性的增加,一些常见的错误也随之出现,往往导致 Salesforce 项目在多种有趣的方式中脱轨。
这些错误我们将称之为反模式,并在本书中以结构化的方式进行探讨。市场上已经有不少关于 Salesforce 架构的书籍,但它们都从规范视角出发,基于良好的实践来探讨这一主题。
本书从不同的角度来看待这个问题。我们关注 Salesforce 项目中常见的错误做法,而这些做法在你做出决策时,实际上看起来可能是个好主意。
通过这样做,我们可以看到当事情未按照计划进行时会发生什么——当你没有做出正确的决策,导致你的解决方案受到影响。这样,我们就能为回顾关键架构概念和良好实践提供一个很好的背景,并且这些概念和实践适用于多种场景。
在本书中,您将获得基于认证技术架构师(CTA)考试路线图的七个领域的信息结构。这样,尽管所有信息都基于真实世界的案例,但如果你正在走向或考虑走向 CTA 的道路,你将能够直接应用这些知识。
在本版中,我们加入了许多新的反模式,并更新了现有内容。特别是,我们增加了关于人工智能和 DevOps 在 Salesforce 生态系统中日益增长应用的章节和参考资料。
本书的目标读者
本书适用于任何在 Salesforce 实施中有责任岗位的人,并希望避免那些困扰许多项目的常见错误。尽管主要读者是架构师或有志成为架构师的人,但项目经理、业务分析师、功能顾问和监督 Salesforce 项目的高管也将从中受益。
本书的内容
第一章,为什么我们需要理解 Salesforce 反模式?,首先通过多种不同的定义和视角来解释什么是反模式。接着,您将了解到,理解这些常见错误的产生过程以及它们在当时如何看起来像一个好主意,可以帮助您深化对架构的理解。最后,本章将帮助您理解本书的内容以及如何处理这些内容。
第二章,如何保持系统架构的清晰,引导你了解与系统环境、你在解决方案中使用的系统组合以及它们如何相互结合的常见反模式。我们将从描述系统组合和范围问题的最高级别反模式开始。然后,我们将探讨那些会导致高度耦合和脆弱系统环境的反模式,接着我们将讨论如何选择正确的系统来包括在内的反模式。最后,本章将以对现实生活中的关键要点和 CTA 评审委员会的回顾结束。
第三章,如何避免在安全性方面产生混淆,包含了与确保 Salesforce 组织安全相关的反模式。首先,我们将回顾关于 Salesforce 的共享安全模型的一个关键反模式。然后,我们将分析当你将其他事物误认为是安全时可能出现的反模式。接着,我们将继续探讨如何避免在共享模型中搞乱安全设置,最后再次通过回顾关键要点来结束本章。
第四章,数据管理中的错误做法,包含了与数据架构、建模和治理相关的反模式。我们将从未考虑 Salesforce 的对象模型设计时出现的问题开始。然后,我们将探讨围绕数据治理的常见灾难。接着,我们将深入探讨数据同步及其可能出错的方式,最后以生活中的关键要点和 CTA 评审委员会的回顾作结。
第五章,解决方案架构故障分析,涵盖了与你的解决方案架构相关的反模式。我们将从与你选择解决方案相关的反模式开始。接着,我们将讨论在进行功能设计时可能出现的错误。第三,我们将关注一些影响定制化的特定反模式,首先是概念层面的,随后是代码层面的。最后,我们将通过总结关键要点来结束本章。
第六章,保持集成清晰,探讨了你与其他系统集成相关的反模式。本章的第一部分讨论了集成环境和集成模式的反模式。第二部分分析了接口设计和使用中可能出现的问题,第三部分则聚焦于特定集成风格的问题,如基于事件的架构和批量传输。像往常一样,我们通过提炼关键要点来结束本章。
第七章 ,防止开发生命周期偏离轨道 ,探讨了与开发过程、治理和 DevOps 相关的反模式。我们将从解决一些重要的过程级反模式开始,然后转向处理 DevOps 和打包相关的反模式。最后,我们将讨论一个常见且非常不幸的反模式,涉及测试。章节末尾,我们将总结现实生活中的关键收获以及 CTA 审查委员会的经验。
第八章 ,无误传达的沟通 ,讨论了围绕向不同受众传达架构的反模式。第一部分涉及与信息控制相关的反模式。接着,我们探讨与沟通清晰度相关的一些反模式。第三部分关注的是关于创建架构文档的反模式。和之前一样,章节末尾我们将总结关键收获。
第九章 ,总结 ,概述了本书的内容,包括前几章的主要收获。接着,它解释了如何在自己的工作中使用反模式方法和视角来提升架构技能。最后,给出一些指引,帮助您在这个方向上进一步发展。
如何最大限度地利用本书
本书面向任何对使 Salesforce 项目成功的人士。尽管一些技术章节会假设读者具备一定的技术知识和经验,但唯一的真正前提是对 Salesforce 平台有一定的了解和兴趣。
使用的约定
本书中使用了许多文本约定。
文本中的代码 :表示文本中的代码词、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟网址、用户输入以及 Twitter 账户名。以下是一个示例:“Salesforce 的架构师之一 Pranit 提出了一个建议,通过创建一个 CentralDispatch Apex 类来简化当前的系统架构,该类将承担调度调用到其他代码或流程的角色。”
提示或重要注意事项
如下所示。
联系我们
我们总是欢迎读者的反馈。
一般反馈 :如果您对本书的任何内容有疑问,请通过电子邮件联系我们:customercare@packtpub.com,并在邮件主题中注明书名。
勘误 :虽然我们已经尽最大努力确保内容的准确性,但错误难免发生。如果您在本书中发现错误,欢迎您向我们报告。请访问 www.packtpub.com/support/errata 并填写表格。
盗版:如果你在互联网上发现我们作品的任何非法复制版本,我们将非常感激你提供该材料的地址或网站名称。请通过版权@packt.com 联系我们,并附上该材料的链接。
如果你有兴趣成为作者:如果你在某个领域有专业知识,并且有兴趣撰写或贡献书籍,请访问authors.packtpub.com。
分享你的想法
一旦你阅读了Salesforce 反模式,我们很想听听你的想法!请点击这里直接访问亚马逊的本书评论页面并分享你的反馈。
你的评论对我们以及技术社区非常重要,能帮助我们确保提供优质的内容。
下载本书的免费 PDF 副本
感谢购买本书!
你喜欢在旅途中阅读,但又不能随身携带纸质书籍吗?
你的电子书购买是否与你选择的设备不兼容?
别担心,现在每本 Packt 书籍都会附带免费的无 DRM 版本 PDF。
随时随地,在任何设备上阅读。直接从你最喜爱的技术书籍中搜索、复制并粘贴代码到你的应用中。
福利不止这些,你还可以每天在邮箱中收到独家的折扣、新闻通讯和精彩的免费内容。
按照以下简单步骤享受福利:
- 扫描二维码或访问下面的链接
packt.link/free-ebook/978-1-83546-784-8
-
提交你的购买凭证
-
就是这样!我们会将免费的 PDF 文件和其他福利直接发送到你的邮箱。
第一部分:技术反模式
本部分将教你如何识别并缓解在系统架构、数据架构和安全架构等技术领域中的反模式。
本部分包括以下章节:
-
第一章,我们为什么需要理解 Salesforce 反模式?
-
第二章,如何保持系统架构的整洁
-
第三章,如何避免在安全性上产生混淆
-
第四章,关于数据的禁忌
第一章:为什么我们需要理解 Salesforce 反模式?
Salesforce 反模式告诉我们很多 Salesforce 项目中常见的系统性错误——这些错误在实施时可能看起来是个好主意,但最终在长期内会带来严重的弊端。我们将在本书中学习最常见的错误类型,并学习如何思考这些问题。然而,为了做到这一点,我们必须理解反模式是什么,以及理解它们如何帮助我们架构和设计更好的系统。
因此,本章将从解释反模式是什么开始,逐步介绍几种不同的定义和看待它们的方式。接下来,你将了解它们如何帮助你加深对架构的理解,通过了解这些常见错误是如何发生的,以及它们在当时看起来为何是一个好主意。我们将在本章结束时解释本书将涵盖的内容以及你如何接近所提供的内容。
在本版中,我们扩展了对 Salesforce 反模式的探讨,涵盖了新的模式和见解,解决了 Salesforce 生态系统中的最新趋势和发展。这些新增内容基于第一版读者的反馈和我们对 Salesforce 架构不断变化的研究。值得注意的是,我们加入了与 AI 和 DevOps 实践相关的新模式,如“ AI 架构就像普通架构 ”和“ 让我们在其中加入 AI ”,同时也更新了现有模式,以反映当前的最佳实践。
在本章中,我们将涵盖以下主要话题:
-
理解反模式
-
反模式从哪里来?
-
反模式如何加深你的架构技能?
-
通过示例学习反模式
理解反模式
大多数开发人员和架构师都熟悉模式的概念——它是对一个架构领域中经常出现的问题的良好解决方案,以一种正式化和可重用的方式描述。以下是一些经典的例子:
-
单例模式(Singleton):一种软件设计模式,它将某一类型的实例数量限制为 1
-
火忘模式(Fire-and-forget):一种异步集成模式,它从计算上下文中发送消息并继续执行,而不等待响应
-
模型-视图-控制器(MVC):一种将应用程序分为三个层次并明确规定各自职责的架构模式:
-
首先,模型维护应用程序的状态,并负责任何数据的更改。
-
第二,视图通过某种界面将该模型的特定表示展示给最终用户。
-
第三,控制器实现了响应用户界面事件或模型变化的业务逻辑,并在视图与模型之间进行必要的调解。
此模式在下图中显示:
-
图 1.1 – MVC 模式图
这些模式已经在多个抽象层次和不同的平台上被定义。
参考文献
请查看以下资源,以便从 Salesforce 角度了解可以应用的各种模式的良好入门:
集成模式指南列出了设计 Salesforce 集成时应该使用的所有主要模式:developer.salesforce.com/docs/atlas.en-us.integration_patterns_and_practices.meta/integration_patterns_and_practices/integ_pat_intro_overview.htm
。在 Salesforce 的世界里,这可能是最常被引用的一套模式,因为它们在集成设计中无处不在。
Packt 出版的《Apex 设计模式》一书,由 Anshul Verma 和 Jitendra Zaa 编写,提供了针对 Apex 语言的软设计层级和具体代码层级的模式。
Salesforce Architects 网站虽然是新的,但涵盖了各个领域的一系列模式,从代码级别的具体内容到参考架构、解决方案工具包,以及选择治理的良好模式:architect.salesforce.com/design/#design-patterns
。
关键在于,我们在 Salesforce 平台上有很多良好的模式可供选择,其中许多是由 Salesforce 本身提供的,尽管也有一些是由更广泛的社区提供的。许多适用于其他平台的模式同样对我们有用,我们通过研究它们学到了很多。
但这是一本关于反模式的书,而不是模式。那么,为什么我要从讨论模式开始呢?事实证明,这两者几乎是不可分的,并且源于同一传统。因此,理解反模式首先需要理解什么是模式。反模式的一种常见形式就是设计模式的误用。我们将在下一节中探讨这一点。
从模式到反模式
软件架构中的设计模式运动源自克里斯托弗·亚历山大(Christopher Alexander)的工作,他是一位建筑师,专门设计建筑物而非系统。在他的著作《建筑的永恒方式》中,他介绍了一种物理架构的模式模板,包含一个名称、问题陈述和一个标准化格式的解决方案。
亚历山大模板所提供的修辞结构很快被另一类建筑师——软件开发者采纳。他们意识到,标准化的方式可以用来描述问题解决集,从而传播良好的实践。随着经典的《设计模式:可重用面向对象软件的元素》一书的出版,模式的使用在软件开发中成为主流,并至今仍然如此。
有关模式的研究激发了一群软件工程领域的从业者和研究者,他们开始像设计模式一样,思考软件系统的失败模式。这一过程经历了较长时间,无法指认出反模式运动中的任何一位人物是可以视为真正奠基性的人物。
然而,许多关于该主题的研究论文都以安德鲁·科宁(Andrew Koening)在 1995 年《面向对象编程杂志》中的定义为起点。该定义认为,反模式与模式非常相似,容易混淆。然而,使用反模式并不会带来解决方案,反而会带来负面后果。
这个定义捕捉了大部分的精髓,并且可以与另一位早期先驱吉姆·科普林(Jim Coplien)的一些思考结合起来。他认为,单纯的好模式不足以定义一个成功的系统。你还必须能够展示反模式的缺失。
总的来说,反模式是指在失败的软件系统或项目中出现的模式,它看起来像是一个好的解决方案,但实际上却会带来麻烦。以下是一些常见的反模式,它们已经存在了很长时间,并且至今仍然具有相关性:
- 锅炉管 : 一种系统或模块,由于其接口设计,几乎不可能进行更改。以下图示为例:
图 1.2 - 锅炉管反模式
-
Blob : 一种设计,其中单个类有效地封装了所有业务逻辑和功能,导致重大维护问题。
-
密切耦合 : 一种设计,使用了另一个类或模块中过多的方法来实现某个功能,导致形成了深度依赖关系,难以理解或修改。
我们将在后续章节从 Salesforce 的角度深入探讨这些反模式,强调一个不幸的事实:尽管 Salesforce 是一个优秀的平台,它仍然是一个容易犯下几十年来困扰软件系统的错误的软件系统。如果情况不是这样,那就不需要这本书——或者说 Salesforce 架构师也不需要存在。
除了对反模式有基础性的理解外,认识到这些模式如何与 Salesforce 生态系统中的最新趋势相符也是至关重要的。随着对 AI 和 DevOps 日益增长的关注,出现了新的反模式,专门应对这些领域中的挑战。例如,“让我们加点 AI”模式警告我们,避免在没有明确合理需求的情况下将 AI 纳入解决方案中,因为这会导致不必要的复杂性和维护挑战。
DevOps 实践也引入了新的反模式,例如“不频繁提交”,它强调了不经常集成代码更改的风险,这会导致集成地狱和部署问题。通过理解这些新趋势及其相关的反模式,架构师可以更好地应对现代 Salesforce 实现的复杂性。
讨论完反模式的历史起源后,接下来我们将讨论它们如何在现实世界中产生。
反模式是从哪里来的?
反模式往往反复出现,因为推动技术项目陷入困境的环境至少在某种程度上是可预测的。同样可以预测的是,处于这些环境中的人们的反应。由于身处困境的人们常常做出相同的错误决策,我们就有了可以研究的系统性模式。
一般来说,关于反模式最重要的记忆点是,它们在当时看起来像是一个好主意。它们不仅仅是一些坏习惯,应该有更多经验的人避免应用。你可以合理地辩解说,当应用这些反模式时,它们本应带来良好或至少是可以接受的结果。
有时,应用反模式的决定源于经验不足,而有时则是源于绝望。但往往,更多的是经验丰富的专业人士说服自己认为,在这种情况下,他们所做的才是正确的选择,或者这个情况是不同的。
反模式通常源于技术项目中可预测的情况,但最近的技术趋势引入了新的环境,在这些环境中这些模式得以展现。例如,人工智能(AI)和机器学习在 Salesforce 项目中的快速应用,导致了新反模式的出现,例如“AI 架构就像普通架构”。这些模式通常源于对将 AI 集成到 Salesforce 解决方案中的独特需求和挑战缺乏理解。
类似地,向 DevOps 实践的转变也突显了与持续集成和部署相关的新反模式。例如,“不频繁提交”模式出现在团队未能频繁集成代码更改时,从而导致了重大的集成挑战和部署延迟。
我们将在本书中提供的例子中,尽量反映这种起源的多样性。然而,为了做到这一点,我们需要解释如何以一致的方式呈现这些例子,以便促进学习。
反模式模板
模式和反模式的一个关键特征是它们都是使用可识别的模板编写的。多年来,已经提出了许多模板,有些比其他的更加复杂。
本书中的模板包含了几乎所有现有反模式模板中反复出现的基本内容。然而,我们不会包含大量的可选元素。其他模板中包含的大多数附加元素用于简化分类或交叉引用,这些元素对于创建可搜索的模式或反模式目录非常有用,但在印刷书籍中则较少实用。因此,我们将省略这些元素,并包含以下内容:
-
名称:一个易于记住的标识符,用于唯一识别该模式并帮助架构师之间的讨论。
-
类型:在本书中,我们将根据认证技术架构师(CTA)复审委员会考试相关的领域对反模式进行分类。这既是为了帮助那些在 CTA 旅程中的人,也因为这对 Salesforce 架构师来说是一种熟悉的分类方法。
-
示例:我们将通过举例说明反模式如何发生,来介绍每个反模式。示例将是虚构的,但与现实中的事件相关。这将为反模式设定框架,并让你在深入探讨之前立即理解其中涉及的问题。
-
问题:本节将正式描述反模式试图解决的问题。这些是反模式旨在解决的实际问题,尽管在实践中使用它将证明是一个糟糕的主意。
-
建议的解决方案:反模式声称如何解决上一节中描述的问题,并且在某些情况下,这种解决方案看起来可能很有诱惑力。
-
结果:在结果部分,我们将概述应用反模式及其主要变体后,你可以期待得到的结果。我们将解释为什么这是一种不好的解决方案,尽管它在开始时看起来可能不错。
-
更好的解决方案:模板中的最后一部分将告诉你,在面对反模式所基于的问题时应该怎么做。并非所有问题都有简单的解决方案,但通常你能做得比应用反模式更好。
现在我们已经理解了反模式是什么,以及它们在本书中的结构安排,我们将继续解释作为架构师的你,如何通过使用它们来提升自己的技能。
反模式如何深化你的架构技能?
尽管理论上理解什么是模式和反模式,以及它们如何一般性地提供帮助是很好的,但你无疑希望从本书中获得的不仅仅是理论讨论。
在这一部分,我们将讨论从错误中学习的价值,无论是你自己的错误还是他人的错误,并展示我们将如何通过反模式在具体实例的背景下提升你的架构技能。
伟大的架构师如何从错误中学习
我们工作在一个失败是常态的行业中。Standish Group CHAOS 报告(这是在这方面最常引用的资料)在 2020 年估计,全球 66%的技术项目最终部分或完全失败。
这比我 20 多年前刚开始职业生涯时要好一点。当时,这个数字只有 70 出头。然而,尽管敏捷开发、云计算、人工智能以及 Salesforce 等伟大的软件平台出现了,情况有所改善,但改善的幅度仍然很小。
这令人沮丧,但它只证明了我的一位英雄——弗雷德·布鲁克斯——所说的“ 软件的复杂性是一个本质特性,而非偶然特性 ”,这不幸意味着我们永远无法找到一颗万金油来解决软件架构和设计中的所有问题。相反,我们面临的是如何合理管理这种复杂性的艰巨工作。做到这一点,是架构师的主要工作。
合乎逻辑的是,在一个高失败率和不可简化复杂度的领域,我们需要有良好的规则和指导方针来引导我们走上正确的道路。这就是模式和最佳实践的作用。它们是不可或缺的,但它们还不够。
要在我们的专业领域做到卓越,并能够设计出突破行业趋势的软件,我们不仅要从自己的失败中学习,还要从我们周围看到的那些失败的项目和糟糕的实践中学习。
这通常并不难做到。通常,当架构师被召入项目时,意味着已经有一个问题需要解决。把这些情况当作学习机会,并以这种视角进行分析,往往会带来巨大的收获。
然而,在这个方向上还有进一步的步骤,这就是反模式所提供的。它们涵盖了事物经常出错的方式,这种方式不仅允许事后学习,还能够进行实时干预。
虽然项目可能会失败,但它们并非随机地出错。其实有系统性的模式一次又一次地重复。学习事物如何以系统性方式出错,可以为你的工具箱增添一套全新的应对策略,帮助你将项目打造成那 34%没有失败的项目之一。
理解反模式不仅帮助你避免常见的陷阱,还增强你应对现代 Salesforce 架构复杂性的能力,包括人工智能和 DevOps 实践。这些见解对准备参加 CTA 复审委员会考试的人特别有价值,因为它们展示了对现代 Salesforce 架构中的挑战和最佳实践的深刻理解。
我们将通过一个解释性的例子开始这段学习之旅。
一个例子——英雄反模式
学习最好的方式就是通过示例。我们在本书中不会有机会涵盖很多管理层的反模式,所以我将用这个领域中的经典例子来展示模板是如何工作的,以及如何解读它以获得最大的收获。
首先,我们将展示反模式,然后提供分析,看看我们能从中学到什么。
Hero(开发生命周期和部署规划)
Tom 是制造行业中一个大型绿色田地 Salesforce 实施项目的项目经理,涉及销售与服务云,面向 2,000 名用户。这个项目原本计划非常简单——一个基础的 MVP,用于启动平台——并且项目的范围和人员配置也是如此。该项目计划在 6 个月后进入全面生产,实施阶段为 4 个月,随后进行测试、培训、部署和超关怀阶段。
实施的前 3 个月飞快过去,项目管理仪表盘上的一切依旧保持绿色。团队稳步推进,与外部咨询公司(提供专业资源的合作伙伴)的关系也保持良好。
然而,当 Tom 交付第一轮业务审查时,情况开始迅速发生变化。事实证明,许多详细需求在最初的范围中被遗漏,许多边缘案例也未被当前的配置所涵盖。业务方面的反馈是,除非包括一大批额外的功能,否则无法让系统上线。
Tom 去向指导委员会请求更大的预算和按计划增加的时间表,以应对业务需求。指导委员会同意了增加预算的请求,但告诉他,时间表是不可更动的。他必须在当前的时间框架内找到完成任务的方法。
Tom 从头开始重新规划项目。如果他从外部合作伙伴那里增加一些新资源,并向现有团队要求加班,他可以通过压缩测试和切换计划让一切适配。他将新计划发给团队,并附上一封激励人心的邮件,呼吁每个人都迎接挑战。
在接下来的一个月,项目再次出现延误,Tom 的新计划看起来越来越不可能成功。并不是发生了什么重大问题,而是许多小问题没有按时完成,或者因为误解需要重新做。特别是,他从外部合作伙伴带来的新顾问似乎犯了很多基本错误。
Tom 打电话给他的老板,IT 高级总监,告诉她当前的情况,并请求帮助延长项目时间表。她告诉他,时间表已经向公司董事会承诺,如果不能按时完成,某些人将会被辞退。她说,现在是团队全力以赴,完成任务的时候了。
汤姆回到团队,传达了消息,再次呼吁每个人都尽全力把事情推进。遗憾的是,大多数人已经在尽自己所在情况下最大的努力。而且与外部合作伙伴的关系已经恶化,他们不愿意再加班,除非能获得额外的资金,而汤姆的预算无法支持这一要求。
然而,还是有一些亮点。特别是两位年轻的技术人员——凯莉和内加什,展现出愿意超越常规去完成工作的态度。在最后一个月的交付过程中,他们几乎全天候工作,汤姆在背后为他们加油:
图 1.3 – 当你陷入英雄反模式时可能会有的危险感觉
在他们二人的合作下,最终在最后阶段清除了足够的新特性和变更请求,汤姆变得有信心认为他能满足足够的项目需求,从而避免项目启动成为一场灾难。虽然会有例外情况,但他可以稍后找到应对方法。只要即将到来的上线顺利进行,项目仍然有可能成功。
然而,用户验收测试(UAT)却给项目带来了麻烦,因为发现了重大质量问题。指导委员会召开了危机会议,最终决定将上线推迟一周。团队必须在这段时间内全力以赴解决问题。
尽管每个人都在努力,但责任不成比例地落在凯莉和内加什身上,他们两人开始表现出持续工作带来的压力。汤姆在每个机会中鼓励他们,并公开表扬他们。他还承诺项目完成后会给予他们现金奖励和额外的假期。
重测的日子终于到来,尽管许多问题已经得到令人满意的修复,但仍然有相当多的遗留问题,包括一些之前已修复但现在又重新出现的问题。
指导委员会召开了另一次危机会议,决定尽管问题存在,仍然推进上线。这些问题将在超照护期内修复,但在短时间内是可以容忍的。
接下来几周,汤姆、凯莉和内加什的生活都充斥着不断的紧张节奏。随着问题的不断出现、修复与重现,他们从一个紧急情况忙到另一个。凯莉和内加什开始承受不住压力,但由于没有其他了解配置的资源,他们实际上被迫继续坚持下去。
最终,问题得以平息。重要的漏洞已经修复,业务部门为遗漏的事项采取了手动解决方案,生活也逐渐恢复正常。汤姆召集团队举行庆功会,但气氛却显得比较低调。
在度完额外假期后,Kayleigh 和 Negash 都接受了大公司咨询公司的邀请,导致公司失去了支持其新实施平台大部分功能的人。
问题
英雄反模式通常声称修复一个紧急的交付问题,这个问题可能发生在项目环境中,如我们的例子,或者在正常运营过程中。当它发生在正常运营模式时,通常是在一个系统问题解决已变成日常事务的背景下。
通常,问题发生在以下几个因素特征的背景下:
-
解决紧急问题所需的资源有限,且有充分的理由说明此时无法引入新的资源。
-
项目有一个紧迫的时间表,人们认为这是不可更改的,或者问题已经上线,紧急且影响到重要业务用户,以至于造成了大量的噪音。
-
对问题的了解集中在少数几个人头上——也就是一些愿意承担角色的人,如 Kayleigh 和 Negash,或者通常是唯一具有技术知识能在当时解决问题的首席开发人员。
-
这种情况被认为是某种特殊的情况:要么这是一个新项目,没有先例,要么问题被认为如此独特,以至于无法为其做计划。
-
危机元素在容易滋生英雄反模式的情况下通常非常明显。有时,公司的未来成功甚至生存的关键部分会因此受到影响。
这些因素都会让问题看起来在有限的时间内修复更为重要,并使英雄反模式显得具有吸引力。
提议的解决方案
英雄反模式提议通过允许个人或小团体承担过多的责任来有效地解决前一部分描述的问题,要求他们在必要时付出一定的代价,完成任务。
这对于管理层和参与其中的人来说,出于多种原因,可能都具有吸引力:
-
这种努力往往会在短期内取得一些成果,给人一种势头和成功感。
-
每个人,或者至少几乎每个人,都希望成为英雄,并获得表扬和奖励。对一些人来说,这值得为了额外的努力而带来的不便。
-
总是可以想象,当前的情况在某种程度上是独特的,不代表组织内部存在更深层次的流程或文化问题,从而将所做的事情合理化为例外。
-
即使我们承认存在潜在问题,通常也可以把这些问题暂时搁置,认为以后再解决。当然,在依赖英雄反模式的组织中,“以后”永远不会到来。
英雄反模式有几种常见变种,值得一提:
-
超人模式,一种变体,通常是指将某个人(通常是高级技术人员)美化并视为唯一能解决特定系统严重问题的人。通常,这种神话会自我延续。
-
新手,前面示例中展示的变体,指的是初级团队成员承担额外责任,迎接摆在他们面前的挑战。
-
没有时间进行知识转移,英雄们因似乎永无止境的时间紧迫而无法将必要的知识传授给其他人。
虽然这个反模式很有诱惑力,许多人在职业生涯中多次落入其陷阱,但它几乎总是会带来负面的长期后果,这是我们接下来要探讨的内容。
结果
尽管英雄反模式往往能带来短期的良好结果,这也是它持续吸引力的主要来源,但依赖这一反模式来完成任务的组织,往往会随着时间积累一长串负面结果。
以下是一些最常见的负面结果:
-
创建单点故障,极大地增加了组织的风险,如果英雄“被丢到车下”,且英雄在与组织谈判时会拥有很大的杠杆作用。
-
随着时间的推移,英雄会开始感受到压力,就像我们示例中的凯莉和内戈什一样,但他们改变局势的选择非常有限。这种情况非常容易导致职业倦怠,带来第一个问题的所有后果,以及由于压力而导致英雄犯严重错误的风险。
-
英雄无法扩展。这意味着组织将无法以比英雄能处理的更大的带宽来部署项目。在某些情况下,这可能会严重限制新计划的开展。
-
英雄是不可复制的。你无法轻易复制英雄或他们的特殊能力,因此你在创建一个可预测、可重复的流程时,选择非常有限。
-
英雄可能会积累严重的技术债务。这通常因为他们必须在压力下迅速行动,且没有真正的监督而未得到有效管理。这可能导致长期的维护问题。
-
英雄完成任务的过程透明度很低,导致缺乏可预测性和可管理性。
-
英雄没有时间解释事情是如何实施的,因此通常缺乏或完全没有文档。
-
剩余的团队成员可能会感到失去权力、被忽视和缺乏动力,因为所有的注意力都集中在英雄身上,其他人几乎没有机会以非英雄方式做出贡献。
在所有的反模式实例中,你不一定会看到所有这些负面结果,而且遗憾的是,这份清单也并非详尽无遗。但希望这些足够让你在应用这个反模式时三思,并且思考更好的选择,这是我们接下来要探讨的内容。
更好的解决方案
英雄反模式的根本问题在于,你依赖于那些通常拥有隐藏知识的特定个体,他们辛勤工作(通常是过度辛勤工作)来完成任务,而不是依赖于可重复、透明和可管理的流程,这些流程将使你在环境和参与人员发生变化时仍能继续交付。
因此,摆脱英雄反模式的主要方法是着手改进流程,并系统地在团队中传播技能和知识。在我们的例子中,潜在的问题包括范围管理、初步的发现工作、治理以及对现场实际问题的理解,还有项目的结构方式,导致它以大爆炸的方式上线,而不是以小的增量发布。
在不同的组织中,具体的干预措施如何提供最大杠杆作用会有所不同,但以下是一些值得关注的方面:
-
向 DevOps 文化转型,实施更小的增量发布,这些发布具有较低的风险特征
-
拥有多功能团队,进行频繁的直接协作和同行评审,以便传播知识
-
鼓励并奖励领导和专家更多地去指导和培养年轻人,而不是扑灭最新的火灾
-
在项目中引入更好的风险管理和治理,以确保当事情出错时(如预期那样),你可以拥有适当的应急措施
-
挑战那些将取得大胜利的文化规范,这些胜利往往是在逆境中取得的,而不是专注于定期进行稳定、不戏剧化但可重复的进展
-
在规划、构建和运营系统时,强调角色和流程,而不是个人,尤其是在与更广泛的利益相关者沟通时
-
通过捕捉技术债务、风险以及依赖此模式时组织失去的可复制努力的机会,揭示英雄反模式的成本
-
确保在项目开始时规划好详细的需求和边缘案例,以减少你需要英雄的可能性
事实上,完全避免英雄反模式并不总是可能的。有时,事情已经陷入困境,而只有一个人能够解决问题。我们需要认识到,这并不是一个好情况,而是一个反模式,我们需要努力解决,以避免它的再次发生。你越是这样做,就越不需要依赖英雄,也就越少需要扑灭火灾。
在讲解完第一个真实的反模式示例后,让我们更深入地分析一下,看看如何最大化从中学到的东西。
分析该示例
英雄反模式是一个经典的模式,几乎所有经验丰富的 IT 专业人士在职业生涯中都会遇到它。然而,尽管它很有趣,但在本书中,我们将更多地关注提取更大的模式,以便从这些例子中汲取经验,提升我们的架构技能。
在本书中,我们将在每章的结尾部分设置一个小节,为你提取关键的学习要点,帮助你在未来的架构之路上不断进步。我们将在实现“心到实战”的实践过程中做到这一点,同时,我们还会为那些准备参加 CTA 考试的人列出专门的学习要点。
考虑到英雄反模式,以下是一些你可能提取出的实际学习要点:
-
当你面临一个需要团队中某些人或所有人付出额外努力的危机时,花时间回顾一下导致这种情况的过程失败。将这些记录下来,以备未来参考。
-
依赖少数几个极其熟练的人,长期来看可能会带来危险,即使现在这种做法有效。
-
你可能会感受到超越常规的压力,这可能反映了一个技术优先级不正确的文化。如果可能,你可能想要挑战这种文化。
-
尽力赋能并培养初级员工,避免陷入必须成为英雄的境地。
-
在项目和技术层面上,积极倡导良好的治理,并记录和弥补因“特殊”情况而积累的技术债务。
查看 CTA 评审委员会,你可以注意到以下几点教训:
-
小心建议“大爆炸”式的交付方法。它们可能是正确的选择,但通常会导致本示例中提到的问题。除非有特定原因,否则应优先使用敏捷、增量式的方法。
-
确保你包括必要的治理职能,包括项目管理办公室(PMO)、指导委员会、设计主管,可能还有变更咨询委员会。在这个例子中,如果后两者到位,许多问题本可以避免。
-
清楚地表达风险和风险管理。提前列出风险,并准备好讨论如何管理和缓解它们。
虽然我们能直接提取许多学习要点,但我们鼓励你深入探讨这一方法,看看你还能从中获得多少收获。从反模式中学习是一个持续且非常有益的过程,特别适合有抱负的架构师。
除了从英雄反模式中获得的传统教训外,还需要考虑这种模式如何与现代趋势(如人工智能和 DevOps)相交叉。例如,在 DevOps 环境中,依赖单一“英雄”来管理部署可能会导致显著的瓶颈和集成问题,从而突出持续集成和频繁检查等实践的重要性。
类似地,在 AI 项目中,当依赖单一的数据科学家或 AI 专家来交付复杂的 AI 解决方案,而没有足够的支持或知识传递时,就会出现 Hero 反模式。这可能导致精疲力尽和缺乏可扩展性,强调了多功能团队合作的必要性。
有了这些知识,我们已经对反模式有了基础性的理解,并且知道它们如何帮助我们更好地掌握 Salesforce 架构。接下来只需要在深入探讨系统架构领域的反模式之前,总结一下我们的进展。
摘要
呼,刚才讲了这么多背景知识!感谢你坚持下来。现在你已经了解了关于反模式的关键事实,并且可以继续阅读本书,掌握如何从反模式中学习。
在进入接下来的章节之前,记住以下几点:
-
重要的是不要仅仅将反模式视为不良实践。不良实践是显而易见的,但反模式则是阴险的。它们伪装成好的解决方案,在某些情况下,即使是经验丰富的专业人士也可能会被其说服。这也是为什么反模式如此有趣的原因。
-
虽然本书中会介绍很多独立的反模式,但重要的是通过比较和对比这些反模式,提炼出其中的相似之处和元模式。我们将在本书的分析部分为你做一些这样的工作,你也应该尝试为自己做这项活动。
-
虽然我们将重点讨论 Salesforce 环境中的内容,但你将学习到的许多模式同样适用于其他平台。一些模式甚至是经典的,许多经验丰富的架构师都会了解。
在本书的后续部分,记住反模式不仅仅是不良实践,它们是具有欺骗性的解决方案,在某些情况下可能看起来很有吸引力。在这第二版中,我们扩展了探讨内容,加入了与 AI 和 DevOps 相关的新反模式,以反映 Salesforce 生态系统中的最新趋势和挑战。通过理解这些模式及其含义,你可以提升自己的架构技能,更好地应对现代 Salesforce 项目的复杂性,无论是在实际项目中,还是为 CTA 审核委员会的考试做准备。
现在这些都讲完了,我们准备详细讨论第一个架构领域:系统架构。
第二章:如何保持系统架构的整洁
本章将从探讨如何通过缺乏实施和治理的规范性方法来混乱你的系统架构开始。我们将审视经典的“烟囱”反模式,在这种模式中,系统是孤立建设的,几乎不考虑标准或共同的抽象,导致架构碎片化且难以维护。我们还将讨论“大泥球”反模式,它的特点是缺乏结构和组织,最终导致无法维护的系统。
接下来,我们将介绍“架构即需求”反模式,这是一种常见的陷阱,即将架构决策仅仅视为需求,而没有考虑更广泛的系统背景和长期影响。我们将深入探讨这种方法的后果,如技术债务增加、可扩展性问题和适应性有限等。
接下来,我们将讨论系统之间过度耦合如何使系统变得脆弱且难以修改,并强调定义清晰边界和倾向于采用更松散集成模式的重要性。我们还将涉及 Salesforce 环境中组织繁殖的挑战,以及为了防止蔓延并确保一致性,制定明确的组织战略的必要性。
在本章中,我们将强调架构治理、技术标准和最佳实践在避免这些反模式和创建强大、可维护的 Salesforce 系统中的关键作用。我们将提供关于如何应对组织孤岛、确保利益相关者的支持,以及如何平衡个别需求与长期架构可持续性之间的见解。
在当今快速发展的技术环境中,人工智能 (AI) 和自动化在 Salesforce 架构中扮演着越来越关键的角色。在我们探索各种反模式的过程中,我们还将考虑 AI 驱动的功能和自动化流程如何加剧这些问题,或者在正确实施的情况下,如何帮助缓解这些问题。理解传统架构问题和新兴 AI 能力之间的相互作用,对于创建强大、未来-proof 的 Salesforce 解决方案至关重要。
到本章结束时,你将深刻理解需要避免的关键架构陷阱,并了解在设计和实施 Salesforce 解决方案时可以采用的策略。你将掌握创建可扩展、可适应、并与组织不断变化的需求对接的系统所需的知识和技能。
在本章中,我们将涵盖以下主要内容:
-
烟囱反模式如何让系统只能在孤立环境中工作,以及你可以做些什么来避免构建烟囱
-
大泥球反模式是什么,为什么系统会退化到这种状态,以及如何防止你的系统陷入这种境地
-
探索“架构即需求”反模式及其对 Salesforce 实施的影响
-
强耦合如何使系统脆弱且可能无法使用,以及如何划定更清晰的系统边界以避免此问题
-
Salesforce 环境中没有治理的组织增长问题以及制定清晰组织策略的重要性
-
架构治理、标准和最佳实践在创建可维护、可演进的 Salesforce 系统中的关键作用
完成本章后,你将牢牢掌握常见的架构反模式,这些反模式可能会影响 Salesforce 实施,并了解应对这些问题的策略。你将准备好领导团队为组织的 Salesforce 项目建立强大的架构基础,确保这些项目提供持久的价值并支持你的业务目标。
混乱的系统景观
混乱系统景观的最简单方式,正如我们将看到的,是以本地、无结构、治理不善的方式进行实施。虽然小型本地项目有许多吸引力,但它们很容易变成反模式,对整体企业架构产生严重的负面影响。我们将首先讨论经典的垂直烟囱反模式,这是这类项目的常见后果,然后看它的组织对等物——垂直烟囱企业。
垂直烟囱
垂直烟囱是一个系统,它的构建没有考虑标准或共同的抽象,导致系统可能能够运行,但难以维护、扩展或与其他系统互操作。
一个例子
John 是 DreamCo 的 CRM 经理,这是一家定制旅行配件的供应商。公司决定投资实施一个小型 Salesforce Sales Cloud 系统,取代已经运行超过十年的旧 Siebel 系统。虽然最初有些担心,但 John 对于这个项目变得相当兴奋,因为它承诺解决一些他们用旧 CRM 系统无法解决的棘手问题。
DreamCo 雇佣了一家小型本地 Salesforce 咨询公司来进行实施。最初,这项工作取得了巨大成功;销售团队喜欢这个新工具,John 要求的许多功能也得到了迅速实现。然而,过了一段时间,进展似乎变得缓慢,变更的成本也上涨了。DreamCo 的 CIO 评估认为,他们的业务需求现在已经过于复杂,本地小型咨询公司无法管理,于是聘请了一家领先的 Salesforce Summit 合作伙伴来接管。
与此同时,DreamCo 的客户服务负责人决定委托第三家 Salesforce 合作伙伴为公司呼叫中心实施 Salesforce Service Cloud。在最初的阶段,John 已经学到了很多 Salesforce 知识,并开始担心不同合作伙伴或实施之间没有共同的约定、标准、方法论或工具。销售部门和客户服务部门似乎也使用了非常不同的数据模型来表示基本相同的内容。
图 2.1 – 初步实施后的 DreamCo 组织结构
John 将这些问题提给了首席信息官,并请求预算来雇佣一名架构师,并对现有系统进行一些重构,以使它们更加一致。他被告知,虽然他的想法很好,但目前无法承担,但他应该为明年的预算提出预算请求。
此时,DreamCo 收购了一家较小的公司,该公司通过机场自动售货机销售旅游配件。该公司 reportedly 拥有非常强大的 Salesforce 实施,比 DreamCo 更为先进,包括销售、服务和现场服务模块。John 的任务是找到一种方法,将这两个 Salesforce 组织合并成一个,而不要求两个组织从根本上改变他们的流程。
John 与 Summit 合作伙伴进行沟通,探讨合并的选项。他们提出了一个满足基本要求的方案,但成本远高于预期。合作伙伴解释说,DreamCo 组织中的技术复杂性过高,导致与新组织的整合非常困难。此外,他们建议不要走合并的路线,而是建议 DreamCo 将所有人转移到最近收购的公司的组织中,并调整流程以使其正常运作,而不改变技术。
经过一些内部讨论,DreamCo 决定还是继续进行合并。然而,问题几乎立刻就开始出现:
-
首先,涉及的不同供应商之间的协作非常困难,导致了一个局面:主导合作伙伴实际上需要逆向工程许多功能,以便理解它们。
-
其次,实施进展非常缓慢,John 现实地认为项目无法按时完成。
-
第三,错误率非常高,每个测试周期都会出现许多重复的错误。所有这些都在朝着一个项目发展,这个项目将显著超出预算,延迟进度,并且质量远低于预期。
John 开始深入调查细节,从项目中涉及的各种技术人员那里,他得知了一些令人担忧的事实。首先,基本的命名约定完全不同,不仅在 DreamCo 和 NewCo 组织之间不同,甚至在 DreamCo 组织内部也存在至少三种完全不同的约定。此外,功能的实现使用了完全不同的方法和工具集,有时相同的功能在系统的不同部分以不同的方式重新实现。
系统的不同部分还存在一些自定义字段和对象,它们在不同的地方以细微不同的重复形式存在。最后,许多第三方工具被用来提供功能。然而,这些工具及其功能从未得到适当的文档化,在供应商更换后,组织中没有人知道如何使用它们。再加上 DreamCo 和 NewCo 两个组织之间找到共同语言所带来的内在复杂性,大多数技术团队开始绝望地举起双手。
图 2.2 – DreamCo 合并场景
约翰将此报告给高级管理层,情况升级成一场重大危机。最终,在经过长时间的争执后,DreamCo 放弃了合并两个组织的计划,决定暂时将它们分别保留,并将数据在其他地方合并用于报告。
问题
如何在一个部门独立、权力分散到各个封建领地、技术团队彼此独立且没有强有力的架构或技术标准中央权威的组织中实施 IT 系统?通常的答案是烟囱式反模式。鉴于这些组织特征的普遍存在,"烟囱式"反模式是你作为架构师最常遇到的反模式之一。
让我们不要忽视解决这些问题的困难。即使有高级管理层的支持,改变组织结构或文化可能需要数年的转型,即便如此,许多不幸的做法仍可能存在。
因此,当你是一个雄心勃勃的经理,在这样的组织中需要一个新的 IT 系统时,直接在你自己小小的王国里推进并实施某些东西,与那些你个人信任的人一起工作,以符合你需求的方式进行,而不太考虑其他部门,确实很有诱惑力。没有强有力的公司 IT 治理和企业架构支持,大多数 IT 部门对此无能为力。
因此,"烟囱式"反模式确实为一个真实的问题提供了答案,我们将在下一节中讨论。但它是一个可靠地导致不幸结果的答案。
提议的解决方案
从根本上讲,"烟囱式"解决方案试图通过在孤立的环境中构建解决方案来解决许多组织中固有的协调问题,而不考虑更广泛的关注点或需求,使用实施团队偏好的任何工具和标准。这样,你可以直接进行操作,同时绕过公司内部的官僚主义。
这是一个在许多方面都很有吸引力的解决方案:
-
你不必参与跨部门合作或解决棘手的内部政治问题。
-
你的技术团队通常很喜欢它,因为他们可以使用任何他们偏好的工具来完成工作
-
它在短期内通常效果很好,能够迅速满足需求并创造局部价值,通常价格也非常合理
-
对于没有强大中央 IT 领导力的组织来说,它可能是默认的操作方式,并且可能会变成“事情的做法”
如果我们生活在一个更简单的世界里,组织能够将其操作划分为彼此独立、不需要太多协作即可完成任务的不同小组,系统也不需要支持跨工作流或跨系统集成,那么烟囱式模式实际上是一个完全合理的软件开发方法。
然而,实际上,大多数组织确实需要让他们的系统跨多个部门和用例协同工作,这时问题就开始显现,正如我们在下一节中将看到的那样。
结果
如前所述,正如我们在示例中看到的,烟囱模式通常最初运行良好。对于一个由单一团队使用的特定解决方案,以这种本地方式构建并没有什么固有的缺点。正如我们所看到的,当我们有多个不同的参与者使用同一基础平台(例如我们提到的销售和服务部门)、尝试将系统扩展到它并未设计过的用例时,问题开始积累,而且当我们需要系统与其他外部系统良好协作时,问题更加明显。
在 Salesforce 上,多个不同的模块在同一个组织中同时运行并利用共享数据模型、用户界面和技术配置是很常见的情况。不幸的是,如果没有一致地实现这些模块,特别容易出现类似“烟囱”问题。
随着时间的推移,烟囱反模式的指示器通常包括以下几点:
-
理解代码库的难度增加,尤其是对于与系统合作的新团队
-
系统不同领域中的架构设计和实现模式不一致
-
由于系统的一致性和灵活性日益下降,用户体验和用户价值逐渐降低
-
每当需要实施新需求时,都会遇到极大的困难
-
系统与其他系统集成的难度很大
-
系统很难融入全球流程;例如,一个整合的 DevOps 管道
-
错误率不断增加,既包括开发过程中的错误,也包括生产环境中的错误
-
由于所有这些因素,变更的成本越来越高
炉膛管(stovepipe)往往会恶化的根本原因是缺乏共同的标准、实践、模式和工具。无一致性增加了技术团队的认知负担,使得一切变得更加困难且容易出错,同时也提高了整体的学习曲线。原本的团队可能理解它,但随着时间的推移,这种理解会丧失,结果往往是变得更加不一致,而不是为了将其重构成更易理解的状态而做出集中的努力。
通过将构建孤岛的团队与运作良好的敏捷团队进行比较,可以有效地理解出错的原因。一个敏捷团队也可能在相对孤立的环境中工作,由赋权的产品负责人做决策。然而,他们将遵循组织内已被接受和深刻理解的标准、实践、模式和工具,并且会使用稳定的接口进行关键集成和对关键系统组件的共同抽象。这样,协调会通过这些共同的基础标准自然而然地进行,而你最终不会构建出一个孤岛系统,而是一个良好调整的系统成员。
更好的解决方案
事实上,许多组织存在较强的孤岛现象,因此在构建、实施或变更系统时,解决业务层面的协调问题变得非常困难。作为架构师,处理这些问题应该是我们的日常工作的一部分,以避免构建孤岛系统,并确保我们的平台(如 Salesforce)在长期内继续发挥价值。
尽管一些能够组织上打破孤岛、提高协作的变革性举措通常超出了我们的能力范围,但我们可以可靠地做很多事情来改善这种状况:
-
定义清晰的架构模式和实践,以便不同团队之间使用,并创建共同的抽象层次
-
制定关于如何实现不同内容的约定,既包括宏观层面的(例如,何时使用流程,何时使用触发器),也包括微观层面的,例如编码规范
-
为所有技术领域(如报告、BI 或数据治理)采用标准,以确保一致性
-
为跨系统集成创建稳定接口提供强有力的指导,并为不同的使用场景提供集成模式
-
为 Salesforce 项目的实施制定共同的方法论,以确保一致性
-
为整个开发生命周期的所有元素采用一致的工具,以促进跨团队和跨系统的理解
-
强力执行这些标准和实践
作为 Salesforce 架构师,我们处于一个有利的地位,因为很多工作可以从已经存在的良好实践中获得,这些实践要么是 Salesforce 自己建立的,要么是更广泛的 Salesforce 社区所共享的。你可以在 Salesforce 架构师网站上找到许多优秀的资源,Salesforce 也最近推出了 Salesforce 操作、治理和架构框架(SOGAF),以帮助我们理解 Salesforce 治理的最佳实践:
图 2.3 – SOGAF 元素
然而,我们始终有责任在我们自己的组织中采纳、适应并实施这些方法。这也包括添加与我们特定情况相关的业务标准和实践,并以一种能够在整个组织中产生共鸣的方式传播这些标准和实践。
在 Salesforce 中实施 AI 能力时,要小心避免创建 AI 筒仓。与更广泛的 Salesforce 生态系统集成不良的孤立 AI 模型或预测分析工具,可能导致碎片化的洞察和不一致的用户体验。相反,应该制定一个与整体 Salesforce 架构相一致的统一 AI 战略,确保 AI 驱动的功能能补充并提升平台上的现有流程。
需要注意的是,有时候标准需要被打破。在某些情况下,你需要不同的工具、方法或模式来完成任务,但如果你希望避免最终建造出筒仓式系统,你应该有一个标准作为偏离的依据。
关于筒仓企业的说明
到目前为止,我们讨论的这个模式主要集中在系统层面。然而,敏锐的读者不会忽视,许多在系统层面出现的问题实际上与组织层面的问题相关,尤其是某些组织倾向于在孤立的环境中工作,并且存在低效的政治行为。
图 2.4 – 组成筒仓企业的筒仓景观
因此,存在一种组织层面的筒仓反模式,称为筒仓企业,重点关注组织因其结构性问题而倾向于产生筒仓式系统。虽然我们可以轻松认识到这种反模式,但作为 Salesforce 架构师,我们的职责通常不包括解决这种层面的问题,因此我们在讨论中主要关注系统层面。
架构即需求
架构即需求 反模式 发生在组织将架构决策视为仅仅是另一组需要收集和实施的需求,而不是作为指导系统设计和演进的基础框架时。
一个示例
Sarah Chen,GlobeTech Industries 新任命的企业架构师,靠在椅背上叹了口气。她被邀请来帮助公司现代化老旧的 CRM 系统,而 Salesforce 实施项目似乎是建立一个强大、可扩展架构的完美机会。拥有 15 年经验的她,以精密的规划和看大局的能力闻名。然而,当她凝视着挂在办公室墙上的项目时间表时,她不禁感到事情已经偏离了轨道。
Salesforce 实施的启动会议充满了兴奋和雄心勃勃的目标。销售、市场和客户服务的部门负责人都提出了他们的愿望清单,每一项都比上一项更复杂。Sarah 曾试图引导讨论,聚焦于建立整体架构原则,但她的建议只收获了空洞的目光和不耐烦的点头。
“我们没有时间做这些高层次的东西,”销售总监 Jack 不以为然地说,“我们需要尽快让这个系统上线。我们的竞争对手凭借他们花哨的 AI 驱动销售预测已经在抢占我们的市场。”
Sarah 曾尝试解释一个稳固架构基础的重要性,但她的话似乎没能引起任何反响。项目经理 Tom 更关心的是完成需求和按时交付,而不是考虑决策的长期影响。
随着时间的推移,Sarah 发现自己在进行一场艰难的战斗。她起草了一份全面的架构愿景文档,概述了数据治理、集成模式和可扩展性等关键原则。但当她将其呈交给指导委员会时,她遭遇了困惑和冷漠的反应。
“听起来很不错,Sarah,”CIO 看了看手表说,“但你能把这些内容提炼成我们能实际执行的需求清单吗?我们需要的是具体的交付物,而不是抽象的概念。”
尽管感到沮丧但不屈不挠,Sarah 尝试在项目的需求驱动方法框架内进行工作。她参加了冲刺规划会议,希望能将架构考虑因素融入开发过程中。但往往,她发现自己无能为力地看着团队做出一些决定,这些决定将对系统未来的灵活性和可维护性产生深远的影响。
一个特别具争议的问题出现在 AI 驱动的潜在客户评分系统的实施上。销售团队坚持认为这个功能至关重要,认为它是他们保持竞争优势的关键。Sarah 认识到其潜在价值,但对它如何与整体 Salesforce 架构进行集成感到担忧。
“我们需要仔细考虑这个 AI 系统如何与我们现有的数据模型进行交互,”Sarah 在项目会议中曾提出过这个观点。“我们还应该思考 AI 模型的长期治理,以及如何管理算法中的潜在偏见。”
但她的担忧被一旁忽视了。Sales 部门的 Jack 已经与第三方供应商进行了谈判,他们急于推进项目。
“听着,Sarah,”Tom 尝试保持外交辞令地说道,“我理解你的担忧,但我们有一个紧迫的截止日期要赶。我们先实施系统,架构方面的问题可以稍后再考虑。”
Sarah 离开会议时感到沮丧。她知道将 AI 实施视为只是另一个需要勾选的要求,很可能会导致后续问题。但在没有得到其他团队成员支持的情况下,她束手无策。
随着项目的推进,Sarah 的担忧开始变成现实。匆忙实施的潜在客户评分系统造成了性能问题,在高峰使用时段,整个 Salesforce 实例的运行速度大幅下降。数据模型变得错综复杂,冗余字段和不一致的命名规范使得生成准确报告变得困难。
与其他系统的集成变成了一场噩梦。团队选择了快速的点对点集成,而不是采纳 Sarah 提出的 API 优先方法。因此,各部门之间的数据不一致问题开始显现,而且任何一个系统的变动都会产生难以预测或控制的连锁反应。
用户采用率也在下降。缺乏连贯的架构愿景导致了支离破碎的用户体验,各个模块更像是独立的应用程序,而不是统一整体的一部分。Sarah 已经记不清她收到多少关于导航不一致和工作流程混乱的投诉。
项目进行到第六个月时,问题达到了顶点。首席执行官召开了一次紧急会议,讨论 Salesforce 实施中日益严重的问题。Sarah 坐在会议室里,周围是沮丧的高管和士气低落的项目团队成员。
“我以为这个新系统应该让我们的生活更轻松,”首席执行官说道,声音中带着失望。“结果,似乎我们只是制造了更大的混乱。有人能解释一下我们是怎么走到这一步的吗?”
所有人的目光都转向了 Sarah。她深吸了一口气,知道这是她终于可以为架构的重要性辩护的机会。
“我们问题的根源,”Sarah 开始说道,“是我们一直将架构视为仅仅是另一个需求,而不是它本应具备的基础框架。我们过于专注于交付单独的功能,以至于忽视了大局。”
她接着解释了缺乏架构治理如何导致当前的局面:一个支离破碎的系统,难以维护、扩展或适应变化的业务需求。她详细说明了一个正确的架构方法如何避免他们所面临的许多问题,并且仍然可以帮助他们纠正方向。
令她惊讶的是,她看到会议室里的人纷纷点头表示理解。即使是 Jack,他曾是最强烈反对她架构建议的人之一,此时也显得有些不好意思。
“我想我一直专注于那些炫酷的 AI 功能,没考虑到这些东西是如何结合在一起的,”他承认道。
CEO 向前靠了靠,显得很感兴趣。“那么,Sarah,你现在建议我们做什么?我们还能挽救这个项目吗?”
Sarah 感到了一线希望。她迅速制定了一个计划,暂停新功能的开发,专注于重构现有的实施,以使其符合正确的架构原则。她提议成立一个架构审查委员会,以确保未来的决策能从整体系统架构的角度出发。
“这不会容易的,”她提醒道,“这可能意味着一些短期的痛苦。但如果我们现在不解决这些架构问题,它们只会变得更加昂贵和难以修复。”
令她松了一口气的是,房间里的反应是积极的。CEO 批准了 Sarah 的计划,她离开会议时感到既被证明了自己的正确,也充满了重新振作的决心。
在接下来的几个月里,Sarah 领导了重新结构化 Salesforce 实施的工作。这是一项具有挑战性的工作,需要长时间的工作和艰难的对话。但渐渐地,她看到系统变得更加协调和可维护。
那个 AI 驱动的潜在客户评分系统被重新实现,这一次充分考虑了数据流和模型治理。团队采纳了更标准化的集成方法,创建了一个灵活的 API 层,能够更轻松地适应未来的变化。数据模型被重构,以消除冗余并提高一致性。
随着架构的逐渐稳固,Sarah 注意到团队的动态发生了变化。开发人员开始欣赏清晰的架构框架带来的好处。项目经理们发现规划和估算工作变得更容易了。即使是那些最初对“架构问题”持怀疑态度的业务利益相关者,也开始看到系统性能和适应性提升所带来的好处。
一年后,在那次关键会议之后,Sarah 站在公司年度全体员工大会的讲台上,讲述 Salesforce 实施的成功故事。这个系统现在已经成为 GlobeTech 的骄傲,拥有很高的用户采纳率,并具备了迅速推出新功能和适应市场变化的能力。
“我们学到的教训,”莎拉在总结她的演讲时说道,“是架构不仅仅是一组抽象的原则,或者在项目计划中要勾选的另一个框。它是构建系统的基础,使我们能够真正满足现在和未来的业务需求。”
问题
架构作为需求反模式试图解决的核心问题是如何设计一个满足多样化且有时相互冲突的利益相关者需求的系统架构。
在多个利益相关者参与的复杂项目中,每个小组通常都有自己的优先事项、技术偏好和功能需求。平衡这些相互竞争的需求,同时确保整体系统的一致性和长期可行性,是一个重要的架构挑战。
没有清晰的架构愿景和指导原则,项目团队可能会陷入将架构仅仅视为一组需要收集和逐步实现的需求的陷阱。他们专注于满足个别利益相关者的需求,而没有考虑整体视角以及设计决策的长期影响。
这种方法可能导致多个问题:
-
缺乏系统级思维:通过将架构视为一组离散的需求,团队失去了对整体系统环境的把握,未能考虑诸如性能、可扩展性、可维护性和互操作性等关键因素。
-
短期关注:将即时的利益相关者需求优先于长期架构可持续性,可能导致快速修复和临时解决方案,积累技术债务并妨碍未来增长。
-
不一致的用户体验:当每个模块或功能都是孤立设计时,缺乏统一的架构愿景,用户可能会在系统中遇到不一致的界面、导航和功能。
-
集成挑战:支离破碎的架构通常会导致点对点集成和定制接口的激增,使得系统脆弱,且随着时间推移,维护变得更加困难。
-
有限的适应性:缺乏明确抽象和关注点分离(SoC)的支离破碎架构使得随着业务需求变化,更难适应变动并增加新功能。
总体而言,导致架构作为需求的相关问题是常见的,因此,这种情况会时常发生。
提出的解决方案
架构作为需求反模式提出的错误解决方案是将架构决策视为仅仅是另一组需求,逐步收集并实现,而没有一个统一的整体愿景。
在这种方法下,项目团队与利益相关者进行沟通,收集他们的具体功能和技术需求,通常根据个人需求和偏好来优先考虑这些需求。然后,他们尝试逐步设计和构建系统,解决每个需求,而没有太多考虑更广泛的架构影响。
这个解决方案起初看起来很有吸引力,因为它似乎能够响应利益相关者的需求,并允许在各个功能上快速推进。利益相关者感到自己的声音被听到,并看到他们的具体需求得到了满足,从而产生了满足感和认同感。
然而,这种方法忽视了架构不仅仅是各个部分的总和。它是塑造系统结构、行为和演化的基础框架。将架构视为孤立需求的集合,忽略了它在确保系统级质量属性(如性能、可扩展性、安全性和可维护性)中的关键作用。
提出的解决方案往往更倾向于追求短期收益而非长期可持续性。通过优先满足利益相关者的即时需求,急于实施功能而没有深思熟虑的架构计划,团队积累了技术债务,导致了一个支离破碎、不一致的系统,随着时间的推移,维护和扩展变得越来越困难。
结果
陷入“将架构视为需求”反模式的后果可能是严重且深远的。随着时间的推移,系统会变成一个由紧密耦合的组件、定制集成和不一致的设计模式构成的复杂网络,使其变得脆弱、不灵活,并且维护成本高昂。
一些常见的结果包括以下几点:
-
技术债务积累:随着系统在没有统一架构愿景的情况下发展,快速修复和临时解决方案层出不穷,导致技术债务的积累。这些债务表现为复杂的代码、性能瓶颈以及增加的维护工作。
-
可扩展性和性能问题:缺乏精心设计的架构通常会导致可扩展性和性能问题,因为系统难以处理越来越大的负载和数据量。资源利用效率低、过多的数据库查询和未优化的代码都会导致系统性能缓慢。
-
集成复杂性:没有明确的架构边界和标准化的接口,不同模块或外部系统之间的集成变得混乱不堪,充斥着定制代码和脆弱的连接。系统中的一部分发生变化可能会引发不可预测的连锁反应,使集成变得脆弱且容易出错。
-
有限的可重用性和可维护性:缺乏模块化、松耦合的架构妨碍了代码的可重用性和可维护性。开发人员难以理解和导航代码库,导致开发时间增加,并且在做出修改时引入错误的风险也更高。
-
抗拒变革:随着系统的复杂化和纠缠,越来越难以引入新特性或适应不断变化的业务需求。架构的僵化和缺乏明确的 SoC(系统间隔分离)使得修改变得耗时、昂贵且容易产生意外副作用。
-
用户的挫败感和应急处理:不一致的用户体验、性能问题和有限的功能可能导致用户挫败感和不满。用户可能会诉诸于手动的应急处理或替代工具,以绕过系统的限制,这破坏了预期的好处和效率提升。
-
成本增加和市场推向时间(TTM)延迟:技术债务、维护挑战和开发低效的累积效应可能显著增加成本,并延迟新功能和增强的交付。组织可能会发现自己将更多资源投入到应急处理和系统大规模重构中,而非专注于创新和业务价值交付。
-
AI 的诱惑有时会导致组织将 AI 能力视为简单的功能需求,而非架构考量。这种做法可能导致草率的 AI 实现,无法充分利用 Salesforce 的本地 AI 能力,或与现有的数据模型和业务流程集成不良。为了避免这种情况,应以全局架构的思维方式来看待 AI 项目,考虑数据流、模型治理以及 AI 驱动的决策在 Salesforce 生态系统中的长期影响。
最终,作为需求的架构反模式可能导致系统未能实现其预期目标,阻碍组织的敏捷性,且成为企业的负担,而非推动者。
更好的解决方案
为了避免陷入“作为需求的架构”反模式,并为成功实施 Salesforce 奠定坚实基础,请考虑以下更好的方法:
-
从清晰的架构愿景开始:首先定义一个清晰的架构愿景和指导原则,使其与组织的目标、价值观和长期目标保持一致。该愿景应阐明关键的质量属性和设计原则,这些将决定系统的结构和行为。
-
早期参与架构师:从项目开始时就应聘请经验丰富的架构师提供战略指导,确保架构考量纳入需求收集和设计决策。架构师应与利益相关者紧密合作,了解他们的需求,同时保持全局视野。
-
将架构视为基础:将架构视为系统的关键推动力和基础,而不仅仅是另一组需求。在项目开始时定义清晰的架构模式、原则和指南,为设计决策提供指导。向利益相关者和开发团队传达这些架构选择背后的理由。
-
使用参考架构和最佳实践:利用已建立的参考架构、设计模式和针对 Salesforce 的最佳实践。这些经过验证的方法能够提供坚实的起点,并帮助确保系统遵循推荐的架构原则和指南。
-
平衡需求与架构:在满足个别需求和保持一致、可持续的架构之间找到平衡。做好权衡准备,并根据需求与整体架构目标的对齐程度优先考虑需求。持续评估需求对系统架构的影响,并做出明智的决策。
-
拥抱模块化和松耦合:设计系统时要考虑模块化和松耦合。将复杂的需求拆分为更小的、独立的组件,并定义清晰的接口。这种方法有助于提高可重用性、可维护性,并促进系统不同部分之间的更容易集成。
-
投资架构文档:创建并维护清晰简洁的架构文档,传达系统的结构、关键组件和设计决策。这些文档为开发团队、利益相关者和未来的维护人员提供参考,确保对系统架构的共同理解。
-
持续评估和优化架构:将架构视为一个与系统一起发展的活资产。定期审查和评估架构,发现改进的空间,解决新出现的问题,并与不断变化的业务需求对齐。积极进行架构重构和更新,以保持其相关性和有效性。
-
促进协作和沟通:鼓励架构师、开发团队和利益相关者之间的开放沟通与协作。创建讨论架构问题、分享知识和做出集体决策的论坛。培养一种持续学习和改进的文化,让团队成员可以贡献想法和见解,从而提升系统架构。
-
使架构与组织目标对齐:确保系统的架构与组织的更大目标和战略对齐。在做出架构决策时,要考虑可扩展性、性能、安全性和未来增长等因素。定期向利益相关者和决策者传达良好设计的架构所带来的价值和益处。
通过采用这些更好的解决方案,并采取积极的、全面的架构方法,组织可以为强大、可扩展且易维护的 Salesforce 实施奠定基础,从而提供长期价值,并支持业务不断变化的需求。
大泥球
“大泥球”是一个系统,它已经失去了所有内部结构和一致性,只有最初的创建者能够部分理解它,而其他人根本无法理解。
一个例子
DreamCo 已暂停对 Salesforce 实施的更多功能开发几个月。在此期间,约翰一直在制定一个计划,重构系统中的关键部分,使其更易维护。他与从第一天起就参与的不同团队中的大量技术人员进行了咨询,最终他认为找到了前进的道路。
然而,就在约翰准备与首席信息官(CIO)开会,推销他的想法时,地面上的情况发生了快速变化。DreamCo 最近聘请了 Ricky,一位来自大咨询公司的经验丰富的架构师,帮助理清如何整合 DreamCo 和 NewCo 的组织。虽然他通常支持约翰启动重构的努力,但显然这并不是他的工作重点。
反而,他提议将 DreamCo 的精力集中在 Salesforce 方面,开展一个整合项目,将两个组织合并。他建议亲自完成大部分技术工作,使用一个他之前在其他项目中使用过的第三方工具。这个整合将是点对点的,但它将可靠地在两个环境之间来回传输所需的数据,并终结业务方面不得不使用的复杂手动流程,这些流程是为了弥补过渡期间的差距。
鉴于业务的压力,CIO 决定按照 Ricky 的计划继续推进,并且在大约 2 个月的时间里几乎是单独实施了这个解决方案。约翰被告知,等整合完成后,他的重构项目将会获得批准。然而,一旦完成,CIO 批准了一套新的功能升级方案,涉及销售和服务团队的现有平台。约翰被告知,业务方面无法等待任何新功能,而是需要他领导开发一个新物流应用,该应用将被构建在一个单独的 Salesforce 组织中,由 Ricky 担任技术负责人。
新的应用程序在新环境中迅速构建,但约翰仍然担心它的构建缺乏结构或纪律。尽管业务方面似乎喜欢他们所看到的内容,约翰最终让步并允许事情继续推进,尽可能提供支持。虽然该应用程序本应是一个实验性原型,但业务决定按现有状态投入生产。主组织的升级需要很长时间才能完成,但生产部署的日子终于临近。
图 2.5 – DreamCo 大规模混乱架构
DreamCo 将在一个周末的单次部署中,将新的升级和新的物流应用程序部署到生产环境。所有人都在全力以赴,发布周围充满了积极的气氛,因为这些新功能以及新的应用程序都备受期待。最后几周略微受到了 Ricky 提交辞职的影响,因为他决定接受另一家咨询公司的工作机会。然而,他承诺在离开之前会做好文档并交接所有内容,因此没有人过于担忧。
在它即将上线的周末,约翰值班并急切等待结果。初始部署遇到了一些问题,完整的部署实际上直到周日下午才进入生产环境。测试团队开始进行冒烟测试,显然发布存在重大问题。主要功能区域似乎无法正常工作,DreamCo 与 NewCo 组织之间的集成开始出现错误,许多在主组织或物流组织中运行正常的测试脚本完全失败。关于 UAT 测试质量的问题被提出,但事实上,发布已经失败。
团队通宵忙碌,试图在早晨业务开始使用系统之前将其恢复到一个合理的状态。通信发布说明发布必须被撤回。DreamCo 的董事会要求首席信息官(CIO)就出了什么问题进行咨询。然而,没有人能够找出问题所在,而且对于物流应用程序和 DreamCo 与 NewCo 的集成,似乎由于 Ricky 的离开,尽管已经进行过知识转移会议,现在无法解决任何问题。
经过一周的相互指责后,CIO 被解雇并由新的人选接任。他委托了他个人信任的一家咨询公司对当前系统进行详细的技术审计。在与约翰及其他许多 DreamCo 利益相关者的咨询后,他们得出结论:许多组件的架构和代码质量极其薄弱,结构难以理解,唯一的选择就是重建系统的关键部分。
问题
大规模混乱(Big Ball of Mud)是指系统内部结构完全崩溃后,留下的一个无法理解或更改的无差异的大团泥土。与可以在其有限范围内运作良好的烟囱模型(stovepipe)不同,大规模混乱实际上是一个“可丢弃”的系统。你或许能通过不断的应急修复来让它保持运行,但你永远无法让它运行得好或做出重大改变。这是对一个系统的反应,这个系统在多个领域承受着巨大的功能交付压力,以至于随便采纳任何看似能够交付所需功能的想法,都显得是个不错的选择。
它通常是由于无知或绝望引起的,因为没有人会故意去制造一个大杂烩。然而,你经常会从那些由于某个人或几个人独立工作,且没有监督、清晰文档或良好决策过程的系统中,看到大杂烩的出现,就像我们例子中的 Ricky 一样。
你可以说,大杂烩有点像耐克的执行理念,“Just Do It.”虽然这在运动中可能是一个好的原则,但在企业 IT 中很少能取得好的效果。
提出的解决方案
大杂烩的解决方案通常是将信任寄托在某个团队或个人身上,只是为了完成某项任务而不顾后果。在压力大的情况下,这种方法常常具有吸引力,因为它看似能为你提供一个摆脱困境的好办法,而不需要承担有纪律的开发或实施的成本。
大杂烩(Big Balls of Mud)通常是从像烟囱(stovepipe)这样的系统中演变而来的,当所有的纪律和控制都丧失时。如果一个烟囱系统保持其内部结构的完整性,它可以独立运行很长时间,但一旦放弃这种内部纪律,它很快就会退化成一个大杂烩。
大杂烩也常常出现在实验性或原型系统被提升为生产环境的过程中,就像我们之前例子中的物流应用程序一样。一个系统到达大杂烩阶段的结果通常是灾难性的,正如我们在接下来的章节中讨论的那样。
结果
大杂烩是一个系统的最终状态。一旦系统达到完全内部混乱的状态,保持其运行的唯一方法就是让一个或两个人依然部分了解它如何工作的情况下,不断地进行紧急修复。你将无法做出任何非琐碎的更改,也不现实将系统重构成合理的状态。重建关键模块会更便宜,这也是这类系统最终通常会发生的事情。
正如介绍中所提到的,一些人喜欢成为英雄,并且也喜欢因不可或缺而带来的工作安全感,因此,大杂烩系统能够维持正常运行的时间在某些情况下出乎意料地长。
解决大杂烩问题的根本方法是采取各种形式的技术纪律,接下来我们将讨论这一点。
更好的解决方案
在许多方面,解决大杂烩反模式的更好方法类似于我们为烟囱反模式列出的那些方法。如果你有良好的技术标准和实践,并且它们在实际中得到遵循,那么你就不会最终陷入大杂烩。
然而,更根本的是,Big Ball of Mud 情景揭示了执行组织内缺乏技术纪律和对工艺的尊重。如果你的技术文化不重视良好的实践、架构、良好结构化的代码和抽象,而是更看重快速启动并运行的牛仔风格,无论多么粗糙,那么你很可能最终会陷入 Big Balls of Mud 的困境。
当然,有些情况下,快速而肮脏的编码是足够的。如果你正在为一个短暂的营销活动、研究项目或临时原型编写代码,那么你可以不必太在意你所创建的系统是否能够进化。然而,对于我们大多数人来说,大部分时间这并非如此。
过度耦合
以低耦合和高内聚设计系统是任何软件架构师的基础目标之一。然而,耦合很难避免,在许多情况下,通过与其他关注点进行权衡来合理化一定程度的耦合。然而,在本节中,我们将看到如何强耦合可能成为严重影响系统架构的反模式。
强耦合
强耦合是一个反模式,其中系统景观中的一个或多个系统未能与其他耦合系统保持清晰边界,导致系统变得脆弱且难以维护的状态。
一个例子
BigCo 拥有一个中等规模的 Sales Cloud 实施方案,用于管理他们的销售机会管道。然而,所有财务流程、报价和订单管理都在他们的主要 SAP 系统中完成,这些年来一直作为业务的真实来源。
销售部门喜爱他们的 Salesforce 系统,并希望通过 Salesforce 完成整个订单和履行流程,将 SAP 系统留给纯粹的财务流程。财务和供应链团队认为这个想法不仅是误导性的,而且可能危及 BigCo 多年来对数据的强大控制。
经过一些内部政治斗争后,财务总监和销售副总裁达成了一个折衷方案。订单和履行流程将继续留在 SAP 中,以及财务流程,但报价将完全迁移到 Salesforce 使用 Salesforce CPQ。这样一来,销售团队很少需要进入 SAP,可以主要留在他们喜爱的 Salesforce 界面中,但其他团队仍然控制所有主数据。安尼塔,一名 Salesforce 架构师,被委托将这一妥协变为现实。
她很快发现了这种方法的一些主要问题:
-
首先,所有产品和价格都直接保存在 SAP 中,而且没有迁移的意愿将其移至 Salesforce;因此,在报价过程中需要从 SAP 中访问它们,并且只能将桩数据复制到 Salesforce。
-
第二,报价过程中会进行一系列商业逻辑检查,确保报价符合公司的可接受参数。Anitha 考虑将这些检查移到 Salesforce 作为实施的一部分。虽然许多检查是可能的,但其中一些需要访问 SAP 财务模块中的数据,无法在 Salesforce 上完成。这些检查也需要通过集成访问 SAP。
-
第三,在报价过程中需要调用许多额外的服务,以获取当前的产品可用性和可能的交货日期,以便将其包括在报价单中。这些必须通过 SAP 调用,因为它们已经通过 Web 服务在该平台上暴露,而 BigCo 没有集成资源来直接连接到 Salesforce 或通过其他中间件进行连接。
图 2.6 – BigCo 集成场景
Anitha 启动警报,并表示,Salesforce 对 SAP 的依赖程度让她怀疑新系统能否满足销售团队的高期望。她建议考虑采用另一种方法,在 SAP 和 Salesforce 之间进行更清晰的划分。然而,财务和供应链团队排除了在实施过程中进行任何流程更改的可能性,因此,尽管心存疑虑,她仍决定继续推进。
与用户的初步研讨会进行得很顺利,销售团队的功能需求似乎与 Salesforce 提供的功能非常匹配。然而,Anitha 仍然担心,由于与 SAP 的耦合,最终产品的表现可能无法达到预期。
在解决方案的用户验收测试(UAT)过程中,出现了对用户界面性能和响应性的担忧,还有一些抱怨称测试因 SAP 的维护或故障而不得不多次中断。
然而,这些担忧不足以阻止上线,因为团队预计从迁移到生产环境中能获得性能提升,而且解决方案的基本功能方面是可以接受的。
不幸的是,迁移到生产环境后,问题不仅没有得到缓解,反而加剧了。性能显著下降,销售用户经常需要等待几分钟才能看到来自 SAP 的响应。此外,在一天中有很多时段,SAP 会执行大型的计划任务,导致销售用户无法进行任何操作。
团队拼命工作,试图改善情况。然而,几周后,团队不得不放弃,销售团队又回到了在 SAP 中生成报价单的方式。
问题
强耦合发生在系统或模块之间的边界被模糊到极点,以至于一个完全依赖另一个的操作。通常,作为架构师,我们努力减少耦合的同时保持一致性。然而,耦合——即使是紧密耦合——在某些情况下也是与其他需求之间的必要权衡。
然而,强耦合是这种权衡的最极端版本。在系统级别,它发生在系统边界未被尊重时,你试图设计一个解决方案,将另一个系统的显著部分集成并复制,使用另一个系统作为同步后端。
同样的模式可以在模块级别重复出现,在这种情况下,一个模块在不同的上下文中复制另一个模块的所有功能,并且大量调用原始模块的功能来实现这一点。
强耦合通常是出于合理的原因。遗留系统或模块的功能通常存在实际问题,解决起来相当困难,而且在不同的系统或模块上下文中似乎更容易解决。
正如我们将在接下来的章节中看到的那样,强耦合所提出的解决方案能够非常有说服力地应对这些问题,这也是它成为经典反模式的原因。
提出的解决方案
强耦合是一个承诺可以“一举两得”的提案。通过使用 API 或 SDK,或使用其他类似的机制,你可以获得你所习惯的所有功能和业务逻辑。此外,你还可以在一个新的用户体验中使其工作,以满足你不断变化的需求,而且你不必经历引入新系统或对遗留系统进行重大更改的痛苦。就像所有这种“蛋糕式提案”一样,你应该对这些表面上的说法持怀疑态度。
Salesforce 特别容易出现这种反模式,因为它拥有许多用户喜爱的用户界面,且业务习惯于在该平台上实现相对简单的功能。因此,常常会有请求,要求将其他系统的部分功能整合进 Salesforce 平台。
如果你小心处理边界,愿意进行必要的过程变更,并且具备强大的集成能力,这种做法是可以成功的。然而,也很容易陷入强耦合的情境中。
结果
强耦合往往会导致一个端到端的用户体验,这种体验通常表现为脆弱、不稳定和低性能。其背后的原因显而易见,因为强耦合的系统,实际上是一个面向单一用户的系统,涵盖了两个底层技术系统。它是一个分布式系统,但并没有意识到自己是一个分布式系统。
你越是依赖另一个系统,越需要频繁调用和访问它的功能。这意味着每当任何一个系统在解决方案涉及的领域中出现问题时,你都会遇到麻烦。
你还会遇到由于系统两侧相关功能的任何变动,都可能导致需要对你那个高度耦合的系统做出变更的问题。这意味着随着时间的推移,你可能会遇到比预期更多的错误和问题。
此外,强耦合系统中两方之间来回传输功能的累积等待会导致性能下降,有时甚至导致系统无法使用。
在模块级别,后果通常表现为可维护性降低、灵活性降低以及更高的变更成本,但性能问题也偶尔会出现。
更好的解决方案
虽然导致强耦合的问题往往是合理的,但作为架构师,你可以做许多事情来避免导致反模式的情况。以下列表提供了一个起点:
-
密切关注系统和模块的边界,确保如果它们发生变化,切割点是在可维护的地方。
-
设计跨界流程时,要非常明确系统的责任以及支持这些流程的集成架构。
-
调整流程,使其能够与修订后的系统边界无缝对接。如果流程不适合,不要试图通过额外的技术工作来弥补。
-
避免在多个系统中出现冗余功能。明确在哪个地方与特定功能集进行交互。
-
如果你所构建的实际上是一个分布式系统,请注意这一点,并使用低耦合的集成模式,如基于事件的集成,以实现目标。抵制大规模同步集成的要求。
-
随着人工智能在 Salesforce 实现中的应用越来越广泛,要小心避免在 AI 模型和核心 Salesforce 功能之间形成紧密耦合。虽然紧密集成可以提供强大的功能,但也可能导致系统脆弱,难以维护或演进。应追求模块化的 AI 集成方式,使用明确定义的接口和数据契约,以实现灵活性并便于更新 AI 模型,同时不会干扰核心 Salesforce 操作。
在讨论了许多适用于 Salesforce 的模式以及其他技术之后,我们将继续介绍第一个独特的 Salesforce 反模式——无序组织扩展。
组织复杂性
在 Salesforce 世界中,你不需要管理底层基础设施,这使你避免了许多可能导致反模式的诱惑。然而,你在 Salesforce 中通过不同组织结构化环境的方式本身也存在许多反模式。
无监管的组织扩展
无监管的组织扩展是 Salesforce 特有的一种反模式,由于缺乏明确的组织战略,导致组织数量不断增加,最终变得架构上无法管理。
例如
Miranda 已被聘为 BigCo 的新客户关系管理(CRM)迁移经理。该公司目前采取的是业务单元驱动的 IT 方法,并且尚未拥有任何集中式的 CRM 能力。相反,三个业务单元主要使用 Salesforce 来进行机会管理,同时还有来自多家供应商的至少 15 个其他系统在使用,以及各部门和地域间使用的内部开发系统。
Miranda 负责整合这个现状,并以 Salesforce 为主要平台。目标是整合系统并标准化流程,但目前缺乏足够的中央资源来推动这一转型。
Miranda 计划制定一个策略,整合现有的三个 Salesforce 组织。她曾经参与过 Salesforce 的组织整合项目,并认为在此情况下没有足够的价值去经历这一过程。
因此,她将创建三个核心 Salesforce 实施的变体,分布在三个地域,并将其他 CRM 系统映射到这三个中最合适的一个。她将使用已经从两个组织中导入 Salesforce 数据的公司数据仓库,在这三个组织之间实施报告流程。
然而,当她开始规划迁移时,面临着来自业务用户的强烈反对。尽管大多数团队愿意迁移到 Salesforce,但法国和中国两个 BigCo 最大的市场的用户要求拥有独立且隔离的环境。
根据各国负责人所述,这是法律要求,不容讨论。Miranda 将这个问题上报给法务部门,但无法迅速得到回应。因此,她不得不接受法国和中国的独立组织。
BigCo 的最大市场是英国,那里负责人一旦了解到可以拥有独立环境的可能性,便要求也为他们提供一个可以根据其需求定制的 Salesforce 组织。英国的运营非常高效,但也具有独特性,因此他们认为无法与其他业务使用相同的流程。
再次,Miranda 发现自己在政治斗争中处于劣势,不得不同意这些要求。然而,这导致了一个新的局面。产品开发团队认为他们的流程足够独特,需要一个独立的环境,其他部门和地域单元也纷纷提出类似的请求。
到最后,Miranda 将会查看十几个不同的 Salesforce 组织,其中许多已经实施了各具特色的流程。这比 Salesforce 之前使用的 15 个完全不同的系统要好,但仍远未达到最初的目标。至少,她终于找到了前进的方向。
图 2.7 – BigCo 组织概览
现在,一份期待已久的报告来自一家领先的管理咨询公司,报告内容是如何优化 BigCo 的全球销售流程。通过为所有现场销售人员实施全球统一的销售流程,报告承诺将实现全球范围内的销售和销售运营效率。这隐含地假设这个全球流程将会在 Salesforce 上实施。
Miranda 四处打听,看是否有人愿意根据新的目标改变实施计划。答案是坚决的“不”。她决定不再忍受,第二天递交了辞呈。
问题
在那些喜欢 Salesforce 但不喜欢标准化流程、用户界面或其他类似要求,并且没有对 Salesforce 平台进行强有力架构治理的组织中,常常会发生未受管控的组织扩展现象。
导致未受管控的组织扩展的主要问题通常出现在以下场景中:
-
不同的业务单元或地域有不同的流程,且无法就可实施的妥协达成一致。
-
不同的利益相关者对用户体验的结构有着截然不同的看法,无法就合理的妥协达成一致。
-
不同的利益相关者对要实施的数据模型有着截然不同的看法,无法就合理的妥协达成一致。
-
某些业务单元需要的关键功能在其他单元中无法使用——例如,不同的集成后端。
-
不同的业务部门正在与不同的 Salesforce 合作伙伴合作,这些合作伙伴将他们引导向不同的方向。
-
不同业务部门之间存在感知到的或实际的安全差异,这些差异对 Salesforce 的实施产生了重大影响。
-
不同业务部门之间在法律合规框架上存在感知到的或实际的差异,这些差异对 Salesforce 的实施产生了重大影响。
注意
值得注意的是,在过去,Salesforce 积极鼓励组织在多个不同的地方尝试软件,即所谓的种子与成长策略,这一策略在许多年里非常成功。在那些与 Salesforce 有着长期历史的大型组织中,你有时仍然可以看到这一遗留问题,体现在相对松散的组织结构中。
提出的解决方案
解决导致无序组织扩展问题的提议是,给每个需要它的人提供自己的 Salesforce 组织,让他们自行运作。这一方案之所以有吸引力,是因为它减少了协调问题和对齐问题,并且更容易解决棘手的合规问题。它还让有权势的利益相关者按自己的方式推动事情发展。
这种反模式有不同的变种和程度,其中一些相对无害,甚至是有益的。在我们之前的例子中,某些要求可能完全是合理的,应该是系统评估的组织战略的一部分。例如,产品开发过程通常会配置在与销售和服务使用的组织不同的组织中,有时确实存在需要多个组织来解决的合规性问题。
让我们明确一点。多组织战略本身没有问题;它既可以是正确的架构选择,也能在实践中良好运行。然而,面对无序的组织扩展问题时,我们谈论的是没有任何战略或架构支持的多组织运营,而这往往会导致严重的负面后果,正如我们将在以下部分中讨论的那样。
结果
无序组织扩展的结果是,组织无法从中心控制的多个组织扩展。这一问题的严重性将取决于组织文化的性质以及它需要多少中央控制。
一般来说,你会在无序组织环境中发现部分或全部这些缺点:
-
在实施跨业务单位或地理区域的流程时遇到困难,因为 Salesforce 实现因数据模型和组件不同而各异
-
报告对齐数据的困难,因为数据模型和字段的含义将在本地定义
-
开发报告时的复杂性,即使数据已被整合,仍因不同的数据使用语义差异而存在问题
-
集成通常需要在多个不同地方重复执行,并且可能很难控制
-
授权费用可能很高,因为一些用户需要多个许可证
-
系统知识严重分散,要找到任何特定方面的概述可能非常困难,因为技术团队也大多在本地环境中工作
-
由于上述因素的结合,实行任何形式的全球治理几乎是不可能的
-
由于组织合并困难,一旦进入这种局面,很难再去逆转
这个列表在很大程度上只是多组织战略缺点的更极端版本,这当然是有道理的。正如我们将在以下部分中讨论的,避免这种反模式的关键是事先明确你的组织战略,并为不可避免的缺点制定应对措施。
更好的解决方案
对于熟悉 Salesforce 架构的人来说,避免这一反模式的最重要因素是制定一个清晰定义的组织战略。这一战略应明确何时可以创建新的 Salesforce 组织(如果有的话),并提供明确的集成模式和组织间数据整合模式。
有许多优秀的资源可以帮助你学习组织战略。我建议你从 SOGAF 开始,这可以在 Salesforce Architects 网站上找到:architect.salesforce.com/well-architected/overview
。这是来自权威的全面视角,尽管它不会涵盖所有可能需要的细节。
图 2.8 – SOGAF 模型
此外,在本书中已成为反复强调的一个观点是,你应该为治理定义一个共同的框架,理想情况下,这个框架应根植于一个卓越中心(CoE),该中心对所有与 Salesforce 相关的事务进行全球性监管,并且所有组织都应遵循此框架。这个框架还应该包括共同的标准和实践,并且理想情况下,必须在每个环境中使用一定的共同工具。
在制定组织战略时,考虑不同组织之间 AI 和机器学习(ML)能力的影响。AI 实施的不一致或孤立的预测模型可能会导致组织内部产生冲突的洞察和决策过程。目标应是建立一个统一的 AI 治理模型,确保所有 Salesforce 组织在数据质量、模型性能和道德考量方面的一致性,同时仍然允许根据特定业务单位的需求进行必要的定制。
这一模式的相反模式
值得注意的是,这一反模式有一个完全相反的模式,我喜欢称之为“普罗克鲁斯特斯之床”,以此向希腊神话人物普罗克鲁斯特斯致敬。
这一反模式试图将所有要求集中到一个组织中,涵盖不同的地理区域、业务职能和业务单元。尽管许多组织在单一全球组织中做得很好,但有时需要多个组织来避免为关键利益相关者创造不良的用户体验,真正使多样化且对业务至关重要的流程得以顺利运作,或者解决实际的法律问题。
也就是说,组织战略是一个平衡的过程,过度偏向任何一方都可能变成反模式。你应参考前面提到的 SOGAF 模型,以找到在你场景中前进的正确方式。
知道要点
在本节中,我们将从特定模式中进行抽象,而是尝试提取出一些广泛的学习点,帮助你在日常工作中作为 Salesforce 架构师使用,或者在准备 CTA 评审委员会时使用。
在构建 Salesforce 解决方案时,你应该注意以下事项:
-
许多组织内部是孤立且政治化的,在这些组织中,默认的操作模式可能是开发独立的功能模块或混乱的系统结构。
-
为了避免这种情况,作为 Salesforce 架构师,你需要强烈推动应对措施。
-
这将包括推动 Salesforce 项目中的强有力的架构治理和协调,包括建立相关的治理论坛来协调活动,制定正确的技术标准和实践,确保每个人都以一致的方式构建。
-
你需要为这些倡议争取足够的业务支持,以便在事情变得紧张时能够执行;这将需要精心培养和管理相关利益相关者。
-
设计你的系统时使用共同的抽象——例如,通过基于共享功能的通用包来构建不同的模块。这将促进项目之间的技术一致性。
-
对不同 Salesforce 项目之间共享的公共元素进行强有力的治理是必要的,例如几乎所有 Salesforce 解决方案都会使用的 Hero 对象。
-
这些必须一致使用并具有明确的所有权,否则你最终会在数据模型中造成混乱,并且很可能也会在自动化流程中出现问题。
-
不要在系统之间设定模糊的边界。明确指出需要在哪个地方进行处理,如果边界需要改变,确保伴随有流程变更,以避免紧耦合场景。
-
尽可能选择更简单的集成模式。在可能的情况下,优先选择异步集成模式而非同步集成模式。这有助于限制耦合。
-
有一个明确定义的组织策略,定义何时(如果有的话)适合创建新的生产环境组织。
-
确保在创建任何新组织之前咨询相关利益相关者。例如,你可以将其提交给设计权威或架构治理委员会批准。
-
确保在任何新组织中也使用共同的抽象、标准、实践和工具。
-
留意“架构作为需求”的反模式,确保架构被视为一个指导框架,而不仅仅是一个需要实施的需求集合。
-
持续评估和完善架构,以确保它与不断发展的业务需求和技术趋势保持一致。
-
在架构师、开发人员和利益相关者之间培养合作与知识共享的文化,以确保架构最佳实践得到广泛理解和遵循。
在准备 CTA 审查委员会时,你应该注意以下事项:
-
始终包括适当的治理结构,以确保你有一个结构化的实施方法。这些治理结构可能包括一个 CoE、架构治理论坛和项目管理办公室(PMO)。
-
同样值得提到的是,公共模式、实践和工具的重要性,它们可以作为协调团队间实施活动的方式,并确保系统的可维护性。
-
如果涉及多个不同部门或业务单元,通常会存在与利益相关者管理相关的风险。如我们所见,糟糕的利益相关者管理可能是选择反模式的一个重要因素。
-
设计一个清晰的系统架构,确保不同系统之间的角色易于理解。避免在核心功能上出现系统间大量重叠。
-
仔细考虑您解决方案中的不同元素(无论是在平台内还是平台外)应如何交互,以避免出现“烟囱式”问题,即某些元素的孤立。您的解决方案应呈现为一个连贯的整体。
-
避免系统之间的不必要耦合,尤其是避免在功能体验不完全关键的情况下产生过强的系统依赖。
-
如果没有直接的同步通信需求,应倾向于使用减少耦合的异步集成模式。
-
您应该始终拥有一个组织策略,并且应该在项目初期就明确说明,并能够为其辩护。
-
小心不要陷入拥有过多组织,导致难以有效治理,或在存在强烈分裂需求的场景中使用单一组织,例如高度可变的流程或明确的法律和合规要求。
-
无论如何,要准备好说明如何缓解与您的组织策略相关的问题,因为没有任何场景是完全明确的,都会有需要权衡的利弊。
-
强调在项目初期定义明确的架构愿景和原则的重要性,以指导整个项目中的设计决策。
-
讨论架构师在平衡个别需求与整体架构一致性和可持续性方面的作用。
-
解释如何通过采用模块化、松耦合和清晰的抽象,帮助创建更具适应性和可维护性的 Salesforce 系统。
-
强调持续进行架构评估和完善的价值,以确保系统与不断变化的业务需求保持一致。
-
讨论促进团队成员之间协作与知识共享的策略,以推动架构最佳实践。
我们现在已经涵盖了本章的内容,准备继续前进。然而,在此之前,我们将总结我们的学习成果。
总结
在本章中,我们探讨了当组织未能采取有纪律的架构驱动方法进行 Salesforce 实施时可能出现的几种反模式。
我们首先考察了“烟囱式”反模式,这种模式下系统被孤立构建,几乎不考虑标准或通用抽象,导致形成一系列断裂的、难以维护的应用程序。接着,我们分析了“大杂烩”反模式,其特征是缺乏结构和组织,导致系统无法维护。
接下来,我们介绍了“将架构视为需求”的反模式,这是一种常见的陷阱,其中架构决策被视为单纯的需求,而没有考虑更广泛的系统背景和长期影响。我们探讨了这种方法的后果,如增加技术债务、可扩展性问题以及适应性受限等。
我们还讨论了系统和模块之间紧密耦合的风险,强调了明确边界的重要性,并倡导采用较为松散的集成模式,以保持系统的稳定性和灵活性。
最后,我们提到了在 Salesforce 环境中组织泛滥的挑战,并强调了制定明确的组织战略和治理模型的必要性,以防止过度分散,并确保不同实施之间的一致性。
在整个章节中,我们强调了架构治理、技术标准和最佳实践在避免这些反模式中的关键作用。我们强调了确保业务支持、促进协作,并在个别需求和长期架构可持续性之间找到平衡的重要性。
通过理解这些反模式并遵循提供的指导,Salesforce 架构师可以创建更强大、可维护且易于演进的系统,为组织带来持久的价值。关键是要主动应对架构问题,全面思考,并持续优化和调整系统,以适应不断变化的业务需求。
第三章:如何避免对安全产生困惑
本章讨论与确保 Salesforce 组织安全相关的反模式。我们将首先研究围绕 Salesforce 共享安全模型的关键反模式。然后,我们将探讨在将其他事物误认为是安全时可能出现的反模式。接着,我们将继续讨论如何避免搞砸共享模型,并再次总结关键要点。随着 Salesforce 不断整合 AI 技术,新的安全考虑因素不断涌现。本章还将涉及 AI 如何影响 Salesforce 中的安全格局。
本章将涵盖以下主要主题:
-
共享属于 Salesforce 反模式以及人们如何错误理解共享责任模型
-
合规即安全 反模式如何使你产生虚假的安全感,以及你可以采取的应对措施
-
声明式永远安全 反模式以及为什么你不能总是依赖声明式功能来保证安全
-
意大利面共享模型 反模式——为什么在 Salesforce 上很容易进入一个过于复杂的共享模型,以及如何防止这种情况发生在你的组织中
完成本章后,你将清楚如何避免 Salesforce 上常见的安全反模式,并了解可以采取哪些步骤来实施更好的安全实践。
对共享责任感到困惑
几乎所有的 SaaS 和 PaaS 平台都采用一种名为共享责任的安全模型。也就是说,供应商负责安全架构的某些部分,而其他部分则由客户负责。在这一部分中,我们将看到误解这一模型如何在 Salesforce 中引发问题。
共享属于 Salesforce
共享属于 Salesforce 反模式 认为 Salesforce 平台上的安全始终是 Salesforce 的首要责任
示例
SmallCo 是一家为光学仪器提供特殊镜头的供应商。他们在全球销售,最近已采用 Salesforce Sales Cloud、订单管理和 B2B 商务,以直接推动电子商务,而不是仅通过分销商销售。
当他们进行实施时,Salesforce 平台经过了 James 这位 SmallCo 内部专职安全专家的安全审查。他对平台进行了整体评估,并确认 Salesforce 平台,包括 Salesforce 如何保障其数据中心、平台和 Web 应用程序的安全,符合 SmallCo 的所有标准。
James 评估了 Salesforce 在安全方面使用的共享责任模型,并认为在初始项目中,SmallCo 方面无需额外的安全控制措施。Salesforce 将充分确保安全,SmallCo 无需额外工作。
在一段时间的顺利运行后,SmallCo 想要扩展其数字体验和与在线社区相邻的网络商店,并且还希望吸引更多客户进入网络商店。Mika,作为 SmallCo 的 Salesforce 产品负责人,被赋予了这个扩展项目的任务。
由于预算有限,Mika 同意与实施伙伴达成一致,将大量功能扩展给匿名用户,以便许多任务无需登录即可完成。这样,SmallCo 可以选择一个相对较小的基于登录的许可 SKU。
系统顺利上线,并且如预期,用户数量增长了十倍以上。Mika 和团队庆祝成功,并在完成最后一些待改进的小问题后,开始为下一个项目做准备。
就在这时,Mika 收到了一份来自一个曾帮助 SmallCo 实施原始 Salesforce 方案的 Salesforce 咨询公司的安全建议。咨询公司指出,Salesforce APIs 中发现了一些新漏洞,这些漏洞在数字体验中被使用。如果存在对外部用户过于开放的模型,这些漏洞可能会导致严重的安全漏洞。
Mika 起初感到担忧,但他想起了自己在启动新项目之前与 James 讨论过的 Salesforce 安全性问题。APIs 听起来像是一个核心平台特性,因此 Salesforce 应该会负责处理它们。项目已经关闭,做任何新工作都需要找到新的预算,而这非常困难。因此,他决定忽略这个警告。
三周后,一封电子邮件送达了 SmallCo 的内部邮箱。邮件包含了一个数据转储,里面有 SmallCo 所有的专有产品信息以及客户和订单的列表。数据转储附带一项赎金要求,要求用加密货币支付至指定地址,否则数据将被公开。
事情迅速升级,外部顾问被召入协助管理这一局面。他们很快发现,为了帮助将功能提供给外部用户,进行了一些非常宽松的配置。这些配置可能是安全漏洞的根源,也是 Mika 收到来自另一方的安全建议的原因。
SmallCo 对 Salesforce 留下如此明显的安全漏洞感到非常失望,并向他们的客户经理提出了这一问题,然而客户经理却把责任推给了 SmallCo 的配置。SmallCo 最终决定,唯一的办法就是支付赎金并修补漏洞。
外部顾问协助了这两个操作,并且外部配置被锁定。SmallCo 必须更改其许可包,但此时,考虑到避免近期事件的再次发生,这笔费用已经变得微不足道。
根据外部顾问的建议,SmallCo 设置了一个流程并使用一些软件持续监控其 Salesforce 环境的安全性。此外,与 Salesforce 相关的人员以及来自安全部门的 James 还接受了一系列关于 Salesforce 安全模型的教育课程。Mika 松了口气,准备迎接下一个项目。
问题
"共享属于 Salesforce" 反模式本质上涉及谁负责维护系统和平台的安全性。在处理云系统时,总会有一定程度的共享责任。这意味着系统或平台提供商将负责一些安全部分,而你则负责其他部分。
图 3.1 – 共享责任模型
在 Salesforce 的术语中,Salesforce 负责维护基础设施和平台的安全性,并在应用层安全方面为你提供了很多帮助。Salesforce Shield,包括平台加密、事件监控和字段审计跟踪,提供了额外的安全层,但需要客户进行正确的配置和管理。然而,当你自己配置或编写某些内容时,最终其安全性仍由你负责。现在,强制性的多因素身份验证要求将更多的安全责任转移给客户,客户必须确保正确的实施和用户采纳。最后,Einstein 的功能引入了新的考虑因素,尤其是在数据使用、模型训练和预测解释方面,影响了共享责任模型。虽然我在这里讨论的是 Salesforce,但它同样适用于所有 SaaS 和 PaaS 提供商,尽管具体的共享责任边界会有所不同。
然而,关于这个边界很容易产生混淆,从而导致这种反模式的出现。"共享属于 Salesforce" 反模式试图解决的就是这个普遍的安全问题。也就是说,“我们如何保持系统安全?” 正如我们将在下一部分中看到的,它提出的解决方案是通过假设一切,或至少尽可能多的事情,都是软件提供商的问题,即使这并非如此。
提出的解决方案
"共享属于 Salesforce" 提出的解决方案是通过假设 Salesforce 作为世界领先的软件提供商已经考虑到了所有问题,因此会保持平台的安全性,从而解决系统安全问题。这样,你可以安全地忽略安全性作为解决方案的一部分,并专注于完成实际的配置工作。
这实际上意味着你没有认真参与共享责任模型,尽管其中存在不同的层次。例如,大多数组织会接受他们对授予用户的系统访问权限负责。
然而,这可能会延伸到你如何配置共享模型;你给谁访问 API 或自定义编码类的权限,或者谁被允许运行报告的问题变得更加模糊。当情况变得复杂时,采用这种反模式的人会做出简化的选择,因为他们认为 Salesforce 已经考虑过了这些复杂性。不幸的是,这并非总是如此,也不能总是如此。
这种反模式之所以吸引人,有几个原因:
-
你不必认真处理复杂的安全问题,这意味着你不需要雇佣或开发专业技能
-
在处理 Salesforce 时减少了你的内部工作量
-
它让你有一个故事可以向利益相关者传达,说明你手上有问题并且不必担心安全性
-
它让你有人可以指责或追究责任,如果事情出了问题
尽管你可以理解为什么人们可能倾向于通过采用这种反模式来简化自己的生活,但结果通常并不理想。
结果
人类倾向于通过简化和采取捷径来减少认知负荷。因此,共享属于 Salesforce 的反模式是一种自然现象,需要积极的安全意识来对抗它。
因此,这种反模式的第一个和最严重的结果是加强了组织内的低安全意识。如果你不意识到安全问题,问题迟早会发生。这种反模式会让你陷入麻烦。
其他典型的负面结果包括以下几点:
-
让所有人,从终端用户到高级管理人员,对其 Salesforce 系统的安全性产生虚假的安全感,导致事故发生时后果更严重,并且缺乏意识到实际上需要采取行动,而不是指望 Salesforce 来修复问题。
-
没有跟上 Salesforce 平台上不断变化的安全格局。这不仅包括忽视新的安全警报,正如我们的例子中所示,还包括不查看新的安全更新或功能,这些将提升你的安全状态。
-
最终,这种反模式导致组织的风险增加,这对大多数高级管理人员来说是无法容忍的,如果他们完全理解了它的话。
值得注意的是,你可以多年来一直采用这种反模式而不发现其负面后果。只有在发生足够严重的安全事故并且被发现时,才会真正不得不面对这种反模式。
因此,指出这种反模式的存在可能会显得有点无功而返,起初可能不会有所进展。然而,我们将在下一节讨论到,确实有些事情是应该做的。
更好的解决方案
解决这一反模式的方案对于任何至少在信息安全领域有些经验的人来说都是显而易见的。首先,这关系到提高对所面临的安全问题的意识,并获得内部的认可,采取积极措施解决 Salesforce 安全问题,而不是假设供应商会自动处理。
主要要点包括以下内容:
-
积极参与共享责任模型,清楚了解边界在哪里,如何确保你负责的部分安全,以及如何持续保持对那些你不直接负责但仍直接影响你的部分的警惕。
-
投资所需的技能,以便初期和持续执行你的安全任务。你可以在内部构建这些能力,也可以使用顾问;无论你如何做,责任在你,确保任务完成。
-
利用现代 DevOps 实践,结合 Salesforce DX 或第三方工具,实施版本控制和 CI/CD 实践,通过一致且可审计的部署流程增强安全性。
-
每当你在重要方面扩展你的解决方案时,评估新风险。这不仅仅是指添加新模块时。对现有功能的重大扩展也可能引入新的安全威胁。
-
转变公司的思维方式。从根本上讲,你需要将组织的思维方式转变为将安全视为组织韧性和增长的基础。这可能超出了我们大多数架构师能够实现的范围。然而,在我们能影响的范围内推动变化也是有帮助的。
-
考虑最小权限原则,这对于防止安全漏洞至关重要,它确保用户和进程仅拥有执行任务所需的最小访问权限。这种方法限制了被破坏账户或恶意内部人员可能造成的潜在损害,减少了攻击面,简化了审计和合规性,并有助于遏制恶意软件的传播。通过避免权限过高的账户和不必要的权限,组织可以显著降低与数据泄露、未经授权访问和权限升级攻击相关的风险,最终增强整体安全态势,并减少成为常见安全反模式的受害者的可能性。
-
持续监控你的组织,以评估 Salesforce 安全建议和关键更新。考虑实施事件监控,以跟踪用户活动、API 使用情况和其他关键事件。这有助于及早发现潜在的安全漏洞或滥用行为。
我们已经完成了本章第一个反模式的讨论,将进入另一个关于一般安全问题的讨论——“合规即安全”。
将其他事物误认为是安全
安全是一个复杂且多维的领域。这种复杂性在许多情况下可能是如此深刻,以至于人们有强烈的诱惑将其简化为更易管理的形式。在本节中,我们将看到如何发生这种情况的两个例子,以及其可能带来的负面后果。
合规即安全
合规即安全 认为,通过严格遵守一个或多个指定的合规性框架,组织的安全性可以得到保障。
示例
Alexandra 在 LifeCo 担任架构师,LifeCo 是一家主要提供用于连续测量生命体征的医疗设备的公司。他们在多个全球市场销售设备,因此需要遵守多种不同的监管体系。可以公平地说,LifeCo 文化的重要部分就是专注于满足这些监管要求并保持合规。
在 IT 安全方面,LifeCo 也采用了一种以合规性为中心的方法,将 ISO 27001、HIPAA 和 GxP 协议结合成一个全面的检查和控制集,这些内容会在每个项目开始时进行详细记录,并随后每年进行审计。虽然在一年中有维护合规性的流程,LifeCo 将大部分注意力集中在初始文档和审计事件上。
LifeCo 采用 Salesforce 进行现场销售和护理程序,使用 Sales、Service 和 Health Cloud 组件。在实施过程中,Alexandra 与来自 IT、安全、法律和数据保护办公室的业务相关方密切合作。
他们对 Salesforce 在平台层面以及每个单独云层面的所有控制措施进行了彻底评估。他们与 Salesforce 的安全代表花费了大量时间,深入了解安全实施的细节,努力获得关于敏感问题的真实答案。
此外,他们要求实施合作伙伴提供详细的检查表和文档,以确保所有配置工作符合必要的标准。这在实施和测试期间增加了相当大的开销,但 LifeCo 坚信 Salesforce 符合他们对所有内部系统所施加的相同标准。
系统文档在经过长时间的调整以满足详细要求后,最终被签署为合规。Alexandra 继续在 Salesforce 领域工作,但主要专注于为新版本准备需求并更新与安全无关的技术标准。
然后,九个月后,难以想象的事情发生了。首席执行官接到一个来自流行新闻网站的电话,询问他们对公司成千上万名患者个人信息被泄露到暗网一事的回应。毫无疑问,这些数据来自 LifeCo,因为其中包含了公司关于设备使用的专有信息。
首席执行官匆忙作出回应,但损害已经造成。LifeCo 的声誉遭遇重大打击,成为主流新闻、社交媒体和股市的攻击目标。亚历山德拉在事件发生后担任调查和清理的主导角色。
调查结果并不完全定论,但有良好的间接证据指向一名心怀不满的员工导出了含有个人信息的报告文件并将其上传到网上。然而,现有证据不足以提起正式指控。
根本原因分析得出结论,事件发生是因为将一种特殊程序用于赋予用户患者数据报告权限,从而扩展了 50 人团队的权限,其中许多人相对较初级,且在 IT 安全或合规方面的训练较少。这一做法得到了几位高级经理的支持,用以绕过系统中的多个管理报告问题。通过导出并手动在 Excel 中处理数据,团队能够弥补 Salesforce 实施中的某些功能缺陷。
问题已经得到修复,并进行了调查,以寻找其他类似的案例,看看是否有使用某种流程规避良好实践的情况。在审计时,Salesforce 通过了审计,没有严重的保留意见。然而,亚历山德拉心中仍然存在一个疑问,或许他们并没有真正弄清楚问题的根源。
问题
你可能会倾向于认为“合规即安全”试图解决的问题与“共享属于 Salesforce”相同。也就是说,这个反模式试图解决的是如何保持数据和系统安全的通用安全问题。然而,这种理解是微妙地错误的。
虽然我们上一条反模式试图解决的是一般性的安全问题,但“合规即安全”回避了真正的安全问题,转而关注的是如何通过所需的实践向某些外部方展示你是安全的。也就是说,文档和检查清单成为了焦点,而不是它们应当推动的实际安全实践。
这与“共享属于 Salesforce”类似,因为我们旨在将实际上保持安全的复杂、棘手问题,简化为勾选所有正确选项的简单问题。正如我们将在下一节看到的,通过将其简化为一组易于理解、可重复的流程来减少认知负担,这种策略对某些类型的组织具有很大吸引力。
提议的解决方案
“合规即安全”提议用遵循一套明确定义的标准来代替并从而解决保持系统和数据安全的问题。这样,你可以放心前进,确信自己已经遵循了良好的实践,因此,自己是尽可能安全的。
对于这个反模式,脑海中可以想象一个检查清单的形象。
让我们非常明确,合规性是一件好事!遵守那些定义行业和一般良好实践的标准确实至关重要。这适用于信息安全,也适用于一般情况。
遵守标准确实是鼓励组织内良好实践并将其嵌入文化中的一种极好方式。使这一情境成为反模式的原因在于,合规性变成了最终目标,而最终目标应该是合规活动所旨在促进的实践意识和改进。
换句话说,对于信息安全,你应该将合规性作为一种工具,旨在变得更安全、更具安全意识,而不是把它当作一个通过打勾所有框框就能摆脱安全问题的方式。然而,不难理解为什么组织会倾向于将重点放在合规性上:
-
合规性将信息安全这一模糊而复杂的问题转化为一个可以管理和治理的问题。管理者通常喜欢那些容易理解和清晰可衡量的问题。合规性容易理解,而安全性则不是。
-
为了建立和维持合规性所需的流程,往往与现有流程和技能相契合,特别是在那些运营于受监管行业的公司,如生命科学或国防部门。
-
当事情出错时,你有明确且不含糊的文档证明你已经遵循了规则。这对于外部解释事件和保护相关利益相关者都有帮助。
-
反正你必须保持合规。对于大多数大型组织,某种程度的合规性是强制性的,并且已经嵌入法律或行业标准中。既然你必须合规,那么将其作为最终目标的诱惑显而易见。
然而,从这种反模式中得到的结果往往是有问题的,正如我们将在下一部分讨论的那样。
结果
一般来说,通过“合规即安全”的反模式,你获得的是与某一标准的时点合规。你将在每次审计时保持合规,在审计之间,人们将遵循他们必须遵守的必要流程。
然而,你并没有在组织内建立起更深层次的安全重要性意识,也没有为人们提供进行有意义安全操作的培训和工具。这意味着你常常会发现许多解决方法,比如我们例子中描述的情况,人们做出某些在技术上合规的行为,却完全绕过了激发合规标准规则的安全精神。
在以合规为中心的组织中,你常常会看到两种模式出现:
-
漂移与修正:在这种模式下,标准实施后,你会看到组织逐渐偏离标准,因为人们将合规性视为一个时点的活动。这会定期进行修正,以使组织在审计时重新回到合规状态。
-
结构化规避:在这种模式中,你持续遵循规则,但在你的合规系统中包含了一些授予例外的方式,这些方式被系统性地利用,以在某种程度上使组织内的工作人员的工作变得更加轻松。这就是我们在前面例子中看到的模式。
从根本上讲,使用“合规即安全”反模式时,贵组织缺失了安全的“为什么”。他们做某些事情只是为了勾选合规框,但在那之后并没有进一步参与。这指向了帮助解决这个问题的关键干预措施,我们将在接下来的内容中讨论。
更好的解决方案
商业作家西蒙·西内克有一本著名的书叫做从“为什么”开始。在书中,西内克认为,最成功的组织(以苹果公司为典型例子)并不是从他们销售什么产品或如何生产它们开始,而是从一个基本的目的开始,这个目的体现在对公司为何存在的回答中。
虽然我不会对这个立场相对于商业的普遍性发表评论,但就信息安全而言,这个立场完全正确。“合规即安全”是一个反模式,因为它忽视了信息安全的根本“为什么”。
解决这个问题的办法,当然是从回答“为什么保持信息安全不仅仅是为了避免威胁,而且实际上使组织能够保持韧性并以安全的方式成长”开始。然后,你可以继续处理合规制度和具体控制的“如何”和“什么”。
对大多数 Salesforce 专业人员来说,这是一个庞大的任务。幸运的是,我们也可以做一些更小、更实用的事情来帮助:
-
持续让其他利益相关者意识到,勾选合规框并不意味着组织将保持安全。
-
培训人员了解 Salesforce 安全以及尽管合规,仍然可能发生的威胁。
-
找到“倡导者”来持续关注安全意识。
-
倡导这些经过培训和激励的人员持续对 Salesforce 组织的安全进行监控。
-
在技术层面,定期使用 Salesforce 的安全健康检查或第三方工具来识别并解决你组织安全设置中的潜在漏洞。考虑使用 Salesforce 的隐私中心来管理同意、跟踪数据主体请求,并保持对隐私法规(如 GDPR 和 CCPA)的合规性。工具支持有时有助于让人们持续参与活动。
-
通过定期在会议和专门的讨论中提出这个话题,在组织内传播知识和意识。
当然,还需要记住合规性很重要,您应该尽自己的一份责任保持合规。例如,Salesforce 在信息安全方面符合 ISO 27001 标准,在隐私管理方面符合 ISO 27701 标准,展示了他们对数据保护的承诺,但组织仍然必须确保自身流程与这些标准保持一致。在考虑过一个非常通用的安全反模式之后,我们将再次聚焦于 Salesforce 安全的一个具体反模式——“声明式功能始终安全”。
声明式功能始终是安全的
陷入“声明式功能始终安全”的反模式意味着对声明式 自定义功能的安全性抱有过于乐观的态度。
示例
Rakesh 是 BigCo 公司 Salesforce 的技术负责人。BigCo 是 Salesforce 的长期用户,在多个不同云平台上有着广泛的应用。他们在 COVID 大流行期间大幅扩展了使用规模,以便推动许多远程进行的工作流程。
Rakesh 和他的团队与几个较小的合作伙伴一起开发了这些流程。由于时间压力,他们在构建流程时结合了开箱即用的功能和流程,暂时没有考虑复杂的需求,打算以后再处理。从开发速度和安全角度来看,架构师们建议采用基于流程的方法。
在业务的合作下,这种方法作为一种权宜之计证明是足够的,BigCo 相对顺利地实现了远程工作的过渡,部分得益于这项工作。在初始发布之后,Rakesh 和团队继续致力于改进和细化这些新流程,其中一些已经发展成复杂的、多方面的业务应用,拥有强大的功能来支持业务发展。
这包括执行大规模更新、创建和删除的能力;通过 API 调用其他系统的功能;甚至在员工承担新角色或职责时,授予他们新的安全权限。还有一些管理流程,超级用户可以用来管理后台功能。
从功能上来看,这对业务运作非常有效,但用户的多次失误导致了记录的意外删除。当一位特别不幸的超级用户在使用管理流程时不小心删除了大量机会后,CTO 决定让合作伙伴审查这些流程,因为他们担心可能会存在更广泛的问题。
合作伙伴对这些流程进行了审查,并反馈了一份列有不安全操作的清单。特别是,流程赋予了大量用户系统管理员级别的访问权限,而这些用户并没有接受过足够的培训来正确使用它们。这不仅带来了已经发生的意外删除问题,还存在真正的安全隐患。包括来自恶意员工和外部威胁的风险,因为部分流程理论上可以通过 API 更新触发。
由于 BigCo 拥有先进的备份解决方案,事件带来的损害很容易得到修复,但流程的修复则需要更长的时间。为了未来的所有开发,Rakesh 与外部合作伙伴共同制定了一套明确的安全指南,在创建流程时必须遵守这些指南。
问题
声明式始终安全试图解决的问题是安全开发或定制。换句话说,我们如何避免我们的代码和定制造成漏洞,进而被利用获取我们的数据和系统?
不足为奇的是,许多人倾向于认为低代码或无代码方法能解决安全问题。许多经典且广为宣传的漏洞都源自模糊的编码错误,因此如果你想要更安全,避免使用代码似乎是个好主意。
当然,低代码/无代码方法是一种相对较新的现象,因此它在实践中是否真的有效,仍然存在一些不确定性。然而,这种推理一般是合理的,因为像 Salesforce 这样的供应商会花费更多的时间来确保他们提供的低代码组件的安全性,而你可能无法在自己的代码上投入相同的精力。
然而,正如我们接下来将详细讨论的提议解决方案所示,这种推理并不是完全可靠的。
提议的解决方案
针对声明式始终安全提出的安全开发和配置问题的解决方案是通过只使用声明式功能来绕过问题,例如,假定默认安全的自定义对象、页面布局、流程,甚至 Omnistudio。这样,我们就不需要花费太多时间考虑安全问题,可以更快速地创建功能。
这对于许多不同的利益相关者来说显然是一个有吸引力的提议,原因如下:
-
这在某种程度上是正确的。低代码方法比基于代码的方法更不容易包含安全漏洞。
-
它通过明确界定可能性范围,简化了开发和配置。
-
它为技术团队提供了一种有效的方式,以应对过于复杂的业务需求。
-
它通过利用可以根据特定业务需求进行调整的预构建功能,加快了功能交付的速度。
因此,专注于声明式功能带来了许多好处,并且通常被认为是 Salesforce 社区中的一种良好实践。然而,过度强调这一点,可能会使其成为一种安全反模式,因为它忽视了即使在声明式解决方案中也可能存在的真正安全威胁。
结果
因此,声明式始终安全这一反模式的关键负面结果是对解决方案中可能存在的安全威胁视而不见,甚至没有意识到这些威胁的存在。这可能导致严重的负面后果,正如我们的示例所示。然而,随着 Salesforce 推出新的声明式功能,这个问题只会日益加剧。
从 Salesforce 平台发布功能的方式来看,Salesforce 希望低代码工具,如流程和 Omnistudio,成为平台上定制化解决方案的首选工具包。然而,这些工具越强大,越有可能执行一些可能导致安全问题的操作。
同样,外部服务虽然是声明式的,但如果配置不当,尤其是在处理外部端点和数据时,可能会引入安全风险。这也适用于日益突出的 AI 解决方案。例如,使用爱因斯坦预测构建器时,您需要确保敏感字段不会被无意地包含在预测模型中,并且模型访问应适当限制。自定义元数据类型虽然是声明式的,但可以存储敏感的配置数据,应通过适当的访问控制来保护。
然而,流程是最大的潜在风险领域。因此,让我们考虑一些可能在流程中发生的安全问题:
-
一般权限,如运行流程或流程用户许可,可能会赋予大量用户运行组织中所有流程的权限,从而导致类似我们示例中的问题。
-
如果用户可以访问 All_Flows 列表视图,他们就可以从 UI 运行组织中的任何流程。这包括外部用户。
-
流程执行上下文很复杂,容易因错误而将流程运行在系统模式下,从而可能导致用户权限的提升。
-
流程中的客户端验证在某些情况下可能会通过将数据包含在响应中,意外泄露信息。
-
组件可见性可能泄露信息,因为该组件仍然包含在 HTTP 响应中。
-
可能会从流程中调用具有广泛影响的 Apex 操作,而没有清晰了解其安全性影响。
-
在体验云站点中使用屏幕流时,确保实施适当的访问控制,以防止未经授权的访问敏感数据或操作。
我推荐阅读文章 了解 Salesforce 流程和常见安全风险,可以在appomni.com/resources/aolabs/understanding-salesforce-flows-and-common-security-risks/
找到,这篇文章是了解一些常见流程问题的良好入门。
然而,关键问题在于,流程、Omnistudio,甚至更简单的声明式功能,确实存在一些实际的安全问题。新的流程功能,如流程编排,如果配置不当,可能会增加额外的复杂性和潜在的安全风险。因此,我们不能默认它们是安全的,而必须采取适当的预防措施,这将在下一节中讨论。
更好的解决方案
避免这一反模式的第一条也是最重要的建议是:像对待基于代码的解决方案一样,认真对待你的声明式解决方案。像流程和 Omnistudio 这样的工具越来越强大,已与 Apex 一样,能够解决复杂的业务需求。
这意味着,对于基于这些工具的解决方案,你应当遵循适合目的的软件开发流程,以符合解决方案的复杂性和重要性。具体来说,涉及安全性时,你应牢记以下几点:
-
应该为声明式解决方案制定标准和指南,就像你在编写代码时会制定一样
-
在处理敏感数据或部署大量功能的声明式解决方案时,提前进行风险和威胁评估
-
培训开发人员和配置人员理解相关问题,并提高他们对依赖声明式工具所能实现和无法实现的目标的普遍认知
-
关注声明式工具的长期发展趋势,并根据需要更新你的指南
-
监控外部环境,关注与 Salesforce 中声明式功能相关的问题或漏洞
话虽如此,我们将通过查看如何真正搞砸 Salesforce 中的共享模型,来结束我们关于安全相关反模式的讨论。
共享并不总是代表关怀
Salesforce 拥有世界上最强大且最复杂的共享架构之一。这既是福也是祸。然而,在本节中,我们将重点展示它如何出错以及如何防止这种情况发生。
意大利面共享模型
意大利面共享模型对 Salesforce 组织的安全性,就如同意大利面代码对应用程序可维护性所做的影响一样。
示例
GlobalCo 是一家跨多个 B2B 行业销售产品的多元化企业。GlobalCo 大部分组织运行在各业务单元内,但 IT 已成为强大的全球职能部门,它使得各业务单元之间能够通过 Slack 等简单工具高效协作。
几年前,GlobalCo 采用了 Salesforce Sales Cloud 和 Service Cloud 作为其企业 CRM。Huan 是该项目的首席架构师,现在在全球 Salesforce 卓越中心担任职务。尽管一些子公司在操作上仍然使用其他 CRM,但所有关于客户交易的基本数据都必须传输到 Salesforce。为了促进流程和数据的标准化,GlobalCo 采用了强有力的单组织战略来管理其 Salesforce 环境。
不幸的是,尽管 GlobalCo 希望能够全球共享尽可能多的数据,但许多法规阻止他们实现理想的共享范围。存在一些问题:
-
一些国家要求将其数据与其他国家的数据隔离,形成国家数据孤岛
-
许多司法管辖区的竞争法也阻止某些子公司与特定其他子公司共享数据,以防止串通。
-
在某些司法管辖区,销售人员对谁可以查看他们的机会感到有些偏执,担心其他人会窃取这些机会,因此采取了很多额外的保护措施。
-
最终,某些业务单元的高管习惯于将敏感的机会和客户支持案例保密,并只在少数人之间共享,这一要求也至少部分得到满足。
在上线后,很多人抱怨 GlobalCo 为满足这些需求而设立的结构过于僵化。至少有六个国家要求进行一系列例外处理。
图 3.2 – 共享机制
Huan 带领团队调查需求。最初,他认为通过对组织层级和企业区域管理进行小的调整可以解决问题。然而,这种方法过于简单,因此他设计了多个额外的公共组,以便捕捉到更多模型的细化调整。
然而,用户仍然在抱怨,于是 Huan 开始发挥创造力,利用账户和机会团队。由于所需的流程过于繁琐,无法手动管理,团队最终实施了一些自动化功能,根据特定标准自动将团队成员添加到账户和机会团队中。
然而,即便如此,这种方式仍然无法完全捕捉到何时应共享和不应共享特定记录的业务需求,尤其是在指定的业务单元和国家之间。Huan 指定了一种基于 Apex 的共享机制,并将其交给开发团队实施。
共享模型的完整调整在一个周末内全球上线。烟雾测试通过,但每个人都屏息以待,因为模型的测试非常困难,没有人能明确表示所有重要场景都已被测试。
尽管没有发生灾难,但在上线后的一个星期内,团队还是收到了持续不断的访问问题。很多情况下,要么某些人拥有不该有的访问权限,要么某些人缺少应该有的访问权限。
更糟糕的是,团队发现几乎无法定位错误。由于涉及的因素太多,确定具体案例中的错误变得非常复杂。每次团队认为解决了一个问题,似乎又会有两个新问题作为后果出现。
在几周的尝试解决问题的过程中,变更管理委员会决定回滚共享模型的更改,并找到一套手动的替代方案,直到找到更稳定的技术解决方案。
问题
在传统的软件应用中,有一个著名的概念叫做意大利面条代码。它发生在程序员在没有设计实践或必要经验的情况下编写系统时。相反,他们一次做一件事,只是当前能用的做法,而没有考虑整体框架。
随着时间的推移,这会导致代码看起来像盘子里的意大利面条。一切都纠缠在一起,系统的某一部分发生变化会以看似随机的方式影响其他部分,即使是代码的原作者也无法真正理解发生了什么。
幸运的是,在 Salesforce 上,我们很少看到如此程度的意大利面条代码。它是可能发生的,但根据我的经验,它是相当罕见的。频繁发生的是“意大利面条共享模型”反模式。也就是说,共享模型复杂到即使是其设计者也无法可靠地告诉你在特定情况下某人是否能够访问某条记录。
“意大利面条共享模型”反模式源于真诚地尝试按照记录共享的需求满足业务需求。问题在于,对于大型的全球性组织而言,这一领域的复杂度如此之大,以至于几乎不可能做到完全正确。
在我们的例子中,我们看到了一些原因:
-
隐私法律在不同国家之间有所不同,决定了哪些数据可以共享,哪些不能共享
-
竞争法可能会限制子公司之间的可见性
-
销售团队对奖金和佣金的关注极为重要,这可能导致关于数据共享的严重顾虑
-
高层管理人员通常因各种商业原因希望保密某些数据,同时共享其他类型的、不太敏感的数据
除了这一场景外,还有更多与特定法律和标准或组织内部政治因素有关的场景,例如保护敏感的健康或财务数据,可能会影响数据共享要求。
总体来说,如果你发现自己身处一个具有这种数据共享需求设置的组织中,你很可能会陷入“意大利面条共享模型”的反模式,单纯为了适应给定的需求而陷入其中。
提出的解决方案
“意大利面条共享模型”反模式建议以增量和迭代的方式解决共享需求,尽可能接近地满足业务需求。
这看起来十分合理,原因如下:
-
这正是我们为大多数其他类型的需求所做的事情
-
这与大多数 Salesforce 实施团队所采用的主流敏捷软件开发方法相符
-
你几乎总能在短期内实现目标
-
需要很长时间,复杂度才会达到使过程偏离轨道的程度
不幸的是,这一过程在某些规模和复杂度的组织中可能会崩溃,并导致我们正在讨论的反模式,正如我们在下一节中所看到的那样。
结果
“意大利面共享模型”反模式的结果是,某些或更多以下特征的情况出现:
-
记录与某些用户共享,但没有人完全理解原因
-
记录访问缺失,某些用户无法完全理解原因
-
确定访问问题非常困难
-
由于复杂性,修改共享模型被认为是完全禁止的
-
共享的变化往往会导致新的问题,这些问题难以理解和解决
值得反思的是,为什么共享更容易出现“意大利面共享模型”反模式,而其他配置领域则不然。答案主要在于 Salesforce 中控制共享的机制数量庞大且复杂,以及它们之间的相互作用。根据不同的统计方法,Salesforce 中有超过 20 种不同的方式来扩展对象和记录的共享。
下表展示了一些可以用于控制共享的机制示例:
机制 | 用途 |
---|---|
所有权 | 记录所有者、用户或队列的访问权限 |
配置文件 | 对对象的基本访问(或不访问) |
权限集 | 对对象的基本访问(或不访问) |
全组织默认(内部) | 默认的内部共享级别 |
全组织默认(外部) | 默认的外部共享级别 |
角色层级 | 访问下属记录 |
使用层级授予访问权限 | 根据角色层级共享(或不共享) |
公共组 | 与特定用户组共享 |
基于所有权的共享规则 | 根据记录所有权配置的规则进行共享 |
基于条件的共享规则 | 根据记录字段值配置的规则进行共享 |
来宾用户共享规则 | 与来宾用户的特殊共享 |
账户团队 | 根据是否为账户团队成员共享 |
商机团队 | 根据是否为商机团队成员共享 |
案例团队 | 根据是否为案例团队成员共享 |
手动共享 | 手动共享记录 |
隐式共享 | 对某些标准对象,在父子之间自动共享 |
领域层级 | 根据配置的领域和领域成员共享 |
外部账户层级 | 根据账户层级授予访问权限 |
共享组 | 与门户用户共享记录 |
共享集 | 根据账户或联系人字段的匹配与门户用户共享记录 |
管理组 | 与管理链共享记录 |
Apex 共享 | 通过编程共享 |
限制规则 | 限制访问特定类型的记录 |
表 3.1 – Salesforce 共享机制
如果这些大量机制使用不当,最终会导致“意大利面共享模型”反模式,因为它们的相互作用对于人类智能而言变得不透明。
更好的解决方案
正如我们所见,意大利面条共享模型反模式可能仅仅是因为人们在做他们的工作,并且逐步努力通过满足要求为企业创造价值。这意味着,这种反模式可能在没有任何人做错事情或做出特别错误决策的情况下发生。需要有人从日常工作中抽身出来,才能在问题发生之前发现这一点。
冒着激怒敏捷主义者的风险,我建议,如果你发现自己身处一个共享需求非常复杂的组织中,你需要停下来,退后一步,并为共享架构制定一个前期设计,同时建立治理机制来长期执行。例如,你可以引入一个原则:在使用共享机制时最好保持节俭,并且将新类型共享的采用纳入架构评审委员会或设计权威的批准范围。
这篇文章已经结束了关于安全反模式的介绍。接下来,我们将重点讨论从本次讨论中可以得出的关键点。
了解重点要点
在本节中,我们将从具体模式中抽象出来,尝试提取出你作为 Salesforce 架构师在日常工作中或准备 CTA 评审委员会考试时可以运用的更广泛的学习要点。
在架构 Salesforce 解决方案时,你应该注意以下事项:
-
安全问题不仅仅是技术问题;你如何构建问题框架和提高意识更加重要。
-
很容易通过各种方式忽视复杂的安全问题。虽然作为架构师你可能无法单独改变这一点,但你可以成为提高意识的一部分。
-
组织共享会议并发送相关材料是一种可以帮助改善情况的好方法。
-
你还可以确保技术层面的安全指南和实践能够反映出全面的威胁情况。
-
不要在没有充分证据的情况下认为某些事情是 Salesforce 的责任。
-
不要认为因为你使用的是声明性功能,就不能存在安全漏洞。
-
寻找方法,定期监控你的 Salesforce 组织的安全状况,并根据情报采取行动。
-
在治理论坛中定期讨论安全问题,在那里你可以影响议程。
-
除非你的需求非常简单,否则不要逐步构建共享模型。
-
相反,提前解决问题,制定一套在你的场景中可行的机制。
-
定期评估和更新你对共享责任模型的理解,特别是在 Salesforce 推出新的功能和服务,尤其是 AI 驱动的能力时。
-
实施持续的安全监控策略,包括自动化工具和定期的手动审查,以便在 Salesforce 环境中跟踪不断演化的威胁。
-
为你的 Salesforce 团队制定一项全面的安全培训计划,涵盖声明式和编程式开发,重点强调这两个领域中的潜在风险。
-
在你的 Salesforce 团队中建立安全优先的文化,将安全考虑融入到开发生命周期的各个环节,从需求收集到部署。
-
定期审计和优化你的共享模型,使用如 Salesforce Health Check 和 Optimizer 等工具,以防止不必要复杂性的逐渐积累。
在准备 CTA 评审委员会考试时,应注意以下事项:
-
安全嵌入在许多领域中,因此即使它是一个独立的领域,你仍然应当在相关的解决方案演练中简明扼要地涵盖安全问题。
-
安全是一个复杂的领域,因此要尽可能清晰简明。很容易陷入长时间的安全讨论,但在评审委员会上你没有时间做这个。
-
在审查治理模型和潜在风险时,考虑加入一些关于安全的评论。
-
在选择安全机制时要节俭。机制越少,就越容易解释,也更不容易出现导致意外后果的交互。
-
利用权限集组来更高效地组织和管理复杂的权限结构,从而减少过于复杂的安全模型的风险。
-
当然,不要过度简化或做出假设,以免忽视在安全领域中可能出现的问题。
-
分享特别容易出错,因此在设计复杂的共享解决方案时要非常小心。
-
不要在场景中没有明确提到的地方发明额外的安全要求。在阅读许多场景时,你很容易会误以为存在额外的隐含要求。
-
唯一的例外是处理隐私法,例如 GDPR,如果你的组织位于适用该法律的司法管辖区内。
-
在与外部系统集成时,确保遵循适当的 API 安全措施,例如 OAuth 2.0、IP 限制和定期令牌轮换。
-
准备好讨论在多云 Salesforce 实施中如何处理安全问题,考虑每个云的独特安全挑战。
-
练习用清晰简洁的方式解释复杂的安全概念,例如人工智能对数据安全的影响,以适应评审委员会的时间限制。
-
准备好解释在大规模 Salesforce 实施中,如何平衡安全需求与其他架构问题,如性能和用户体验。
我们已经覆盖了本章的内容,现在可以继续下一章了。不过,首先,我们将总结一下我们的学习成果。
总结
在本章中,我们已经看到,通过采取看似无害的行动或未能意识到职责和方法上的微妙区别,存在多种方式可能会危及你的安全。
这些包括了许多不同平台的通用安全反模式,例如“属于 Salesforce 的共享”和“合规即安全”,以及 Salesforce 特有的反模式,例如“声明式总是安全的”和“意大利面分享模型”。这些反映了安全领域的特殊复杂性。
在安全问题上,你既要关注组织文化的高层次问题,也要关注技术设计的细节,特别是如何为你所使用的技术量身定制机制。这正是让它既让人沮丧又极具趣味性的原因。
在涵盖了安全领域之后,我们将继续深入了解数据。
第四章:关于数据,绝对不能做的事
本章讨论了在 Salesforce 平台上如何使数据层受到妥协。整个章节中,我们将介绍在 Salesforce 环境中频繁出现的四种数据领域反模式,并为你提供识别和避免这些问题的建议。此外,我们还增加了关于 AI 相关反模式的新章节,以帮助你应对这些新兴发展。
本章将涵盖以下主要内容:
-
为什么将 Salesforce 当作关系型数据库处理不会带来令人满意的结果
-
没有协调活动会导致一个断裂的数据模型,并带来严重的负面后果
-
没有为数据库的增长做好规划,尤其是在你明知道该做时,会带来负面后果
-
为什么数据同步在小规模时可能是一个不错的解决方案,但在大规模时却可能成为噩梦
-
如何在 Salesforce 的背景下构建 AI 架构
完成本章后,你将清楚了解 Salesforce 与传统关系型数据库的区别以及为何这非常重要。你还将明白良好治理的重要性、数据建模和增长的规划,以及在没有治理的情况下可能出现的问题。最后,你将对数据同步的复杂性有更深入的了解。
将 Salesforce 误认为是普通数据库
许多人从其他技术背景进入 Salesforce 生态系统,他们通常会带着基于过去经验的先入之见,认为架构应该如何设计。虽然这能为平台带来一些丰富的经验,但也有一些情况可能会在架构设计上引导你走偏。最常见的错误之一,就是把 Salesforce 当作其他类型的数据库使用——通常是关系型数据库。
将 Salesforce 当作关系型数据库
将 Salesforce 当作关系型数据库的反模式包括将 Salesforce 的数据层误认为是 关系型数据库。
示例
UmbrellaCo 是全球最大的旅游行业雨伞制造商。他们使用 Salesforce 来管理其 B2B 销售渠道,包括机会管理、报价和订单。
然而,在 UmbrellaCo 的整体系统架构中,Salesforce 只是一个相对较小的组件。总体架构由一套定制化的业务系统主导,这些系统是公司内部开发和维护的,同时还有一个老化的制造资源计划(MRP)系统。
还有一个相对现代化的中间件平台,UmbrellaCo 的企业 IT 架构在很大程度上依赖于在中间件中整合、转换和结合来自各系统的数据。这让他们在面对老旧和定制化的系统组合时,能够保持一定的灵活性。
Rishi 是 UmbrellaCo 负责 Salesforce 的经理。他是一个外部招聘人员,最近刚刚从一家中型生态系统合作伙伴公司加入 UmbrellaCo。作为他刚刚上任后的第一件事之一,他必须处理来自中间件团队的一系列关于 Salesforce 数据模型的投诉。
UmbrellaCo 长期以来有着一些针对特定类型数据建模的惯例,例如不同类型的账户,如中小企业账户与大型企业账户,以及严格的地址建模标准。Salesforce 模型未能以标准方式适应这些模型,导致中间件团队在将数据映射到其他系统时需要进行大量的工作。
John 是长期受雇于 UmbrellaCo 的一名集成架构师,他被分配到 Salesforce 团队,目的是使 Salesforce 数据模型保持一致。Rishi 在与 John 合作时立刻感到非常不舒服。John 对 Salesforce 数据模型表现出极大的反感,认为它从根本上无法符合良好的数据建模实践。
UmbrellaCo 的标准是使用关系型数据库,规范化到 第三范式(3NF),并遵循公司对关键数据类型的约定。Salesforce 并未达到这些期望,也无法轻易地做到这一点。Rishi 尝试解释,Salesforce 数据模型不应被视为经典的关系型数据库,无论它在表面上有多少相似之处,但他的反对意见未能得到回应。
经过一个月的工作后,John 提出了重新设计 Salesforce 数据模型的提案。该提案涉及用一组新的自定义对象替换标准的 Salesforce 地址字段,这些自定义对象包含地址和一个与主账户对象关联的任意数量的地址行。不同类型的账户将有各自的自定义对象,并通过类似继承的接口与主账户对象进行关联。
图 4.1 – 重构账户模型的提案
为了实现这一点,既需要在用户界面上进行重构,又需要在 Salesforce 内部进行数据迁移,但 John 坚持认为这将使系统与公司标准保持一致,并减轻中间件团队的工作负担。
Rishi 强烈反对,并且甚至让他的 Salesforce 客户经理带来了一位 Salesforce 的高级解决方案工程师,试图解释为什么按照这个计划进行操作无疑会削弱 Salesforce 平台的功能,并使额外的项目变得更加复杂和昂贵。这些反对意见最终被提交到公司架构论坛,但由于符合公司标准被认为是更重要的迫切任务,因此被拒绝了。
展望未来,Salesforce 上的数据建模应遵循常规的 UmbrellaCo 标准,并交付符合企业数据模型规格的良好规范化数据模型。Rishi 深吸一口气,决定未来主要在 Salesforce 上进行定制解决方案的开发。
问题
Salesforce 作为关系型数据库所解决的问题是与软件系统中业务实体建模相关的一般问题。在这种情况下,采用软件行业中最常用的建模范式:关系型数据库模型。
在这种方法中,你将业务领域的逻辑模型映射到一组数据库表中,使用一个叫做规范化的过程。规范化的具体细节我们不需要过多关注,但它本质上关注的是消除数据库中的冗余。换句话说,每一条信息应在数据库中只存储一次并且是唯一的,然后在所有使用它的地方进行引用。
此外,不应有重复字段,例如多个地址行,实体中的所有字段应明确依赖于主键:Salesforce 中的 ID 字段。你应该始终为实体拥有一个且仅有一个唯一的键。
通过应用这些以及其他一些更复杂的规则,严格或宽松地达到一定的规范形式,这是规范化模型的名称。最严格的应用形式是所谓的第六范式(6NF),在这种情况下,表只包含一个主键和另一个属性。然而,大多数企业应用程序都力求达到 3NF,这符合我们之前概述的标准。
图 4.2 – 范式层级
这一切都很好,并且是基于关系型数据库的系统中公认的做法。然而,Salesforce 尽管在表格(称为对象)和关系(以查找和主/从关系的形式,使其能够作为关系型数据库使用)上与关系型数据库有一些表面上的相似之处,但它并不是一个关系型数据库,且不应当被视为一个。
提出的解决方案
将 Salesforce 作为关系型数据库,忽略了 Salesforce 平台上数据建模的独特性,并用一个基于关系型数据库的模型替代。这意味着自由使用自定义对象作为表格,关系则作为外键关系。
它明确忽视了 Salesforce 标准的记录区分方式,如记录类型和页面布局,而选择了一个具有更多唯一自定义对象的关系模型。此外,这种反模式往往很少使用标准对象,因为它们与良好规范化的数据模型不兼容。
这个解决方案对于许多从其他平台转到 Salesforce 的有经验架构师来说非常有意义,特别是那些没有很多理解或培训的人。毕竟,这在所有传统企业系统中都是被接受的做事方式,与公认标准的一致性在企业架构中非常有价值。
然而,像这种模式对 Salesforce 造成的形态扭曲,说明了每个标准都有例外。
结果
正如我们在前面的例子中看到的,引入这种反模式的结果本质上是增加了 Salesforce 解决方案的复杂性,导致了解决方案和维护方面的额外成本。
通过几乎为所有事情依赖自定义对象,你减少了利用开箱即用功能的能力,因为关系模型往往需要更多的小对象,这使得一些 Salesforce 常用功能(例如跨对象报告或跨对象公式字段)几乎无法使用。
这意味着你很可能需要编写更多自定义代码或构建复杂的自定义流程,而这正是你在前期实施成本、时间以及之后的维护和扩展性方面遭受重大损失的地方。
还有一个机会成本,即无法在同样程度上使用标准功能,也无法以相同频率采用新发布的功能。总的来说,为了一致性而付出如此高的代价是不小的。
更好的解决方案
数据领域是你应该采用 Salesforce 方式来获得最佳结果的领域。虽然有时 Salesforce 的好实践会有例外,但在数据建模方面,几乎没有例外地应该遵循这些指导原则。
这意味着直接在系统中建模广泛的业务对象,而不是经过规范化过程并依赖平台来管理和优化数据,或者至少提供工具让你做到这一点。这还意味着在可能的情况下使用标准对象,尽量避免自定义对象,并确保数据模型得到良好的治理,以避免数据完整性和冗余问题。
这对于许多在 Salesforce 生态系统中成长的人来说显而易见,但对于大多数传统架构师来说却是违背直觉的。因此,这是少数几个更可能由经验丰富的架构师而非全新架构师发起的反模式之一。它在 AppExchange 应用中比在标准实现中更为常见,因为这些应用更接近其他平台上传统开发模型。
忽视治理
治理在所有架构领域中都很重要,但也许有几个领域在缺乏治理时会出错,其中之一就是数据领域。在接下来的章节中,我们将探讨这一现象的两个例子,从当你未能在统一平台上协调数据模型时会发生什么开始。
断开的实体
断开的实体 是一种反模式,其特点是在公共数据库中出现未连接的数据实体,通常是同一业务级实体的多个数据库表示。
示例
SmileCo 是一家主要提供牙科用品的公司,业务遍布多个全球城市。他们已经使用 Salesforce 数年,并采取了部门战略,每个部门独立在 Salesforce 上运行,且没有中央监督。
有三个部门在认真使用 Salesforce,分别如下:
-
财务,使用自家开发的应用程序进行债务催收
-
物流,使用由一个小型生态系统合作伙伴开发的应用程序进行供应商管理
-
销售,使用标准的销售云实现
这些应用中的信息分散,并且团队之间没有跨部门的可视性或合作。Kimmy 是 Salesforce Summit 合作伙伴的一位咨询经理,她带领一个小团队来实现对基础数据的全面视图。
然而,她很快发现这项工作比她预期的要复杂得多。财务应用程序使用扁平化的、非规范化的数据模型来建模债务催收。所有信息都存储在一个巨大的债务自定义对象中,包括所有的联系人和账户信息。这些数据未经过验证,乍一看数据质量似乎存在问题。
物流应用程序通过自定义对象有效地反映了标准 Salesforce 数据模型,用于表示供应商、供应商联系人以及与供应商的报价和购买信息。这些字段与标准 Salesforce 数据模型有很大差异,但通过一些创造性的数据显示映射,仍可与标准对象(如账户和联系人)相匹配。
销售云的实施相对标准,但使用了许多额外的自定义字段,这些字段与其他两个平台应用中的数据建模方式完全不匹配。Kimmy 向客户报告了她的发现,客户在犹豫了一会儿后,要求她继续制定合并计划。
图 4.3 – 三种不同的账户和联系人表示方式
她提出的计划旨在标准化所有三个部门使用账户和联系人对象,采用标准对象,并基于此编写一套报告和仪表板,提供所需的概览。她放弃了尝试整合其他对象,因为它们与任何标准对象的距离太远,尝试成功的可能性非常小。
对于财务应用程序,她建议对巨大的债务对象中的账户和联系人部分进行重新归一化。这需要进行数据迁移,并做大量的去重和数据质量提升工作。幸运的是,由于应用程序本身使用了简单的声明式功能,重做应用程序的工作量相对较小。
物流应用程序则面临更大的问题。大部分功能都在自定义代码中,且需要大量的重做。合作伙伴不愿意做 Kimmy 建议的更改,因为他们更喜欢在自己的空间中工作,但在一定的压力下,他们同意了。然而,这些更改非常昂贵,且需要几个月才能完成。
总体而言,本来是一个持续几周的小型咨询项目,最后却花费了超过三个月的时间,导致了可观的成本。在离开客户后,Kimmy 提出了一份新的提案,建议在 SmileCo 引入一些基本的 Salesforce 治理功能。他们对提案进行了审议,并承诺会及时回复 Kimmy。
问题
断开实体是另一种反模式,它发生在你没有意识到某些没有监督或治理的实践可能在更高层次的操作中引发严重问题时。它是由缺乏意识引起的,而非为了达成某个特定目标的尝试。
这种反模式通常出现在较小或高度去中心化的组织中,这些组织中不同的团队可能共享相同的基础设施,在这种情况下是一个 Salesforce 组织,但除了最基本的操作外,并没有真正协调其他活动。它还需要一个 IT 成熟度较低、IT 治理极为薄弱的环境。
提议的解决方案
到目前为止,如果我们要总结“断开实体”反模式所提出的解决方案,它可能是类似于“别担心数据模型,任何设计都足够好”的说法。至少,这可能是它的解释方式,因为没有标准、实践或指南可供遵循。
缺乏治理在许多领域可能带来不良影响,但在数据领域,断开实体反模式是最严重的之一。这意味着团队在没有意识到同一平台上还存在其他内容或其他团队如何使用相同元素(甚至是相同标准对象)的情况下,孤立地进行开发。
这意味着你可以在没有意识到的情况下产生跨组织的影响。而且,至少从反模式的角度来看,最终会导致我们之前示例中所描述的情景,其中跨部门的项目被数据模型所妨碍或阻塞。
结果
对于“脱节实体”反模式,结果可能和其产生的过程一样混乱。对于那些缺乏协调的团队来说,尽管他们的工作最终会导致反模式,但通常在短期内没有问题。
当你孤立地处理自己的事情时,做事不规范或不按常规其实并不会带来短期影响。影响只有在规模扩大、协调要求增多或需要将应用扩展到新的用例时才会显现。
因此,具体的负面后果可能会有很大差异,但一些常见的后果包括以下几点:
-
无法实现对联系人、账户或其他任何相关业务实体的 360 度可见性
-
无法进行跨部门或跨应用程序的报告
-
由于数据层的变异性和复杂性,新开发和维护的成本增加
-
无法连接应用程序或创建跨部门工作流,而不需要投入大量重工成本来使不同领域达成一致
-
不同领域之间的重复工作
-
因数据模型不一致,采纳新标准功能的空间较小
总的来说,这种反模式在数据领域中具有与“大杂烩”(Big Ball of Mud)在系统领域或“意大利面条共享模型”(Spaghetti Sharing Model)在安全领域中的许多相同特征。
更好的解决方案
毫不意外,避免由于缺乏治理和意识所导致的反模式的关键,是实施适当的治理和意识生成机制。这意味着首先必须建立适当的治理论坛,在这些论坛中,不同的领域可以以结构化的方式协调他们的活动。
这需要良好的数据治理标准和实践的支持,以支撑在相关论坛中开展的工作。这些标准和实践可以根据组织和文化的不同而有所变化,但为了避免“脱节实体”反模式,以下清单可以作为起点:
-
在可能的情况下,严格执行标准对象和字段的使用
-
确保团队一致使用标准对象和字段
-
对于创建新自定义对象,必须遵循的审批流程
-
对于创建自定义字段,采用更轻便的审批流程
-
定义所有对象的所有权,并确保对象所有者在对其对象做出任何更改时都能被咨询
-
让一到两位架构师从全球角度审视数据模型,并提供关于其演进的持续建议
在阐述了当你未能协调数据领域中的活动时会发生什么之后,我们将转向讨论如果你未能为增长做规划会发生什么。
未计划的增长
“未计划的增长”反模式发生在组织未能为存储数据的增长做好计划时,尽管他们本可以或应该更好地预见到这一点。
示例
HappyWorkoutCo 是一家全球拥有 200 多家门店的运动服零售商。他们开发了一款基于 Salesforce Industries 的定制零售管理应用,进行了大量的定制开发和一些专门的开发。该应用采用敏捷迭代开发方式,并且他们也计划以这种方式进行上线。
马丁负责向门店的推广工作。最初,他们将仅向少数几家主要市场的门店推出三个小型产品类别。尽管产品测试良好,但随着首批门店上线,马丁依然感到紧张。
但这一次,产品的上线取得了巨大的成功。产品运行无误,商店的员工也喜欢软件提供的新功能,这些功能帮助他们在不同渠道中与顾客进行更深入的互动。
在初步成功的鼓舞下,马丁和他的团队启动了一项增量上线计划,逐步推广到更多的门店和产品类别。一开始一切进展顺利,但过了一段时间,系统性能开始受到投诉。系统中的多个屏幕明显变慢,一些关键报告需要几分钟才能运行。
由马丁团队成员和开发合作伙伴的技术资源组成的专责小组开始调查这个问题。然而,最终决定继续推出新的产品和新门店。
专责小组开始工作,但在他们着手调查后不久,发生了一个重大事件:在一次大型上线后,20 家新门店和数千个新产品上线。系统渐渐停滞不前,多个屏幕完全无法使用。
马丁的团队执行了紧急回滚,恢复了系统的正常运行状态,但现在所有人的目光都集中在了性能小组。该团队迅速投入工作,焕发了新的活力和强度,并找到了他们认为是根本原因的地方。
在包含核心零售管理应用的包中,有一个连接对象,包含每个零售店可用的每种产品配置的记录。当系统上线时,共有 5 家门店,100 个产品,每个产品约 10 种配置,总共 5,000 条记录。
在大型上线后,门店数量增至 150 家,产品达到 17,000 个,每个产品平均有 35 种配置,总记录数为 89,250,000 条。更糟糕的是,连接对象不仅包含当前记录,还包括在上线过程中被覆盖的历史记录,导致连接对象中出现超过 117,000,000 条记录。
该对象在多个自动化任务、批处理作业和报告中被使用,并且被自定义用户界面组件频繁查询。设计似乎主要是出于开发便利性考虑,似乎没有人对要存储的数据量进行过任何计算。
特别工作组提出了其结论,并推荐了一些应急措施,包括移除自动化任务、归档所有历史记录、移除稀有产品配置、优化一些报告,以及在用户界面中实现一些缓存和优化。
这个工作计划解决了眼前的紧急问题,但系统的表现仍未达到预期。马丁开始与开发合作伙伴进行谈判,讨论如何重新设计系统,以消除根本原因。
问题
这是另一种反模式,它往往不是由主动选择引发的,而是由于为实现特定目标而降低某些实践的优先级。在未计划的增长情况下,团队为了在初期交付时提高速度,而降低了可扩展性的优先级。
在某些情况下,这种方法是合适的,例如,如果你是一家初创公司,正在努力证明产品与市场的契合性,并且预算非常有限,因此它可能具有一定的诱惑力。如今,许多大型组织都希望将自己塑造成敏捷初创公司的模样,采用许多这种世界中的实践。
然而,对于那些已经有一定规模的大型成熟组织来说,如果没有在前期就意识到这一点,那么后果将是灾难性的。
提议的解决方案
未计划增长反模式建议,团队应当专注于交付的重要任务,而不必过于关注未来可能由于规模增长而出现的问题。实际上,提议的方案是先做小规模进展,然后根据需要再做调整。
这种反模式不同于“断开的实体”等其他反模式,因为它不是由于缺乏意识引起的,而是由于主动选择降低了对可扩展性的规划优先级。同样需要注意的是,这种情况并不总是反模式。
在某些情况下,先从小做起,然后为后期的返工付出代价是一种可辩解的策略。通常,如果你无法事先知道你的想法是否可行,或者在部分构建应用程序时无法预测将需要容纳多少用户,这种策略是合理的,因为这时你是在获取更多的信息。
但对于那些已经知道其正在构建的应用程序最终需要达到某种可定义规模的大型组织来说,这始终是一种反模式。
结果
未计划增长的结果包括一系列较大的可扩展性问题,这些问题由应用程序的性质决定。最常见的是你会遇到大数据量(LDV)类型的问题,如下所示:
-
报告和仪表板的性能下降
-
列表视图的性能下降
-
数据加载或正常使用时的锁定问题
-
加载自定义组件时超时
-
关于治理限制的错误
-
第三方包失败
你可能还会看到一般用户体验停滞不前,特别是当它使用了许多自定义页面和组件时。集成也可能受到同样问题的影响,导致跨系统出现严重错误。即便是以前运作良好的自动化,也可能开始失败,尽管不一定是系统性的失败。
总而言之,如果不计划的增长足够大,它可能会让你的整个解决方案崩溃。
更好的解决方案
避免这种反模式的首要任务是从一开始就明确你要构建的规模。如果你计划构建一个小规模的系统来验证某个想法,那是可以的,但要明确说明这一点,并有一个计划,一旦你成功并需要扩展时,能够后退一步并重新设计。
如果你确切知道自己需要达到某个规模,事先不为其设计几乎可以说是犯罪。这意味着需要融入 LDV 缓解策略,例如以下几点:
-
使用选择性查询
-
使用平台查询优化器优化你的查询
-
避免在 LDV 对象上执行同步自动化
-
避免在 LDV 对象上执行同步代码运行的查询
-
使用精简表来优化特定查询和报告
-
使用自定义索引来优化特定查询和报告
-
持续归档非当前数据
-
尽可能使用外部对象存储数据
为增长设计也意味着以一种减少 LDV 问题的数据模型设计方式。在我们之前的例子中,可能会有许多替代的数据模型,这些模型不需要在一个单独的连接对象中保存所有按店铺划分的完整产品配置记录。
在考虑到数据领域中未考虑规模时会发生的情况后,我们将进入本章的最后一个反模式——无约束的数据同步。
避免过度同步
数据同步难以做到完美,但一旦成功,它非常有用。然而,开始实施同步方法时,很容易被带偏,导致一系列问题。我们将在接下来的章节中看到这些问题。
无约束的数据同步
无约束的数据同步是一种反模式,其特征是过于雄心勃勃地同步系统之间的数据,而没有充分意识到所有可能出现的问题。
示例
BusyCo 是一家大型生产力相关产品的供应商,最近实施了跨网络、社交、呼叫中心和合作伙伴渠道的 B2B 全渠道数字体验。他们使用基于 Microsoft Azure 的定制方法实施了 Web 应用,并使用 Salesforce 管理任何手动处理报价和订单以及机会管理,以及通过呼叫或现场销售产生的任何报价或订单。
所有信息最终都进入企业资源规划(ERP)系统,该系统处理订单过程的履行和财务方面,并作为财务预测的真实来源。由于其在生成财务信息方面的作用,ERP 中的信息必须始终具有最高可能的质量。
Oleg,Salesforce 方面的首席架构师,建议采用结构化方法来管理数据治理,明确定义每个系统在核心数据模型对象方面的角色和责任。此外,关键字段和对象应明确归属,以确保始终了解真实来源。
然而,BusyCo 采用了任何系统中的任何信息都可以随时修改,并且所有系统将几乎实时更新修改数据的方法。为了实现这一目标,他们在所有三个系统之间实施了双向数据同步。
图 4.4 – BusyCo 同步方案
在验收测试阶段没有发现问题,但 Oleg 并不感到特别安心。测试场景并没有涵盖一旦同步功能发布后可能出现的所有问题。然而,业务用户非常喜欢能够在任何系统上下文中更改任何内容的灵活性。
上线后,问题开始出现。虽然没有致命问题,但出现了许多恼人的错误。有一天,网站与其他系统之间的链接中断了几个小时,之后一些记录未能正确同步。更糟糕的是,几天后发现,一些地址更新从未同步到 ERP,导致一些客户订单发往错误的地址。
Salesforce 和 ERP 之间的报价似乎反复变化也是一个反复出现的问题。问题似乎是由 ERP 中运行的批处理作业执行一些例行维护引起的。由于作业无法关闭,短期内唯一的解决方案是支持团队每天手动处理错误状态的报价。
此外,在手动输入报价和订单的同步方面存在一些特殊情况。在所有情况下,它们似乎不能可靠地触发数据同步,因此一些订单卡在 Salesforce 中,最终没有发货。
随着错误的积累,业务领导层开始更加关注像 Oleg 这样提倡使用更简单模式来管理系统间数据的声音。然而,由于系统已经上线并且至少部分正常运行,任何重构都必须在不需要大规模停机的情况下进行。
Oleg 接受了寻找一种方法来重构系统,使其使用更简单的数据集成模式,同时建立更好的数据治理的挑战。这将不容易,但他相信只要时间和精力到位,BusyCo 能够成功。
问题
与之前由于缺乏意识或未及时采取措施导致的反模式不同,无约束数据同步反模式的发生是因为你尽最大努力去满足业务需求。有时,即便有最好的意图,仍然可能会造成巨大的混乱。
你在这种情况下试图解决的问题是如何在不同系统中同时使所有相关的业务数据可用并可编辑。用户讨厌在不同环境间切换。如果他们在系统 A 中,那么他们希望能够编辑系统 A 中所有相关的字段。如果他们在系统 B 中,他们希望能够编辑系统 B 中所有相关的字段。如果他们想编辑的字段在主数据角度上是相同的,例如一个地址或客户姓名,那么这个需求将迫使你同步数据。
从用户体验的角度来看,这是完全合理的。在不同系统和界面之间切换以更新数据是一件很麻烦的事,缺乏所需信息的即时访问也同样令人困扰。同样,你通常需要这些信息能够在系统间实时更新,以避免处理错误。
近乎实时的数据同步看起来像是万灵药,如果从技术角度来说,它确实会是,但它涉及的复杂性让人头疼。
提议的解决方案
无约束数据同步提出的解决方案是双向同步所有相关系统间的所有数据点,接近实时。正如所述,这可以被视为一种银弹,许多供应商愿意通过承诺提供能简化同步的工具来利用这一点。
问题在于同步过程中有许多失败模式。这些失败会随着数据同步使用的增加而积累,没有任何工具能够消除这种根本的复杂性。不同系统之间甚至同一系统内部的小差异可能会导致意外结果,某些平台的轻微故障或错误也可能会造成类似问题。这些错误会随着你同步的系统和对象数量的增加而不断叠加。
除非你能自信地说你完全掌握了所有系统和流程可能出错的方式,并且确信你完全控制了所有操作流程,否则不受限制的数据同步将给你带来麻烦。
结果
数据同步在小规模场景中通常工作得很好。在两个系统之间同步特定类型的数据很少会出现问题,单向同步大量数据也不会有什么问题。
问题出在你有多个系统、多个对象和双向连接的组合时。在这里,你将开始看到像我们示例中那样的小错误随着时间的推移积累成重大问题的场景。
通常,你会得到一系列需要技术支持团队处理的小规模修复活动,并且需要在业务层面采用若干变通方法来避免已知的同步问题。你的场景越复杂,你遇到这些问题的可能性就越大。
偶尔,这种反模式可能会导致灾难性后果,例如,当一个同步链路在长时间内默默失败,导致系统之间的数据严重不同步,业务错误在无人察觉的情况下蔓延,直到抱怨开始出现。
然而,大多数时候,你只会看到一连串的小问题,似乎永远不会停止。
更好的解决方案
你可能期待我们说你应该普遍避免数据同步。我们不会这么说。这将是天真且不必要的。
我们要说的是,你应该谨慎处理你所做的数据同步类型,特别是在以下情况下:
-
在两个系统之间进行双向数据点同步是可以的,但不要再加一个第三方。
-
如果你需要与多个系统进行同步,确保你是在单向同步,并且已定义谁拥有主数据。
-
中间件和同步工具可以帮助实现,但它们无法解决根本问题。
-
同一组织中的多个同步是可以的,只要它们不重叠;但是要小心不要对同一对象进行多个同步操作。
-
需要在近实时运行的同步比那些可以批量处理的同步复杂得多。
现在我们将继续介绍一些组织在开始采用 AI 时常见的反模式。
太多的 AI 未必是一件好事。
本节介绍了两个与 AI 相关的反模式,它们描述了当你没有正确思考 AI 的不同之处,以及何时在你的解决方案中使用它时会发生什么。
让我们将 AI 加进去
这是一个反模式,当你使用 AI 是为了它的酷炫效果,而不是出于真正的商业理由时,就会发生。
示例
MediCorp 是一家中型生命科学制造公司,一直在努力解决其产品线之间的定价一致性问题。尤其是销售团队中的客户经理,常常在应用正确的折扣和遵循公司定价策略方面遇到困难。经过多次商讨,领导层决定实施一项新的定价解决方案,将平台外的定价引擎与 Salesforce CPQ 结合使用。
项目开始时,大家充满热情。团队精心绘制现有的定价流程,识别痛点,并设计了一种解决方案,承诺简化定价决策,同时为复杂的交易保留灵活性。但在实施六个月后,一切发生了变化。
销售副总裁 Sarah 参加了一场备受瞩目的科技会议,会议的热议话题是人工智能(AI)。她听完了一场关于 AI 驱动的定价优化演讲,演讲中承诺通过此技术能将收入提升 15%,并将定价错误降至接近零。她对这种可能性感到兴奋,回到 MediCorp 后,决心将这项前沿技术融入他们的正在进行的项目中。
尽管项目经理和首席架构师对项目范围膨胀和复杂性增加提出了担忧,执行团队还是被 Sarah 的热情所打动。他们批准了引入平台外 AI 定价工具的提案,确信这将为他们带来竞争优势。
项目团队现在面临整合三个独立系统的挑战:Salesforce CPQ、原始定价引擎和新的 AI 工具。AI 应该为 CPQ 提供定价指导,并将结果反馈给定价引擎的计算。曾经相对简单的集成,现在变成了一个复杂的数据流和决策点的网络。
随着上线日期的临近,测试揭示了许多不一致之处。有时,AI 建议的价格与定价引擎中的规则相矛盾;有时,CPQ 中应用的折扣未能体现在最终价格上。团队加班加点解决这些问题,但由于 AI 决策过程的“黑箱”特性,往往很难找出根本原因。
尽管有不少红旗警示,MediCorp 仍然推动项目上线,部分是由于沉没成本谬误,部分是因为想要成为一个“AI 驱动的公司”。销售团队接受了关于新系统的广泛培训,特别强调了那些声称能让他们工作更轻松的 AI 驱动功能。
起初,大家都充满兴奋。客户经理们对界面的流畅性和所谓的智能定价建议感到惊叹。然而,随着时间推移,问题开始显现。销售代表们发现自己开始怀疑 AI 的建议,常常回到旧有的定价方法。客户们也开始质疑类似订单之间定价的不一致性。
财务团队注意到,尽管一些交易的定价较高,但整体利润率实际上在下降。他们怀疑 AI 有时会建议过于激进的折扣以促成交易,但没有充分考虑到 MediCorp 的成本结构。
最令人担忧的是,由于三方集成的复杂性以及 AI 决策过程的不透明性,没人能够自信地审计定价决策。当发现差异时,几乎不可能确定问题是出在 CPQ、定价引擎还是 AI 工具上。
上线六个月后,MediCorp 的 CFO 要求对定价系统进行全面审计。审计结果令人震惊。不仅承诺的 15% 收入增长未能实现,反而定价错误有所增加。系统的复杂性导致了缺乏透明度,使得销售代表很难向客户解释定价决策,从而破坏了信任。
在一次艰难但必要的决策中,MediCorp 的领导层决定撤回系统中的 AI 组件。他们重新审视了方案,计划重新实现一个更加专注于 CPQ 和定价引擎核心功能的版本,并且未来将更加谨慎地将 AI 纳入其中。
看似充满希望的“让我们加点 AI”的倡议,最终导致了成本增加、效率下降和定价公正性的短期丧失。MediCorp 通过痛苦的教训学到了,尽管 AI 具有潜力,但它不是一种魔法解决方案,不能随意地加入到现有项目中,必须经过仔细考虑和规划。
问题
“让我们加点 AI”的反模式源于广泛的信念,即 AI 能够普遍提升和优化现有的流程或产品。这种信念受到多种因素的推动,包括围绕 AI 的炒作和媒体关注、对 AI 能力的误解、害怕错失机会以及对创新的渴望。
许多决策者对 AI 的理解肤浅,导致他们高估了 AI 的能力或其对特定用例的适用性。来自利益相关者的压力常常促使他们在没有充分理解 AI 的影响或必要的前期准备的情况下,匆忙采用 AI。AI 平台和工具的普及让人们看起来很容易将 AI 融入到现有系统中。
这个反模式试图解决的核心问题是如何改进现有的产品、服务或流程。AI 被视为一种可以在任何情况下应用的通用增强工具,以实现更好的结果、更高的效率或更好的用户体验。然而,这种观点往往忽视了 AI 实施的复杂性、对高质量数据的需求、系统复杂性增加的潜力以及明确的使用案例和预期结果的重要性。
提出的解决方案
“让我们加上 AI”反模式提出了一种看似简单的解决方案,用于增强现有系统或过程:在可能的地方集成 AI 能力。这通常包括识别潜在的 AI 集成点、选择 AI 工具或平台、集成 AI 组件、训练 AI 模型,并启动增强了 AI 的系统。
该解决方案建议通过遵循这些步骤,组织可以获得许多好处。人们相信,AI 将改善决策、提高效率、增强用户体验、提供竞争优势、降低成本并提供可扩展性。随着 AI 组件处理更多数据,它们的性能预计会随着时间的推移得到改善,可能揭示人类可能忽视的新见解。
提出的解决方案看起来很有吸引力,因为它承诺利用尖端技术解决现有问题并创造新机会。它似乎提供了一种快速升级当前系统的方法,而无需进行完全的彻底改革。此外,随着 AI 即服务平台和预训练模型的兴起,它通常还具有相对容易实施的魅力。
然而,这种解决方案往往过于简化了 AI 实施和集成的挑战。它假设 AI 可以轻松地插入现有系统并立即提供价值,而没有考虑到对当前流程的潜在干扰,或对数据管理和决策框架进行重大变化的需求。
结果
当组织屈服于“让我们加上 AI”的反模式时,结果往往远未达到预期,且可能导致一系列负面结果。最直接的影响通常是整体系统复杂度的增加。将 AI 组件添加到现有系统中,通常会使架构更加复杂,难以维护、调试和更新。
数据质量问题经常浮出水面。许多组织在太晚时才发现他们现有的数据不足、偏见或质量差,导致 AI 输出结果不可靠。集成挑战也很常见,将 AI 组件与传统系统连接的过程通常比预期更加困难,导致项目延迟和预算超支。
许多 AI 模型,特别是深度学习模型,缺乏可解释性,这可能带来问题。当 AI 作为一个“黑箱”操作时,理解或解释它的决策变得非常困难。这在受监管的行业中或当透明度对用户信任或法律合规至关重要时,尤其具有挑战性。
用户体验通常会受到影响。如果 AI 组件没有按预期表现或犯明显的错误,可能会导致用户的沮丧和对系统的拒绝。还有过度依赖 AI 的风险,用户可能会过度信任 AI 的推荐,从而导致批判性思维能力或处理异常情况的能力下降。
如果 AI 实施匆忙,且未充分考虑伦理和隐私问题,可能会引发伦理和隐私担忧。这可能导致声誉损害或法律问题。
从资源角度来看,AI 项目可能会成为一个重大负担,消耗大量计算和人力资源。这可能会将注意力和资金从其他重要的项目中转移出去。AI 系统的维护往往比预期更具挑战性且资源密集,需要持续的监控、再训练和更新。
就性能和可靠性而言,匆忙实施的 AI 解决方案可能会导致不同场景或用户群体之间的结果不一致。它们可能会引入新的安全漏洞,或者无法按预期扩展。在某些情况下,AI 引入的复杂性使得追踪某些结果背后的逻辑变得困难,从而导致责任缺失。
也许最令人失望的是,许多组织发现很难衡量其 AI 项目的投资回报率。AI 系统的复杂性,加上它们对业务各个方面的影响,使得准确评估其价值变得具有挑战性。
本质上,“让我们为其添加 AI”的反模式通常会导致一个比其前身更复杂、可靠性更差、管理更困难的系统。它不仅没有提升现有产品或流程,反而可能引入新问题和低效。通过 AI 集成实现轻松改进的承诺被证明是一种幻觉,组织最终会面临意外的挑战和令人失望的结果。
更好的解决方案
为了避免陷入“让我们为其添加 AI”的反模式,组织应采取更加审慎和战略性的方法来实施 AI。关键是从明确的问题陈述开始。在考虑 AI 之前,必须清楚定义你要解决的问题。这有助于确保 AI 真的是最佳解决方案,而不仅仅是最流行的选择。
进行彻底的尽职调查至关重要。组织应研究并了解 AI 在其特定领域的能力和局限性。这可能涉及咨询专家和检查类似实施案例的研究。评估数据准备情况也很重要。应评估可用数据的质量、数量和相关性,并可能需要在实施 AI 之前投资数据基础设施和治理。
从小处着手并进行迭代是一种明智的做法。从一个试点项目或概念验证开始,使组织能够在扩展之前以最小的风险进行学习和调整。在此过程中,专注于用户需求至关重要。进行用户研究有助于确保 AI 功能真正增强用户体验并解决实际痛点。
组织应优先考虑 AI 实现中的可解释性。在关键应用中,选择能够提供透明决策过程的 AI 模型和方法尤为重要。这与考虑伦理影响密切相关。制定 AI 伦理框架可以指导实施,并确保技术的负责任使用。
在整个组织中投资于 AI 素养是非常有价值的。教育利益相关者,包括高管和最终用户,了解 AI 的能力、局限性和影响,有助于管理期望并促进更顺畅的采纳。
长期规划至关重要。组织应在规划和预算中考虑到 AI 系统的持续维护、更新和扩展。这包括建立明确的指标来评估 AI 随时间推移的表现和影响。
有时候,最佳解决方案是在添加 AI 之前先优化现有流程。对当前系统和工作流的简单改进,有时比复杂的 AI 解决方案能带来更好的结果。当 AI 被实现时,保持人类监督至关重要。系统应该设计为增强人类决策,而不是完全取代人类,尤其是在关键领域。
AI 架构就像普通架构
这是一个反模式,发生在 Salesforce 架构师将 AI 项目视为与其他项目相同的情况下。
示例
CloudForce Solutions 是一家成功的 Salesforce 独立软件供应商(ISV),多年来一直在为 Salesforce AppExchange 开发应用程序。他们的产品组合包括各种销售分析、客户管理和营销自动化工具。当 Salesforce 宣布新的 AI 功能时,CloudForce 看到了创建一个 AI 驱动的潜在客户评分和优先排序应用的机会。
这个名为“LeadGenius”的项目由 CloudForce 的资深 Salesforce 架构师 Sarah 领导。Sarah 和她的团队有着使用传统开发方法创建强大且成功的 Salesforce 应用的经验。他们决定将相同的方法论应用于 LeadGenius,将 AI 组件视为需要实现的另一组功能。
他们首先从潜在客户那里收集需求,并创建详细的规格说明。Sarah 设计了一个熟悉的架构:用于业务逻辑的 Apex 类、用于用户界面的 Lightning 组件和用于数据存储的自定义对象。团队计划使用 Salesforce Einstein 功能来实现 AI 功能,将其视为可以轻松集成到现有模式中的黑箱组件。
开发进行到一定阶段,团队遇到了第一个挑战。他们使用的爱因斯坦预测构建器(Einstein Prediction Builder)在给销售线索评分时,并未如他们预期的那样稳定。有时,它会给销售代表明确知道有潜力的线索分配意外低分。萨拉的团队将这视为典型的 bug,尝试向预测模型添加更多字段,并创建复杂的 Apex 逻辑以“修正” AI 的输出。
下一个障碍出现在他们尝试将 LeadGenius 与各种客户关系管理(CRM)系统集成进行测试时。AI 模型在处理来自不同组织的多样化且常常混乱的数据时遇到困难,导致结果不一致。团队的解决方案是在他们的 Apex 代码中实施更多数据清理和转换步骤,基本上试图强行使数据适应他们预定义的结构。
随着项目接近上线日期,CloudForce 在应用的线索优先级逻辑上遇到严重问题。在复杂的销售场景中,AI 有时会提出似乎与经验丰富的销售经理相悖的建议。团队的应对措施是在他们的 Apex 代码中添加更多的if-then语句和决策树,试图考虑每种可能的情况。
尽管面临这些挑战,CloudForce 依然推进 AppExchange 的上线,他们对自己的完善架构和严格测试充满信心,确信这将带来成功。最初,LeadGenius 受到早期采用者的积极反馈,他们对 AI 驱动的线索评分前景感到兴奋。
然而,随着时间推移,问题开始显现。应用的性能逐渐下降,难以处理新类型的线索和初期训练数据中不存在的行业。团队发现很难诊断问题,因为 AI 的决策过程并不像他们传统的 Apex 代码那样透明。
客户报告称,该应用无法适应他们特定的销售流程或处理复杂的线索资格标准。有些人注意到,LeadGenius 有时会对来自大公司的线索给出较高的分数,而不考虑实际适配度或兴趣,反映出训练数据中存在的偏见,这是团队之前未曾预料或考虑到的。
最令人担忧的是,有时该应用会提出道德上值得质疑的建议,例如基于可能被视为歧视性的因素对线索进行优先排序。
在上线后六个月,CloudForce 面临越来越多的客户投诉和取消订阅。他们要求对 LeadGenius 进行全面审查。结果令人失望。使用该应用的销售团队并未看到承诺的转化率增长,在某些情况下,由于误分类的线索,错失了宝贵的机会。
在与关键客户的困难会议中,Sarah 和她的团队不得不承认,他们传统的 Salesforce 应用开发方法未能解决 AI 系统的独特挑战。他们在意识到问题时已经太晚,才发现 AI 驱动的应用需要一种根本不同的思维方式,专注于数据质量、模型行为、伦理考量和持续学习——这些是他们在传统 Salesforce 开发方法中忽视的方面。
CloudForce 决定暂停新销售 LeadGenius 并启动应用的全面重设计。他们被迫重新回到设计阶段,这一次对 Salesforce 生态系统内 AI 架构的独特需求有了更深入的理解。
问题
“AI 架构就像普通架构”的反模式源于一种误解,即认为可以像传统 Salesforce 开发一样,使用相同的原则和方法设计和实施 AI 驱动的 Salesforce 解决方案。这种信念通常源于对 Salesforce 开发实践的熟悉,低估了 AI 的复杂性。许多团队觉得用过去在 Salesforce 项目中成功应用的技术会更舒适,但并没有完全理解确定性 Apex 代码与像 Einstein 这样的概率性 AI 系统之间的根本区别。
组织内部也经常面临快速实现 AI 功能的压力,以保持竞争力并最大化 Salesforce 投资。这种紧迫感,加上倾向于将 Einstein 功能视为简单的即插即用组件,可能导致对 Salesforce 生态系统内 AI 能力的过度简化。
这个反模式试图解决的核心问题是如何高效地将 AI 能力整合到 Salesforce 实施中。假设通过将 AI 架构视为普通 Salesforce 架构,团队可以利用现有的技能和流程有效地在平台上交付 AI 解决方案。然而,这种方法未能考虑 Salesforce 中 AI 系统的独特特性,如其概率性特征、对数据质量和数量的依赖、潜在的自主行为、决策过程的不透明性以及伦理问题。
结果
当组织在 Salesforce 实现中屈服于“AI 架构就像普通架构”反模式时,结果往往远远低于预期,可能导致一系列负面后果。
最直接的影响通常是人工智能性能差。人工智能模型在实际场景中的表现可能无法达到预期,导致预测或推荐不准确。这通常是由于对数据质量和数量考虑不充分,或缺乏对 Salesforce 生态系统内模型局限性的理解。
适应性也成为一个重要问题。AI 组件可能无法适应新数据或不断变化的业务环境,因为传统架构并没有考虑到 Salesforce 中持续学习和模型更新的需求。随着 Salesforce 组织的成长和数据量的增加,AI 解决方案可能难以应对多样化的数据集和使用场景,从而导致性能下降。
当没有充分考虑 AI 道德时,可能会引发伦理问题。Salesforce 的 AI 实现可能做出有偏见或不公平的决策,这可能使组织面临声誉或法律风险。由于 AI 决策过程的不透明性,排查 AI 问题时会更加困难。当出现问题时,由于 AI 的决策过程不像传统的 Salesforce 配置或 Apex 代码那样透明,Salesforce 管理员和开发者可能很难诊断出根本原因。
用户满意度往往因此受到影响。Salesforce 用户可能对 AI 功能在处理复杂场景或适应特定业务流程方面的能力感到沮丧,导致采用率低。随着 Salesforce 组织的演变,维护变得越来越困难,团队发现更新 AI 组件时可能会产生意外的后果。
资源消耗是另一种常见的结果。试图使用传统的 Salesforce 定制方法来“修复” AI 问题可能导致配置和代码变得越来越复杂,消耗更多的计算资源,并可能触及 Salesforce 的限制。
也许最令人失望的是错失了创新的机会。将 AI 仅仅视为一个附加功能,组织可能无法充分利用 Salesforce 的 AI 能力,错失了真正转变业务流程的机会。
集成困难经常出现,AI 解决方案难以与其他 Salesforce 功能或第三方工具顺利协作。这通常是因为 AI 系统的独特需求在初始架构中未得到妥善处理。
实质上,“AI 架构像传统架构”的反模式常常导致 Salesforce AI 实现未能兑现其承诺。它们不仅未能提升业务流程和提供有价值的洞察,还可能带来新的问题和低效。最初看似简单的 AI 集成,最终证明是一种幻觉,因为组织发现自己在 Salesforce 环境中面临着意想不到的挑战和令人失望的 AI 性能。
更好的解决方案
为避免陷入“AI 架构像传统架构”反模式,组织应采取更加细致和 AI 友好的 Salesforce 开发和实施方法。
首先,投资 AI 教育至关重要。整个 Salesforce 团队,包括管理员、开发人员和架构师,应对 AI 概念有扎实的理解,特别是在 Salesforce Einstein 能力的背景下。这一知识基础对于做出有关 AI 集成的明智决策至关重要。
采用以数据为中心的设计方法至关重要。组织应从彻底分析其 Salesforce 组织中的可用数据开始。AI 解决方案应围绕数据的质量、数量和与 AI 模型相关性进行设计,同时考虑 Salesforce 数据结构和关系如何影响 AI 性能。
模型监控和再训练的规划是另一个关键方面。应实施机制,跟踪模型随时间的表现,并根据需要对模型进行再训练。这可能涉及在 Salesforce 中创建自定义对象来存储模型元数据和性能指标。
采用迭代开发方法可以根据 Salesforce 环境中的实际表现和反馈持续优化 AI 模型。这种敏捷方法比传统的瀑布式方法更适应 AI 系统的不断发展。
强大的数据预处理至关重要。组织应开发 Apex 类或特别利用 Salesforce Flow 来清洗和准备数据,以适应机器学习算法的独特需求。
设计可解释性对于用户信任和合规性至关重要。在可能的情况下,应使用提供模型决策洞察的爱因斯坦功能。对于自定义模型,可以添加日志记录或可视化功能,帮助用户在 Salesforce 工作流中理解 AI 输出。
应优先考虑伦理问题。应制定关于 Salesforce 中伦理 AI 使用的指南,包括检测和减轻偏见的机制。这可能涉及创建自定义验证规则或 Apex 触发器,以标记潜在的问题决策。
组织应充分利用 Salesforce 的 AI 基础设施,例如爱因斯坦平台服务(Einstein Platform Services),该服务旨在与 Salesforce 的其他功能无缝集成并遵循平台治理。然而,同样重要的是要规划优雅降级,确保当 AI 组件失败或产生低置信度结果时,Salesforce 架构能够回退到基于规则的决策机制。
应实施全面的测试策略,不仅仅包括传统的单元测试,还应包括模型性能的 A/B 测试以及使用多样化数据集进行的基于场景的测试,所有这些都应在 Salesforce 测试框架内进行。
用户教育对于成功的 AI 采纳至关重要。应开发应用内指导和外部文档,帮助 Salesforce 用户了解 AI 功能的能力和局限性,设定现实的期望。
最后,保持人工监督至关重要。Salesforce 工作流应设计成允许人工审查和在适当情况下覆盖 AI 决策,特别是在高风险场景中。
通过遵循这些最佳实践,组织可以创建真正发挥 AI 潜力的 Salesforce 解决方案,同时解决 AI 系统在 Salesforce 生态系统中面临的独特挑战。这种方法有助于确保 AI 真正为 Salesforce 用户带来价值,而不仅仅是增加复杂性或跟风。
我们现在已经讨论了反模式,接下来准备着眼于数据领域的关键要点。
了解关键要点
在本节中,我们将稍微抽象一下具体模式,而是尝试提炼出您在日常工作中作为 Salesforce 架构师或准备 CTA 审查委员会时可以使用的更广泛的学习要点。
在设计 Salesforce 解决方案时,您应当注意以下几点:
-
Salesforce 采用了一种独特的数据建模方法,这种方法不容易与传统方法(如关系数据库设计)进行映射。
-
试图将 Salesforce 强行适配为这种方法只会导致灾难。
-
相反,您应遵循 Salesforce 自身建立的良好实践,并以平台自带的数据模型为例。
-
这包括使用广泛的业务对象建模,而不是采用规范化模型,强烈依赖标准对象,并限制在数据层面进行自定义工作的数量。
-
未能在团队之间协调活动可能会导致数据模型层出现严重问题,并大大降低您在未来项目中完成工作的能力。
-
因此,始终推动适当的协调或治理论坛,确保团队了解彼此的工作内容。
-
如果可能,将数据治理机制,如数据所有权、数据建模标准和指导方针以及对具有严重数据层影响的决策(例如添加新自定义对象)的审批过程,加入到这个协调论坛中。
-
如果知道需要达到某个规模却不进行必要的计算,来判断该规模是否应该在项目中积极规避,那就是一种重大的错误。
-
如果您决定不积极采取措施来缓解规模带来的潜在后果,您需要在完全了解风险的前提下进行决策,并制定计划,必要时进行重构和重新设计。
-
一般来说,忽视规模因素在初创公司和实验性项目中可能是适用的,但在企业级系统中则很少适用。
-
业务用户通常喜欢数据同步的概念,因为它能够提供更优秀的用户体验。然而,他们很少意识到其中的技术复杂性。
-
小规模的数据同步通常是解决问题的好方法,但要警惕过度扩展它们的规模和复杂度。
-
避免在超过两个系统之间双向同步相同的数据点,并小心同步大量对象和字段,除非是针对严格的单向用例,例如数据传输到数据仓库。
-
抑制在没有明确商业案例和数据需求理解的情况下添加 AI 功能的冲动。
-
将 AI 组件视为与传统 Salesforce 自定义功能根本不同,需要独特的架构考虑。
-
在设计 Salesforce 中的 AI 驱动解决方案时,优先考虑数据质量和数量。
-
在 Salesforce 组织内实施强大的 AI 模型监控和再训练机制。
-
设计 Salesforce 流程,确保在 AI 组件失败或产生低置信度结果时,能够优雅地降级。
在为 CTA 评审委员会做准备时,您应注意以下事项:
-
在为您的场景创建数据模型时,理解并遵循良好的建模实践。
-
这意味着以“Salesforce 方式”建模,而不是采取过多自由度,最终需要解释和辩护。
-
首先使用标准对象,只有在完全确信没有标准对象足以满足需求时,才应在解决方案中使用自定义对象。
-
明确哪些对象用于什么目的,避免在多个地方存储相同的数据。
-
在数据模型概述中,将所有非明细对象的数据所有权在角色级别上纳入考虑。
-
在描述治理模型时,您可能希望提及一些关于良好数据治理的建议。
-
对场景中的关键对象的数据量进行计算,并明确识别任何可能有 LDV 要求的对象。
-
通常,这些是系统中关键实体之间的连接对象,但也有例外情况。
-
为相关对象创建清晰且经过深思熟虑的 LDV 缓解方法。仅仅列出常见的 LDV 缓解技术是不够的。
-
在指定系统之间的数据流时要小心。您需要现实地考虑您提议传输的数据及其方式。
-
优先选择单向同步和集成,而非双向同步。
-
在当前场景中,尽可能优先选择数据虚拟化,而不是数据同步。
-
展示对传统 Salesforce 架构和 AI 驱动解决方案之间根本差异的理解。
-
阐明确保数据质量和相关性策略,以适应不同规模和复杂性的 Salesforce 组织中的 AI 模型。
-
解释在 Salesforce 环境中监控和维护 AI 模型性能的方法。
-
讨论将 AI 组件与现有 Salesforce 功能和第三方系统集成的方法。
-
概述在 Salesforce 组织数据和用户群体增长时,扩展 AI 解决方案的架构考虑。
我们现在已经覆盖了本章的内容,并准备继续深入解决方案架构领域。但在此之前,我们先总结一下我们的学习成果。
总结
在本章中,我们讨论了如果不小心,在数据领域可能出错的很多方面。数据层出错往往会影响到上层的所有内容,因此,如果你陷入任何这些反模式,未来的配置、集成和开发工作将面临严重后果。
因此,在数据领域,学习良好的结构、良好的实践和健全的治理尤其重要。并不是说它们在其他领域不重要,但如果你搞错了数据层,那么其他方面也很难做对。
这一点既适用于现实生活,也适用于 CTA 考试。正如许多有志成为或已经是 CTA 的人所说的那样,如果你在某个场景的数据模型中出现了任何重大错误,往往会影响到其他领域,从而使得通过整体场景变得非常困难。
在讨论完数据领域后,我们将继续讨论解决方案架构——这是一个充满反模式的领域,我们必须非常有选择性地决定哪些反模式需要包含在内。
第二部分:解决方案反模式
本部分将教你如何识别并缓解解决方案架构以及集成架构中的反模式。
本部分包括以下章节:
-
第五章 , 解决方案架构问题解析
-
第六章 , 保持集成清晰
第五章:解决方案架构问题
本章将涵盖与你的解决方案架构相关的反模式。我们将从选择解决方案相关的反模式开始。然后,我们将探讨功能设计时可能出现的问题。第三,我们将探讨一些影响定制的特定反模式,首先是概念层面上的,然后是代码层面上的。我们将在本章的最后总结关键要点。
在本章中,我们将涵盖以下主要内容:
-
如何避免通过基于不良研究和分析选择错误的解决方案方法
-
为什么你的假设可能会误导你,使你的架构和设计走偏
-
在错误的方式下应用好的功能可能会出问题,如何通过良好的治理来克服这个问题
-
经典的代码反模式如何也会出现在 Salesforce 的实现中,以及你如何设计更有结构和模式的代码
完成本章后,你将对如何在 Salesforce 上设计解决方案时避免常见的反模式有一个很好的了解,并且知道可以采取哪些步骤来为合适的问题使用正确的解决方案。
选择错误的方案
本节将探讨解决方案选择中看似微小的决策如何对你的 Salesforce 实施产生深远的影响。我们将看两个与选择错误解决方案相关的反模式,这些反模式基于一些与技术无关的考虑。我们将首先探讨当你忽视更广泛的生态系统时会出现什么问题。
忽视生态系统
故意忽视第三方选项而偏向内部解决方案可能会变成反模式。
示例
SafeCo 是一家大型保险公司,为大众消费者市场提供各种保险产品。它拥有一个庞大的客户服务组织,目前正在最后阶段推出 Salesforce Service Cloud,以实现对客户咨询的 360 度全景视图。
Royce 是 SafeCo 公司 IT 部门的经理,曾间接参与过 Service Cloud 项目。然而,现在,他被指派领导一个团队,该团队的任务是找到几个新出现的通用需求的合适解决方案,这些需求在项目初期的范围之外,如下所示:
-
首先,SafeCo 在进一步了解 Salesforce 后,决定需要一个备份解决方案,因为他们不想仅仅依赖有限的开箱即用功能
-
其次,虽然政策文件是由业务线(LOB)系统生成的,但相关方已经发现有必要直接从 Salesforce UI 打印几封标准客户信件。
-
最后,在 IT 部门中,有几个人询问是否可以在 Salesforce 上使用项目管理工具,因为他们认为这将是与业务用户协作的一个好平台。
Royce 开始着手解决最紧迫的备份问题。他大致知道在 AppExchange 上有几种解决方案可以解决这个问题,但在简要查看之后,他发现它们太贵且过于复杂。而且,SafeCo 已经为其他系统建立了备份基础设施。Royce 请 IT 部门的开发人员写了一个脚本,将 Salesforce 对象一对一地复制到结构化查询语言(SQL)数据库中,方法是将它们导出为 CSV 文件,然后使用标准批处理过程进行导入。然后,可以使用 SafeCo 的标准备份解决方案对数据进行备份。
文档生成是另一个 Royce 知道有多个第三方解决方案存在的领域。然而,企业的文档管理系统(DMS)也有一些内部的文档生成能力,这正是他开始关注的地方。虽然解决方案并不完美,但 DMS 团队可以通过接受一个 web 服务请求来提供该能力,该请求将被放入队列中,而队列会定期被一个批处理作业清空,生成文档并将其放入文件共享中。然后,另一个作业会取出这些文档并将其上传回 Salesforce。这个过程稍显缓慢且笨拙,但应该还可以。
对于项目管理模块,Royce 运气不错。在一个周末,他的团队中的一名成员整理出一个小应用程序,似乎展示了 SafeCo 所需要的许多功能。他估计在几周内,他可以开发出足够好的东西,足以推广到业务中。Royce 赢得了这一小胜,并决定采用它。
现在,Royce 已经有了解决方案,他督促团队加快进度,确保按时完成全球服务的上线。然而,尽管没有出现灾难性的故障,但仍然有不少问题需要应对。备份脚本工作正常,但在新环境和部分环境中进行完整和部分恢复测试时,他们遇到了一个巨大的、意料之外的复杂性。他们放弃了业务连续性(BC)测试,并计划稍后开发一些更复杂的恢复脚本。
如预期所示,关于文档生成速度慢有一些抱怨,但最严重的问题是模板管理,这一点 Royce 在分析时并未详细考虑。事实证明,模板变动频繁,而在新方案中,所有模板的更改必须由 DMS 团队中的某人来完成,这让客户服务团队感到相当恼火。
项目管理应用程序顺利推出,没有出现重大问题,但反响平淡。出现了几处漏洞和误解,总体来说,团队原本期待的几个功能并没有包含在内。因此,各团队的采用情况不太理想。
Royce 深吸一口气。尽管一切大致正常,但存在很多问题。Royce 想知道自己是否在过程中错过了什么,但现在是时候结束这个项目,继续前进了。
问题
在忽视生态系统部分中解决的问题是如何处理与实施主要需求相关的常见功能,但这些功能不完全是核心需求的一部分。这些功能包括常见的备份和恢复、文档管理和生成、自动化部署流水线、将日志发送到中央日志服务器以及一系列类似的需求。
对于这种类型的需求(以及许多其他需求),AppExchange 上存在大量第三方解决方案,它们通用地解决了这个特定的需求,如下图所示。此外,许多 Salesforce 咨询合作伙伴也有标准方法,其中包括使用加速器或内部资产,这些也能帮助解决此类需求:
图 5.1 – AppExchange 的顶级类别部分
使用这种反模式,你可以忽略这些选项,甚至不认真考虑它们。
提议的解决方案
当你忽视生态系统时,你主动忽略了通用需求的第三方选项,而是继续采用定制或内部解决方案来处理常见功能。尽管对于通用需求采用定制答案是有正当理由的——例如,如果你拥有某项功能的高度开发基础设施,想要在所有企业系统中使用它——但如果不与现有的商业选项进行理性比较,这就是一种反模式,并且违背了 Salesforce 的核心理念。
也就是说,当你没有为重要但通用的功能做出经过深思熟虑的构建与购买决策,而是本能地选择内部解决方案时,就会出现反模式——无论是因为“这里没发明”症候群,还是因为这样对组织的关键利益相关者来说更容易处理。当用户熟悉其他平台并希望你在 Salesforce 上重建其功能时,这种情况也经常发生。
再次强调,这并不是说在这些能力上构建的方法永远无效。但根据我的经验,你很可能低估这些构建所涉及的复杂性和持续成本,并且最终可能会得到更少的功能,却花费比业务案例中预期的更多的钱。
结果
忽视生态系统的结果通常是可以预测的。然而,在详细层面,它们会根据所考虑的能力有所不同。然而,在更高的抽象层次上,它们往往如下所示:
-
一个功能较弱的解决方案,它满足的需求比你在生态系统中以类似成本能获得的要少。
-
随着时间的推移,增加到该功能的新特性越来越少,且其维护成本往往高于第三方解决方案的常规成本。
-
需要为开发和维护内部能力而维持额外的技能和知识储备。
-
新功能与现有系统之间的耦合度比使用第三方解决方案时要高。
-
成本情况可能复杂,但自己构建一个通用能力通常不会带来显著的节省。
总的来说,结果很少是灾难性的,但通常,最终的解决方案比第三方的同类产品更差,而且是以更大的痛苦和风险达成的。
更好的解决方案
有一个普遍的建议需要记住,以避免这种反模式,尽管实施它可能是一个挑战,那就是在遇到相对常见的功能需求时,做出经过深思熟虑且有充分理由的“构建与购买”决策。
对 AppExchange 解决方案的更全面评估对于像 SafeCo 这样的组织至关重要。通过仔细评估各种选项,公司可以发现不仅符合其独特需求的工具,还能提供额外功能和持续支持。这种积极的方式可以在长远来看节省大量时间和资源,确保所选解决方案有效促进业务增长和运营效率。
为此,你应该做以下几点:
-
仔细探索生态系统的替代方案,包括在 AppExchange 上的选项以及来自 Salesforce 合作伙伴的直接解决方案。
-
积极与供应商互动;他们通常比你想象的更愿意考虑你的独特问题。
-
详细列出潜在选项,以便做出有根据的决策,记得包括架构、运营和商业考虑因素。
-
在列出内部选项时,计算总拥有成本(TCO)。在这类比较中,运营、维护和进一步开发成本通常被低估。
-
与第三方供应商进行艰难的商业谈判——你通常能获得相当可观的折扣。定期进行生态系统审计,保持对新 AppExchange 产品的了解,以替代或增强自定义解决方案,可能减少技术债务。此外,定期审查现有解决方案,寻找优化机会,并能够集成与业务需求相符的新工具。
在审视忽视生态系统的后果后,让我们考虑将解决方案与许可相适配,而不是将许可与解决方案相适配的后果。
基于许可的解决方案
基于你能够负担的许可集而非真正需要的许可集来创建解决方案,而不做出 必要的妥协。
示例
Alexis 是 Salesforce 一家主要合作伙伴的首席架构师,直接与 Salesforce 合作,处理位于中等规模的欧洲国家 Ruritania 的社会福利部的一个项目。该部门为数百万居民提供服务,拥有几千名社会工作者,分布在总部和几百个地方办事处之间,大约是 50/50 的比例。他们正在将 Salesforce 作为案件管理平台,用于一个旨在帮助因生活成本不断上升而受困的家庭的新高调倡议。
作为协议的一部分,Salesforce 的客户代表(AE)强烈推动了一种许可模式,使得总部用户可以拥有完整的 Salesforce 许可证,而地方办事处的用户仅拥有 Customer Community Plus 许可证。他认为,由于地方办事处的工作人员技术上是当地政府的成员,根据 Salesforce 的许可条款,这种方式是可以接受的,并且能够为客户提供更为可接受的许可证费用。
Alexis 迅速指出的一个含义是,社会工作者将基于社区在两个不同的界面中工作,一个是内部界面,一个是外部界面。然而,AE 认为这些差异很小,大部分为内部界面所做的工作可以直接在社区中复制。
虽然一般来说这是正确的,但随着工作持续进行,许多微妙的差异开始产生影响。系统中客户社区 Plus 用户能够访问的内容有所不同,此外,在 Lightning 页面和社区页面上可以显示的内容以及如何显示也存在差异。
这种情况迫使越来越多的功能被转移到自定义代码中,特别是转移到一系列小型Lightning Web Components(LWC)中,以适应这两个界面。此外,所有测试用例需要编写并执行两遍,每个界面各一次,这增加了相当大的工作量。
在应用程序推出时,他们还需要创建两个版本的文档、培训材料和实际的用户培训。Alexis 还指出,她的公司将需要提高应用程序的维护费用,因为维护的自定义功能更多,而且未来的许多更改都需要在两个版本中进行。
用户总体上对新应用程序感到满意,但由于地方办事处和总部之间界面的差异,很多沟通错误和失误发生。社会福利部的财务主管也对实施成本和应用程序维护费用的增加感到不满,他认为这并未完全通过较低的许可证费用得到补偿。
问题
基于许可证的解决方案解决的问题是一个老生常谈的问题:如何在我们给定的成本范围内交付所有必需的功能?如果你从未经历过将用户需求与预算紧张的情况相匹配的挣扎,我想知道你在哪里工作,我好去应聘。
几乎普遍适用的是,利益相关者希望拥有更多的功能,但他们的预算却不足以购买这些功能。为了解决这个问题,一种方法是尽可能优化购买的许可证,以获得最佳的性价比。这被称为许可证优化,是 Salesforce 平台上的一项基本技能。以下是 Salesforce 许可证模型的概览:
图 5.2 – Salesforce 许可证模型
基于许可证的解决方案通过明确哪些许可证是可负担的,并将解决方案的其他部分强行调整以使其适应,反而将这一可取的做法变成了反模式。
提议的解决方案
基于许可证的解决方案提议通过使用变通方法和自定义功能来填补所需许可证类型与可负担许可证类型之间的差距,从而为给定的一组需求创造一个可负担的许可证组合。这意味着,当存在一个标准的许可证类型可以满足用户需求时,你却选择采用一个定制或部分定制的解决方案,试图在你拥有的许可证功能和你希望拥有的许可证功能之间架起桥梁。
这里是一些常见的示例:
-
为内部用户使用社区许可证——虽然这些用户外部足够,不至于明显违反条款——如果不是因为价格过高,他们理想情况下会使用内部 UI
-
使用影像对象来复制未涵盖的标准对象——例如,拥有一个影像案例对象,通过双向复制 Case 中的信息,以便内部案例工作人员能够使用更便宜的平台许可证
-
复制行业云中的关键功能——例如,行动计划——因为不愿意采用额外的许可证
-
在具有相同组织角色的不同用户之间共享许可证,规避条款和安全性。
-
对某些功能使用更便宜的解决方案——例如,使用 WordPress 网站代替社区来节省许可证费用,然后在网站和 Salesforce 之间同步数据
虽然这些做法在商业上可能有其合理性,但从技术角度来看,它们无疑是适应不良的。
结果
结果可能会根据具体的使用案例有所不同,但通常包括以下几种情况:
-
需要更多的自定义工作以弥补许可证功能的不足
-
为了使不同部分合理地融合在一起,解决方案的整体复杂性增加
-
由于定制工作增加和整体复杂性增加,未来的维护工作会更多。
-
由于你需要考虑增加的定制工作,未来功能升级的价值会减少。
-
由于共享许可或重用单一许可处理多个功能,安全性可能降低。
因为实施解决变通方案和定制解决方案来绕过许可限制,可能会带来增加的技术债务。这些做法可能导致显著的长期维护成本,因为它们通常需要额外的资源来管理和支持,进一步增加了技术复杂性。
这可能会让你处于一个与 Salesforce 的灰色地带,因为许可协议对外行人来说不容易理解,而且 Salesforce 在如何执行条款方面并不透明,特别是在存在相当模糊的情况下。
话虽如此,从 TCO(总拥有成本)角度来看,有时确实是你最好选择不购买许可,而是做定制工作。Salesforce 的许可费用昂贵,如果你只需要功能许可中包含的一小部分内容,你可能能够以较低的价格重新构建它。
然而,我的建议是尽可能避免这样做,而是寻求替代选项,正如我们将在下一节中讨论的那样。
更好的解决方案
通常情况下,你最好是尝试与 Salesforce 谈判获得更好的交易,寻找第三方解决方案来满足你所需的特定功能,或者重新设计解决方案,避免使用你需要的特定功能,方法是改变范围或重新定义谁需要哪个功能许可。
让我们逐一看这些:
-
当面临无法负担的许可费用时,你的首选应该是更加强硬地推动你的 Salesforce 客户经理。他们通常有相当大的灵活性可以提供折扣,尤其是当我们讨论的是新类型的许可,或者你愿意承诺在交易中更长的周期时。在 Salesforce 财务季度结束前推动谈判也会有所帮助。
-
第二,你应该考虑第三方解决方案。你可以查看 AppExchange,看看是否有价格更低的产品满足你的需求,或者你可以询问你的实施伙伴是否有可用的资产可以利用。
-
第三,你可以返回公司,请他们重新优先排序功能,以便你可以削减其他内容以腾出空间来支付许可费用,或者删除需要额外许可的功能。
-
第四,你可以返回并进行另一轮许可优化,详细审查拟议的许可,并查看你能在哪里为特定用户减少特定许可。通常,某些许可对某些用户来说是必须的,但对其他用户则只是可选的。
如果你找不到好的解决方案,必须按照这种反模式进行,务必意识到其中涉及的实际成本和风险。话虽如此,让我们继续讨论下一个反模式:假设驱动的定制。
错误地应用方案
在本节中,我们将考虑两种反模式,这些反模式基于我们带到桌面上的假设失败,导致了不满意的解决方案。这些假设可能是关于用户需求或我们技术的能力——这两者都可能导致问题。
假设驱动的定制化
让一个小而不具代表性的群体的假设来代替更广泛用户群体的需求。
示例
Helene 是 LifeCo 一项新计划的产品负责人,负责推出 Health Cloud,这是 LifeCo 一家主要的慢性病监测医疗设备供应商。除了 Health Cloud 的推广外,LifeCo 还在开发一款定制的护理应用程序,主要供卫生保健专业人员(HCPs)使用,尤其是为 LifeCo 护理项目提供服务的诊所中的护士使用。
Helene 曾是一名护士,后来转入 IT 领域,并且曾担任过几款主要 IT 产品的主题专家(SME)。因此,她认为自己对需求有很强的理解,并且有几位仍在当护士的朋友,作为她的反馈渠道。
在经过一些内部讨论后,Helene 决定将应用程序交付为一种优化了平板电脑使用的应用程序,因为她知道平板电脑在诊所中很常见。这将允许卫生保健专业人员在与患者互动时记录与护理项目相关的信息。
团队开发了一个既具有吸引力又功能强大的平板应用程序,满足了 Helene 确定的所有关键需求。在与友好的用户群体进行初步测试时,该应用程序受到了高度评价,大家都期待着正式推广。
然而,当他们开始计划推广时,许多诊所却反对并拒绝实施新的应用程序。经过调查,问题的根源在于,尽管许多诊所的工作人员有平板设备可用,但他们不愿意直接在与患者互动时使用它们,因为他们觉得这会妨碍互动。
对于其他卫生保健专业人员(HCPs)来说,在与患者的互动中直接录入数据与他们长期以来的做法相违背——他们习惯于白天用纸质笔记收集信息,然后在下班后通过 PC 录入系统,这些 PC 的界面经过高度优化,便于快速录入数据。这些卫生保健专业人员觉得转用新系统会让他们花更多时间在数据录入上,从而减少与患者接触的时间。
Helene 有一长串反驳意见,来回应卫生保健专业人员提出的担忧,她坚信通过适当的培训和流程变更,最终用户将会看到新应用程序如何显著改善他们的工作实践。然而,她遇到了一个不幸的事实:拒绝采用新应用程序的诊所都不是 LifeCo 直接拥有的,所以无法强制它们进行改变。
这对 LifeCo 来说是一个重大问题,因为这意味着他们必须保持旧的护理项目管理系统运行,并且将同时使用两个不同的护理信息数据库,这会导致严重的整合问题。Helene 被迫寻找一个快速的解决方案,以满足那些拒绝使用的诊所。
解决方案与实际用户需求之间的这种不对齐,不仅影响了采用率,还导致了生产力的显著下降。用户在挣扎于操作一个不适合的系统时,采取了寻找变通方法的方式来完成任务,但这些替代方法却在数据管理中引入了不一致性和错误。因此,依赖于非正式流程降低了数据的完整性和可靠性,进一步复杂化了决策过程,并损害了整体组织的效率。
最终,她不得不妥协。她和团队一起坐下来,看看能做些什么,以创建一个可以在 PC 上使用的应用程序版本。他们迅速移植了关键功能,并发布了一个简化版本给那些拒绝接受平板应用程序的诊所。虽然反应冷淡,但至少这次没有人拒绝使用它。
问题
基于假设的定制化的问题在于,它比它试图解决的问题要少——理论上它可以是任何东西——更多的是关于你尝试解决问题的方式。通过基于假设的定制化,你是在尝试解决一个由产品管理、产品负责人或开发人员定义的问题。
然而,事实证明,你需要解决的真正问题完全不同。换句话说,基于假设的定制化问题在于,你无意中在试图解决错误的问题。
这与仅仅要求错误不同,因为它可能发生在遵循良好流程的优秀团队中。所需要的只是你所使用的样本在某种程度上系统性地偏离了真实的用户群体,就像我们在示例中所看到的那样。
提议的解决方案
提出的基于假设的定制化解决方案是让一群专家代替更广泛的用户群体,以促进所构建解决方案的快速交付。这是一个完全合理的方法。我们在大多数事情上都让专家引导我们,而且通常情况下,这样做效果非常好。
只有当你的代表性专家与真实的用户群体相比,出于某种原因,存在系统性的偏见时,事情才会出错——例如,有人曾经在某个职能部门工作,但现在已经脱离了日常现实,或者某人早些时候转行做了 IT,现如今已经从 IT 的角度来看待问题。
请注意,有时候,你可能会推出一些并不是用户群体所期望或要求的东西,以推动变革。这是一个完全不同的情形,关键在于你如何进行变更管理。然而,如果你无意中且未意识到这样做,那么你就是在使用反模式。
结果
假设驱动的定制化结果取决于与用户需求和期望的契合度:
-
在规模的一端,你有一组基本无害的误解,这些误解可以通过善意、培训和一系列替代方案来修复。
-
如果这样还不够,你可能需要添加或重新设计一些有限的功能,以让用户在新系统上能够愉快地工作。这仍然是相对可控的。
-
然而,有时你会遇到一个阶段,用户完全拒绝采用新系统,即使进行了大量修改。
-
此时,你有两个选择:要么强行推进并应对来自用户群体的反弹,要么放弃这个工具,回到旧的方式。
以下图表提供了结果规模的可视化表示:
图 5.3 —— 假设驱动的定制化结果恶化的规模
因此,这种反模式的后果虽然通常是轻微的,但也可能是灾难性的,你应该花时间注意避免它。
更好的解决方案
这是一个难以防范的模式,因为它发生在我们信任的代表用户群体的人在某些重要方面未能代表这些用户时。必须向产品经理或产品负责人提出这些问题时,可能会非常不舒服,他们通常对自己的立场非常有信心,公平地说,大多数情况下,他们会是对的。
然而,一些机制可以帮助解决这个问题:
-
与用户群体的更广泛咨询——例如,通过大型活动或共同的在线论坛。
-
来自更广泛用户群体的早期反馈。路演、演示视频和网络研讨会是不错的选择。
-
来自更大用户群体的逐步验收测试。
-
如果你希望创造深远的变革,要做好规划,并包括必要的变更管理。永远不要试图偷偷进行重大变更。
这就结束了我们对这种反模式的讨论。现在,让我们看看一个真正经典的例子:黄金锤。
黄金锤
黄金锤犯下的根本错误是把一个在某些使用场景下是好解决方案的工具,错误地当作适用于所有使用场景的工具。
示例
WheelCo 是一家大型轮胎制造商,特别专注于运输行业。它正在推出以制造云为核心的 Salesforce,以紧密连接其制造和销售流程。
根据与 Salesforce 达成的协议,WheelCo 获得了无限制使用 OmniStudio 的权限,并参与了与产品能力相关的多次培训和加速器。因此,WheelCo 的架构师、开发人员和业务用户都对 OmniStudio 能为他们的业务带来的价值感到非常兴奋。
在最初的架构讨论中,决定将整个解决方案建立在 OmniStudio 工具集上,包括所有 UI 过程(无论是内部的还是外部的)、集成和任何可以合理使用 OmniStudio 的附属流程。只有批处理和异步流程被排除在范围之外。通过这种方式,WheelCo 认为可以最大化从 Salesforce 购买中获得的价值。
项目启动后,在许多领域取得了快速进展。为了保持一致性,大多数标准用户界面(UI)部分被忽略,FlexCards 和 OmniScripts 几乎构成了整个用户体验(UX)。集成是通过集成流程开发的,除了少数在后台运行的集成。
开发的工作量远大于最初预期,但通过增加足够的资源,WheelCo 仍然设法按时完成了实施。尽管在寻找足够多具有所需 OmniStudio 经验的合格资源方面遇到了一些困难,但通过支付高薪,WheelCo 设法为项目招募到足够的人才,确保了项目的成功。
总体而言,上线是成功的,尽管有人抱怨并不是所有承诺的功能都已包括在发布版本中。在开发过程中,若干关键功能不得不被删减,以确保按时发布。
在接下来的年度中,解决方案开始显现出一些问题。集成的灵活性没有预期的那么高,无法适应业务希望添加的所有不同用例。另一个问题是 Salesforce 平台上的新功能发布。每当添加新的功能时,都需要对 OmniScripts、FlexCards 和有时是支持代码进行修改,才能使其对用户可用。
支持该解决方案的成本也很高。任何变更都需要高级技术人员的干预,这减少了平台的灵活性。在 WheelCo 内部,许多人开始质疑 OmniStudio 是否是满足项目中所有需求的正确解决方案。
这一点尤其适用,因为一些排除在 OmniStudio 工作之外的原生制造云功能似乎在没有任何人为干预的情况下迅速得到改善。
大约一年后,WheelCo 的首席技术官(CTO)任命了一位新的首席架构师,他将 Salesforce 平台的架构作为早期的优先事项之一进行审视。他发现大量定制化导致的高复杂性是成本和功能问题的主要根源。为了解决这一问题,他建议重构解决方案,使其采用更加标准化的用户界面,保留 OmniStudio 用于复杂的多步骤流程和需要特定数据视图及相关操作能够创造真正价值的领域,并在其他地方去除该功能。
问题
黄金锤子解决一切问题——这就是黄金锤子的特性。一旦你找到了黄金锤子,遇到的每个问题都会变得合适。没有对目标适配性的评估,因为黄金锤子就是解决方案。
技术行业通常很容易陷入黄金锤子陷阱。我们总是在寻找下一个酷炫的技术来解决我们的难题。Salesforce 以其激进的销售方式和 Kool-Aid 喝水般的社区,可能比大多数技术平台更容易陷入这一反模式。
请注意,黄金锤子通常在其解决方案空间内是技术上非常优秀的,但由于热情、炒作和兴奋,它们往往被拉得超出了这个空间。
提议的解决方案
黄金锤子提出的解决方案就是黄金锤子——无论问题是什么,无论问题的参数如何,它们都会被扭曲成黄金锤子可以解决的某种形式,或者黄金锤子会被扭曲成能够解决问题的某种形式。
如果必须选择,最好是将问题调整为适应不合适工具的形态,而不是将不适合的工具应用于问题。但无论哪种选择,都不是特别理想的。
检查是否受到黄金锤子影响的一个好方法是,查看你对新技术功能的讨论是否以寻找你的技术栈可以解决的问题开始,还是从问题入手然后寻找合适的技术栈。如果是前者,你需要小心,因为你可能已经拿到了一把黄金锤子。
结果
黄金锤子的结果取决于你所参与的技术适配不良的程度:
-
至少,你最终会发现与你本应满足的需求存在差距,因为黄金锤子未能解决某些问题,因为它不是为解决这些问题而设计的
-
随着黄金锤子被不断延伸超出其能力范围,成本和定制工作将增加
-
由于过度延伸的解决方案所产生的额外维护工作和由此带来的成本
-
即使黄金锤子确实是一个合适的解决方案,也会导致组织对黄金锤子的真实能力失去信心
-
在你企业的不同领域中,保持一个专门的技能集是必要的,即使当某个工具不再流行或趋势过时时,这种技能集仍然会持续存在。
总的来说,结果将取决于你在多大程度上拉伸了工具的能力,但在你还没有搞清楚问题之前就选择工具,往往是一个反模式。
更好的解决方案
建筑师在采纳新工具和技术方面的态度各不相同。根据我的经验,Salesforce 的架构师在采用新技术时相当积极,只要它们是在平台上。因此,当我说我的一般建议是对采纳最新的工具集保持相当保守的态度时,尤其是在 Salesforce 上,我可能会显得有些固执。
在 Salesforce 生态系统中,我们不断受到新功能、新工具集和新做事方式的轰炸。虽然这是好事,但改变一个过去对你有效且继续为你的组织带来价值的方法,应该在仔细考虑之后进行,而不是因为 Salesforce 刚刚发布了一个闪亮的新玩具。
实施定期审查你的技术栈的过程。这有助于确保你为每个任务使用最合适的工具,并允许你逐步淘汰过时或低效的解决方案。以试用的方式接触新工具集,选择有限的业务使用案例来收集见解并评估它们的价值。如果一个工具提供了真正的价值,可以考虑在整个组织中推广;如果它没有提供价值,无论它多么有吸引力,都应该停止使用。
工程溢出
本节中的两个反模式都代表了技术治理的失败,结果是将过多的工程工作投入到单一组件中,而没有应用适当的设计模式和实践来缓解这种情况。
自动化盛宴
自动化盛宴是指当你没有对关键对象上的自动化使用进行治理时所发生的情况。
示例
DrinksCo 是 Salesforce 平台的长期用户,使用它进行销售和客户服务,同时在 Marketing Cloud 上有着庞大而复杂的使用足迹。虽然整个系统中有多个组织正在使用,但有一个主要的组织管理着 Salesforce 使用的核心流程。
虽然这个组织已经有一段时间稍微有些吃力,但现在情况已经到了一个点,DrinksCo 的用户开始提出严重的投诉。像 Opportunity 和 Account 这样的关键对象上的记录保存时间,有时可能以分钟为单位来衡量。偶尔,记录会直接无法保存,显示一个模糊的技术错误信息。更糟糕的是,包含关于新潜在客户和机会的重要信息的同步作业,有时会随机失败,而且没有给出明确的原因。
Francesca 是一家精品 Salesforce 合作伙伴的 Salesforce 顾问。她受邀分析情况,并提出对组织的改进建议,理想情况下解决问题的根本原因,但至少能够迅速减少症状。
在一周的组织审查后,她不再怀疑:问题是由大量复杂的自动化在关键对象上相互作用引起的。例如,在 Opportunity 上,经过多年的演变,自动化形成了多个深层次的层次,合起来导致了严重的问题。
这包括一个大型复杂的 Apex 触发器,两个来自托管包的额外触发器,一些工作流规则,三个尚未迁移到 Flow 的流程构建器,一个前记录触发流,一个后记录触发流,几个操作该对象的批处理作业,以及多个直接使用本地 API 和自定义 Web 服务来操作 Opportunity 对象记录的集成。
Francesca 深吸一口气,开始有条不紊地绘制出不同事件序列的发生顺序,这些序列取决于 Opportunity 记录及其更新。她通过系统地跟随执行顺序,查看不同自动化之间是否可能存在不希望出现的相互作用效应。
经过一段时间,她得出结论,这些事件序列出错的方式太多,当前模型无法承受。如果不大幅减少自动化的复杂性,这个问题是无法解决的。
因此,她制定了一个重构计划,相信它能够有效缓解 Opportunity 对象最严重的症状,尽管可能无法完全消除问题。如果在 Opportunity 对象上成功,类似的计划将会应用于核心组织中的其他关键对象。
计划包括将流程构建器和一些工作流规则移入两个流中,合并集成使得只有一个集成定期处理 Opportunity 的导入,简化 Apex 触发器,并去掉那些已经不再严格需要的托管包。
该计划的实施远比最初预期的要长——需要考虑的因素太多,无法按计划进行。但最终,用户开始报告在使用 Opportunity 时的体验有所改善。旧的随机错误不再发生。尽管保存仍然比他们希望的慢,但已不再慢到成为严重问题。
在短暂享受成功之后,Francesca 深吸一口气,开始处理组织中其他关键对象的相关事务。
问题
自动化盛宴试图解决的问题是如何在 Salesforce 上创建自动化时适应不同的架构风格或偏好。当多个团队在不同项目中同时处理相同的对象,且通常来自不同的实施合作伙伴时,这几乎是不可避免的。
随着组织的成长,相互作用的自动化的复杂性可能呈指数级增加。不同的团队可能对自动化其特定需求有不同的处理方法,但这可能导致混乱和低效。因此,至关重要的是从一开始就建立清晰的自动化策略,以有效管理这些复杂性。
这时,你需要一种方法来指导架构随时间的发展,以保持一致性。如果你未能做到这一点,可能会陷入自动化盛宴。
提出的解决方案
自动化盛宴应对了多样化的自动化选项,其中一些选项在以下截图中展示,并且通过支持多样性,回应了自动化方法的多样性。这意味着团队可以选择最适合的孤立方法:
图 5.4 – 一些 Salesforce 自动化选项
这减少了团队之间的协调要求,通常不会导致短期问题。因此,发现问题或产生问题可能相当困难,直到事情已经出错。
结果
自动化盛宴的负面后果可能丰富多样。以下是一些经常发生的情况:
-
关键记录页面的性能下降——有时,保存操作可能需要很长时间才能完成
-
集成调用失败,特别是当这些调用以批量或批量方式更新记录时
-
批量作业或导入作业失败
-
在 UI 中发生奇怪、不可预测的错误,通常与保存或更新事件相关
-
调试平台上出现的问题时的困难,因为自动化的交互效应掩盖了整体情况。
总体来说,如果你陷入严重的自动化盛宴情境,可能会让事情一团糟。更糟糕的是,这种情况通常最先发生在你最珍贵的对象上,因为这些对象在各个项目中使用得最多。
更好的解决方案
避免自动化盛宴反模式的关键是对核心对象及其自动化进行良好的架构治理。为此需要注意的一些事项在此展示:
-
你应该从定义你希望在组织中使用的自动化类型以及对应的使用场景开始。
-
理想情况下,你希望每个对象的数量尽可能接近 1。选择流程或触发器作为首选自动化类型,并坚持使用它。
-
混合使用 Apex 和流程是可能的,但这需要仔细的规划和一个好的框架。
-
如果你使用流程作为主要机制,应该通过操作调用 Apex,而不是创建触发器,除非出于性能原因不得不这样做。
-
确保你有一个框架,帮助架构师使用流程。这个框架应包括使用子流程来保持灵活性。要有解耦的自动化流程,便于在出现问题时进行故障排查,而不是拥有一个包含所有业务逻辑的大型单体流程,后者通常紧密耦合且在长期维护上复杂且昂贵。
-
如果你使用触发器作为主要机制,可以使用一个触发器框架,例如 Apex Trigger Actions(
github.com/mitchspano/apex-trigger-actions-framework
),该框架使你能够在触发器执行时调用流程。 -
避免使用 Process Builder 和工作流规则,因为这些功能将被逐步淘汰。
-
批处理流程和传入集成需要小心设计,并且要考虑现有的自动化流程。记住,可以使用某些机制选择性地绕过某些流程的自动化,例如绕过标志。
-
注意管理包触发器和流程。你无法控制它们,但它们仍然可能通过与你的功能交互而导致问题。
一般来说,尽量保持自动化方法简单和统一,将为你的 Salesforce 组织带来可观的长期利益。话虽如此,让我们来看下一个反模式:过度复杂的组件。
过度复杂的组件
过度复杂的组件是指一个单一组件,它已经发展成了一个独立的应用程序,但没有足够的架构和设计来支持它。
示例
HealthyMindCo 是英国的心理健康服务经纪公司,正在 Salesforce 上实施一个新的案例管理解决方案。在这个解决方案中,案件工作者收集新客户的相关信息,并确定哪个实际的本地服务提供者最适合帮助他们。此外,他们还跟踪客户进行的咨询,以评估干预的有效性。
公司在系统应为潜在治疗选项和转诊可能性提供的推荐方面有非常特殊的要求,这些要求只能通过使用自定义代码来真正满足。由于 HealthyMindCo 倾向于简单且高度优化的用户体验,负责实施解决方案的项目负责人 Amir 决定使用一个 Lightning 组件,该组件可以融合创建新案例所需的逻辑。
最初的想法是该组件仅用于新案例。然而,在初步用户测试后,显然还需要添加更新功能。因为有太多情况下需要检查初步假设,这可能会导致治疗计划在不同情况下的不同结果。
添加了更新功能后,组件再次进行了用户测试,显而易见的是,组件还需要支持活动和活动模板的管理,因为这是治疗计划初始设置中的关键部分。团队努力将此功能添加到组件中,组件也开始变得像一个相当复杂的工程项目。
一旦活动和活动模板被添加到组件中,几个用户指出,将活动管理部分放入这个新的组件(现在已经被称为案件处理组件)并且不能在组件中跟踪这些活动的 SLA(服务水平协议)是没有意义的。这也意味着需要增加访问跟踪功能,因为这是管理 SLA 所必需的。
此时,Lightning 组件是 HealthyMindCo 员工使用的主要界面。由于这个原因,多个从其他系统获取信息的集成调用直接被添加到组件的代码中,因为反正这里是它最终会被使用的地方。
系统上线时并不轰动。存在很多 bug,尤其是在案件处理组件中。但凭借大量的善意和辛勤工作,团队逐渐将质量提升到一个足够可接受的水平,使得客户能够勉强使用它。
上线后,HealthyMindCo 不断在案件处理界面中发现新的 bug。它通常相当不稳定。此外,公司仍然希望在其中添加大量的新功能。然而,公司对其变更请求的报价并不满意。
Amir 向公司中的一些高级架构师咨询。他们评估了情况并告诉他,组件太大、过于单一且难以维护。他需要重构代码库,并从客户或内部获得资金来实施这一点。他尝试了,但似乎没有人特别愿意承担费用。
问题
通常,重量级组件是为了适应对定制用户体验(UX)的实际或感知需求,这种需求远远超出了 Salesforce 开箱即用工具所能提供的范围。请注意,在某些情况下,认为需要这种定制用户体验的看法可能比实际情况更为强烈。
来自旧系统的用户,习惯于在专门的应用程序中工作,或者他们的旧系统根据需求进行了大量定制,可能会认为在像 Salesforce 这样的平台上也需要进行类似的定制。某些用户可能对使用标准功能持有较大怀疑态度。毕竟,我们都喜欢认为自己所做的事情是特别的。
并不是说没有真正需要独特且高度定制的用户体验的情况,但根据我的经验,它们比很多人想象的要少。无论如何,重量级组件尝试提供这种体验的方式并不理想。
提议的解决方案
一个重量级组件提出在 Salesforce 内提供独特的用户体验,使用如 LWC 这样的开发框架来创建一个实际上是嵌入式的单体应用程序,驻留在平台上。这对于几个原因来说可能很有吸引力:
-
你可以完全控制单一组件内的用户体验和界面,允许你响应几乎任何用户需求
-
所有功能都被集成,架构简单易懂
-
所有内容都集中在一个地方,所有变更都可以在那里进行,从而减少了对工具和协调的需求
-
该组件仍然嵌入在标准的用户体验中,通过巧妙的样式使用,它甚至可能看起来像是标准配置的一部分
-
你可以在组件内调整用户体验,提供更多用户需要的内容
这个解决方案在一开始也往往看起来不那么危险,即使是对经验丰富的架构师和开发人员而言,因为我们讨论的仅仅是“另一个”LWC 组件。只有当该组件的真正范围被意识到时,它才会成为问题。
结果
尽管该组件仍然相对较小,你不会看到任何负面结果,当然,轻量级组件是大多数 Salesforce 架构中有用且架构上合适的元素。然而,随着组件的持续增长,它开始类似于一个独立的应用程序——一个基于代码的单体应用程序,存在于更大的应用程序中,但仍有自己的生命。
通常,这种情况是在一个本应完成相对简单任务的组件,意外地演变成一个功能的“万用”地点。通常发生这种情况是因为最初的组件非常成功,用户希望它做更多的事情。
这种演变的后果是熟悉的:
-
随着新组件变得过大和复杂,开发人员开始难以处理,质量开始下降,错误率增加
-
维护变得缓慢,错误修复和功能请求需要更长时间才能通过流程
-
只有某些开发人员能够处理重量级组件,因为它变得过于复杂,其他人无法处理
-
由于质量下降和功能过于拥挤,整体用户体验开始恶化
-
这个组件越来越难以与平台的其他部分集成,并且越来越被视为一个独立的应用程序
随着组件的规模和复杂性增加,测试变得越来越困难且耗时。这可能导致潜在的质量问题,影响系统的功能,并导致发布周期的延长,最终影响交付时间表和资源分配。
偶尔,这种模式可能会恶化到一种程度,导致最终形成“庞大的乱麻”——请参见 第二章。然而,即使没有发展到这种程度,你最终也需要进行大规模重构来解决这些问题。
更好的解决方案
鉴于重型组件的问题是你最终得到的是没有清晰架构的单体应用,应该不意外的是,你必须通过改进你即将交付的自定义功能的架构来解决这一反模式。
通常,这可以通过将较大的组件分解为一组更小、更易管理的部分,同时尽可能利用标准功能来实现。使用事件驱动架构(EDA),使得较小的组件通过发送和响应事件来进行通信,也会有所帮助。
此外,架构治理在这种反模式中起着关键作用。你应该为新组件设立评估和审批流程,同时也应定期安排人员检查被批准的自定义组件,因为它们往往会膨胀。
这并不意味着你需要进行正式的代码审计来检查每个人的工作,除非你的项目非常大,但你应该有架构师参与治理流程,并且了解你组织中任何自定义开发的细节。这将帮助你及早发现潜在问题。
接下来,我们将探讨两个以代码为重点的反模式,从神类开始。
代码乱作一团
本章中我们将讨论的最后两个反模式集中在代码中发生的反模式。虽然这些在 Salesforce 的世界中并不常见,但作为架构师,我们仍应意识到,我们的基于代码的解决方案必须遵循良好的实践,否则可能会陷入常见的反模式。
神类
神类是一个包含了应用程序定义的所有或大部分业务逻辑的单一类。
示例
ShoeCo 是一家生产世界上最受欢迎运动鞋品牌的公司,拥有一个复杂的多云 Salesforce 组织,用来运营其业务的关键部分。由于它有许多自定义需求,并且平台上有大量遗留系统,它有大量的 Apex 类来处理业务逻辑和集成。
它最近已经开始转向流程化,并且在实践中,大多数功能是代码和声明性功能的结合。随着时间的推移,ShoeCo 希望简化其 Salesforce 功能,并避免目前面临的一些问题。
特别是,ShoeCo 的许多架构师开始觉得组织已经失控,他们对在系统不同部分激活的逻辑没有清晰的概览。Salesforce 架构师之一 Pranit 提出,通过创建一个CentralDispatch Apex 类来简化当前的系统架构,这个类将负责将调用分发到其他代码或流程。
由于所有业务逻辑都通过CentralDispatch类进行,Pranit 认为,识别在哪些情况下调用了哪些代码将变得更加容易,从而实现更大的透明度、更低的维护成本和更大的代码重用潜力。
这一方法的一个关键哲学要求是,CentralDispatch类不应该包含任何逻辑。它仅仅负责将请求转发到正确的处理器。然而,这一哲学原则在实践中很快就被废除了。
为了使类按预期工作,越来越多决定在不同上下文中调用哪些内容的业务逻辑必须移到CentralDispatch类本身。这意味着实际功能的越来越多部分将存在于一个日益膨胀的类中。
虽然最初这引起了一些担忧,但 Pranit 和他的同事们接受了这一开发,因为相较于CentralDispatch类引入之前,他们仍然比以前拥有更好的可视性。直到开发人员开始抱怨该类太大,并且无法在没有各种系统部分出现未知副作用的情况下进行更改,他们才开始认真关注这个问题。
该类已经增长到超过 5000 行 Apex 代码,并且有效地协调了从 ShoeCo 组织内其他地方调用的所有逻辑。从某种程度上来说,它成了自身成功的牺牲品,但此时,大多数开发人员认为它更像是障碍而非助力。
Pranit 决定制定一个新的计划来重构CentralDispatch类,并使其恢复到原本精简的状态。他希望将所有复杂的逻辑移出,将它保留为一个调度中心,决定在特定上下文中调用哪些其他 Apex 代码或流程。
然而,在检查代码时,他发现,在许多情况下,无法在不包括大量逻辑的情况下进行请求转发。失望之下,他开始考虑是否需要从根本上改变这个方法。
问题
God 类反模式被用来将技术问题解决集中到一个应用中。从概念上讲,使用一个单一的模式在单一类中处理所有在自定义开发过程中出现的技术复杂性,比花费大量时间进行详细的架构和设计要容易得多。
你可以在下图中看到 God 类代码结构:
图 5.5 – God 类代码结构
你在 Salesforce 实现中不常看到这种反模式,但它对于为 AppExchange 构建的独立软件供应商(ISV)或任何在 Salesforce 平台上构建定制应用程序的组织来说,都是一个真正的危险。
提议的解决方案
上帝类是一个单一文件——通常在讨论 Salesforce 时是一个 Apex 类——它托管了一个复杂应用程序的所有或至少大部分关键业务逻辑。以这种方式集中功能似乎是一个不错的设计决策,因为它使得整体架构和设计相对可管理,甚至有一些模式,例如我们在前面的示例中使用的 Dispatcher 模式,在这种集中方式下也可以有效使用。
通常,随着应用程序的发展,你可能开始失去大局。这在小应用程序逐渐演变成大型应用程序时尤为明显。你可能在最初并没有强烈的架构设计,因为它最初只是一个可以快速构建的小应用程序。
在这种情况下,集中管理代码库可以成为管理应用程序并重新掌控局面的一个方法。或者,你可能只是出于方便将所有逻辑放在一个地方,并且没有注意到该类已经扩展到几千行代码。
然而,正如所有功能进化管理不善的情况一样,最终你会为此付出代价。
结果
在本书的这个阶段,你应该能够预测由不当管理的应用程序增长导致的反模式的负面后果。我们已经看到了一些这样的模式,从重量级组件到“大球泥”,上帝类也共享了我们所期待的许多负面后果:
-
代码变得难以理解,导致更长的维护周期、更慢的新开发速度以及更高的错误率
-
只有某些程序员可能能够处理上帝类,以避免不幸的副作用
-
代码库中的所有更改,无论在任何地方,都需要对上帝类进行相应的更改
-
上帝类与系统其他部分之间经常发生奇怪的交互效应,导致难以调试的错误
-
该类在应用程序中呈现出单点故障(SPOF),如果它失败了,其他任何逻辑都无法被处理
总的来说,你最终会得到一个脆弱、易碎且有些杂乱无章的应用程序。
更好的解决方案
在 Salesforce 上构建自定义解决方案时,你通常会使用 Apex,这是一种与 Java 密切相关的面向对象(OO)语言。这意味着,如果你打算在该平台上构建任何复杂的应用程序,你应该遵循良好的面向对象分析与设计(OOAD)实践。虽然本书的范围远远不包括教学 OOAD,但一个很好的入门点是学习 SOLID 原则。
SOLID 原则是一组在设计软件时可以使用的指导方针,以使软件更易理解、维护和扩展。这个首字母缩略词代表了 单一职责,开放封闭,里氏替换,接口隔离 和 依赖注入(DI)。让我们简要了解一下它们:
-
单一职责原则(SRP)是指一个类或模块应该只有一个且仅有一个原因发生变化。这个原则通常与 开放封闭 原则(OCP)一起使用。
-
开放封闭原则(OCP)指出,软件应该对扩展开放,但对修改封闭。这意味着应该通过扩展现有代码来添加新功能,而不是修改它。
-
里氏替换是 面向对象编程(OOP)中的一个原则,指出一个超类的对象应该能够被其子类的对象替代,而不需要改变程序的功能。
-
接口隔离是将单一接口分割成多个更小接口的过程。这可以出于多种原因,例如增加系统的模块化或减少接口的复杂性。
-
依赖注入(DI)是一种实现对象与其依赖关系之间松耦合的技术。它通过提供组件所需的依赖关系,而不是让组件自己创建或获取这些依赖关系来实现。这可以由程序员手动完成,也可以通过工具自动完成。
既然我们已经讨论完了“上帝类”,那么我们接下来讲解最后一个模式:错误隐藏。
错误隐藏
错误隐藏是指当你在没有采用结构化错误处理方法的情况下,隐藏技术错误信息给最终用户的行为。
示例
SailCo 是一家定制设计帆船的供应商,拥有一个复杂的配置应用程序,用于配置其销售的帆船,该应用程序构建在 Salesforce 平台之上。该应用程序以一种相对传统的方式构建,结合了 LWC 和 Apex 代码。
SailCo 的用户通常极少具备技术背景,而定制应用程序的一个关键要求是永远不向最终用户显示技术错误信息。因此,原始应用程序的开发人员设计了一种方式来捕获所有异常,并在显示给用户之前将其包装成通用错误信息。
这种以友好方式告知用户发生错误的通用信息是系统中看到的主要错误消息,因为开发人员无法或者没有足够的时间合理区分可能发生的错误。然而,用户似乎对这个解决方案感到足够满意,并且对于偶尔发生的错误的具体性质并不多加追问。
然而,过了一段时间,显然配置应用程序存在一些系统性的故障模式。多个客户投诉他们所需的配置没有成功记录在他们的订单中,而这些订单已经通过自定义应用程序在 Salesforce 中进行了注册。
没有人能准确指出错误所在,最后由相对较初级的 Salesforce 工程师 Sarah 来尝试调试这个问题。她首先回顾了她可以从生产系统中生成的日志,但发现她能看到的唯一错误是被包装机制抛出的通用错误信息,这些信息将技术细节隐藏在用户之外。在许多情况下,异常仅仅是被捕获了,却从未得到处理。
这意味着生产日志实际上对她的调试工作没有帮助。她尝试在做了一些代码更改后,在较低的环境中重现错误,以获得原始的堆栈跟踪,而不是被封装的错误信息。然而,她无法在较低环境中重现错误。
她寻求并最终获得了一个特殊的生产版本发布许可,以便向系统添加改进的日志记录功能。然而,她需要对现有代码库进行大规模重构,因为她最初使用的快速修补程序被认为不适合生产环境使用。
在几位其他 SailCo 开发人员的帮助下,经过大规模的代码重构,她成功将新的日志功能投入生产。幸运的是,问题证明只是一个微不足道的编码错误。
Sarah 修复了这个问题,并将新代码发布到生产环境,确信通过新的错误处理方法,她将能够发现问题,即使当前的修复并没有解决代码库中可能存在的所有问题。
问题
错误隐藏是出于一个很好的原因:为了不向最终用户展示那些会让他们困惑并导致他们失去对我们应用程序信任的丑陋技术错误信息。在理想的世界里,我们希望能够从所有错误中优雅地恢复,或者至少显示一条友好、易于理解的错误信息。
你可以在这里看到一个简单的错误隐藏示例:
图 5.6 – 错误隐藏的简单示例
实际上,我们通常只有时间在分析和设计阶段分析最常见的故障模式,留下了大量我们没有准备的潜在故障。采用错误隐藏反模式后,我们最终不仅把这些错误隐藏起来,不让最终用户看到,甚至连我们自己也看不见。
提议的解决方案
错误隐藏反模式通过简单地隐藏错误或将任何错误替换为通用的无害错误信息来解决不向最终用户显示技术错误信息的问题。技术上,这种做法是通过捕获异常并简单地丢弃该异常包含的信息来完成的,无论是否向最终用户显示消息。
这意味着我们没有日志记录或系统性捕获错误信息的方法。因此,我们无法知道应用程序中是否存在任何系统性问题,这些问题可能是我们之前没有考虑到的,也无法调试在生产环境中发生的、在低环境中无法立即重现的问题。
这种反模式节省了开发人员的时间,因为他们在开发过程中无需采用结构化的错误处理方法,同时它也满足了用户不想看到混淆信息的需求。然而,它带来了许多负面副作用。
结果
错误隐藏最明显的结果是你无法找到错误。错误被系统地隐藏,你只能依赖用户报告以及你重现问题的能力来解决任何问题。
在没有良好日志信息的情况下调试 Salesforce 中的错误可能非常困难,尤其是当错误可能与用户上下文、数据量或类似的难以控制的变量有关时。
这意味着你的维护成本将大幅增加,解决漏洞的周期也会变长。随着用户发现可能存在被掩盖的问题,他们也可能开始对系统失去信心,这会导致一个恶性循环,用户开始把所有问题归咎于隐藏的系统问题。
最终,你需要重构应用程序并引入系统化的日志记录和错误处理方法。通常,这比第一次就正确做事要昂贵得多。
更好的解决方案
错误隐藏的解决方案是采取结构化的错误处理方法,从项目的分析阶段开始。你应该分析常见的故障模式,并积极地为它们做好准备,而不仅仅是关注“顺利路径”。
你还应该制定一个错误处理标准,其中包括如何处理异常、如何记录错误以及如何在不同的上下文中向最终用户展示错误信息。你还应该采用一个好的日志框架。我倾向于推荐 Nebula(github.com/jongpie/NebulaLogger
)作为框架,但社区中也有许多不错的选择。
在寻找日志框架时,请记住以下几点:一个好的日志框架应该易于使用和配置,能够从多个来源(例如,Apex、流程、集成等)进行日志记录,而不会影响应用性能。此外,实施分层日志系统,捕获不同级别的详细信息(例如,INFO、WARN 和 ERROR),以平衡用户友好的消息和详细的诊断信息。理想情况下,你还希望能够轻松地可视化错误并跨越流程边界追踪它们。
在这一切中,当然,你希望将终端用户与技术错误消息隔离开。但你希望做到这一点时不依赖反模式。
现在我们已经讨论完了最后一个反模式,我们可以开始总结我们的关键要点。
了解关键要点
在本节中,我们将从具体模式中抽象一些,尝试提炼出你可以在日常工作中作为 Salesforce 架构师使用的更广泛的学习要点,或者在准备 CTA 审查委员会时使用的要点。
在架构 Salesforce 解决方案时,你应该注意以下事项:
-
不要急于基于组织的常规做法来寻找解决方案。仔细考虑你的选项。
-
在做购买与自建决策时,务必仔细计算定制解决方案的实际总拥有成本(TCO),包括长期运行和维护成本。
-
如果可以避免,不要为特定许可证集设计解决方案。
-
相反,争取更好的商业交易、更广的范围或不同的许可证组合。
-
你必须对用户群体做出假设,但要小心系统性偏见。
-
为了帮助减轻偏见,开发过程中应使用各种咨询方法以降低风险。
-
不要对新技术过于投入。无论它看起来多么酷,它都不是万灵药。
-
自动化是许多 Salesforce 解决方案中的一个特别痛点。它应该是技术治理的重点之一。
-
优先选择简化的自动化设置,而不是更复杂的设置。
-
如果需要复杂的自定义 UX,请以有意义的方式拆解功能,而不是将所有内容放在一个单一组件中。
-
在 Salesforce 上进行大量开发时,你应该应用所有适用于类似语言中其他面向对象开发项目的好实践。这包括如何构建你的类以及如何处理异常和错误。
-
定期回顾和重构你的解决方案架构,以确保其始终与不断变化的业务需求和 Salesforce 平台功能保持一致。
在准备 CTA 审查委员会时,你应该注意以下事项:
-
在你的解决方案中使用 AppExchange 产品是完全合适的,通常比定制解决方案更可取。
-
推荐你了解并能够证明其价值的产品,或者是市场上广为人知的产品,以避免不必要的问题。
-
假设预算不是限制因素,并推荐适合工作的正确许可证
-
然而,不要过度推荐大量额外的功能许可,如果不需要的话
-
自由地做出假设,但在过程中要表明假设的前提
-
要做好准备,假如评委让你考虑如果你临时改变了一个关键假设会发生什么
-
推荐适合的工具来完成任务,避免依赖过于片面的解决方案方法
-
不要过度依赖自动化,始终清晰地说明你推荐的方法以及推荐的理由
-
优先选择简单的自动化设置而不是复杂的自动化设置
-
推荐定制组件通常是合适的,但要小心不要过度开发其功能
-
请记住,在推荐基于代码的解决方案时,你还应该了解面向对象开发的良好实践,尽管这在问答环节时可能更为相关
-
有一个结构化的错误处理方法,这样如果评委提问时你可以清楚地说明
-
准备好讨论在长期的 Salesforce 实施中管理技术债务的策略,包括重构方法以及何时考虑重新架构
这样,我们已经覆盖了本章的内容,准备继续进行。但首先,让我们总结一下我们学到的知识。
总结
本章中,我们讨论了八个反模式,比迄今为止的任何一章都要多。这并非偶然。解决方案架构可能是大多数架构师最耗时的工作。即使我们不是直接负责解决方案的所有部分,我们也经常参与咨询特性。
解决方案架构是我们工作中最显眼的部分。虽然集成架构、数据架构和安全架构为我们创建解决方案设定了基础,但最终,用户判断的基础是我们为他们设计的解决方案。
如果我们正确地构建了核心架构,但未能交付一个好的解决方案,在大多数观察者眼中,我们就失败了。不幸的是,这也是一个非常难以做到的领域。
如同这些反模式所展示的,保持灵活性与规范之间的平衡,既能满足用户需求又能遵循良好的技术实践,这需要经验和良好的判断力。希望你现在能更深刻地理解这一点。
讲解了解决方案架构后,让我们继续讨论下一个领域:集成架构。
第六章:保持集成清晰
本章探讨了与其他系统集成相关的反模式,这是现代 Salesforce 实施中的一个关键方面。本章的第一部分讨论了集成架构和集成模式中的反模式,第二部分探讨了接口设计和使用中的潜在陷阱,第三部分集中讨论了集成风格的问题。像往常一样,我们通过总结关键要点来结束本章。
在本章中,我们将涵盖以下主要主题:
-
如何避免滥用技术,避免让系统架构过于复杂
-
何时适合,何时不适合为集成创建自定义服务
-
如何避免在设计接口时的常见失败
-
如何良好地使用基于事件的集成
-
如何正确地使用集成模式
-
AI 如何影响集成模式
完成本章后,你将对如何更好地选择集成模式和结构化集成架构有一个清晰的理解,通过学习各种可能出错的方式来避免这些问题。随着 Salesforce 的不断发展,理解这些集成反模式对于从事该平台工作的架构师和开发人员来说变得越来越重要。
搞乱集成架构
本节介绍了两种反模式,它们以不同的方式可能会在你的集成架构中造成混乱。我们将首先讨论如何避免错误地使用中间件。
名义上的中间件(MINO)
使用中间件来创建点对点连接,而不是利用其扩展功能
示例
PumpCo 是一家大型 B2B 公司,专注于为工业生产制造泵。它在 30 多个市场运营,历史上在 IT 系统上的投入较少,并且在销售上主要使用手工流程,这些流程在不同国家和产品线之间存在显著差异。
在过去的一年里,他们开始实施 Salesforce Sales Cloud 和 CPQ,以推动全球销售流程的标准化。他们过去在 IT 平台上的一项重大投资是 SAP,基本上,SAP 目前管理着公司所有关键业务。
Michelle 在 Salesforce 实施的早期阶段作为集成架构师加入。集成路线图非常雄心勃勃,因为业务希望看到所有相关数据和流程能够在 Salesforce/SAP 边界上无缝运作。从根本上讲,他们希望能够在 Salesforce 中直接访问所有相关的后台数据和流程,而不需要切换上下文。
一旦完成初步的映射,就有 75 个离散的集成点,涵盖从定价和物流到人力资源等各个方面,需要实现这些集成点,才能提供业务所期望的完整体验。然而,好消息是,许多集成点可以分为相似的领域,例如客户或订单接口。
来自 Salesforce 和 SAP 方面的架构师讨论了多种替代架构和实现方法,目的是创建少量稳定的接口,以满足大多数用例的需求,但不幸的是,进展缓慢,利益相关者和架构师之间没有真正达成一致。有许多潜在的解决方案和几种可能完成任务的技术,而各方愿意妥协的意愿较低。
双方最终同意让中间件团队来管理这个过程。PumpCo 刚刚购买了一个新的中间件平台,团队正在寻找机会开始工作。
中间件团队将向 Salesforce 暴露服务,并将调用转换为 SAP。任何 API 的修改也将是它的责任。因此,两个平台团队无需就方法达成一致,可以独立工作。
随着项目的推进,米歇尔统计了 Salesforce 调用中间件的接口数量。她数了 45 个。虽然比最初的 75 个少,但随着项目的推进,范围也有所缩小。
这是 PumpCo 集成架构的示意图:
图 6.1 – PumpCo 集成架构
从她所看到的,许多这些中间件接口几乎只是简单地将 Salesforce 的调用转发给 SAP,然后再返回。她在想,这真的是最好的方法吗?但这已不再是她的问题。
然而,随着时间的推移,随着 Salesforce 的使用量增加,集成开始出现问题。错误率较高,性能问题,维护变得越来越复杂。总体而言,集成导致了平台上的大多数技术问题。
一名顾问被请来评估情况,并建议对集成架构进行合理化,因为当前的设置实际上包含了通过中间件连接的 45 个日益定制的点对点连接。这种设置带来了很大的失败潜力,且通常很难理解。
米歇尔被要求参与重新设计过程,在几周的设计工作后,他们最终得出了一个与初期项目实施过程中所做的某个迭代方案相差无几的提案。当一位高级利益相关者直接询问为什么一开始不做这个时,没有人能够给出令人信服的回答。
问题
MINO 反模式试图通过引入中间件来减少创建良好集成架构的复杂性。然而,它的做法未能充分利用中间件平台的能力,而是通过中间件重新创建了本应出现在点对点场景中的流。
这种情况通常出现在具有复杂系统景观、系统间有许多接口和接触点的组织中。然而,在这些组织中,通常缺乏协调不同部门之间的技术治理,从而导致集成架构的混乱。
MINO 反模式的另一个常见特征是关键平台上存在过时且不灵活的系统 API,并且很难达成一致的标准表示法来表示这些关键平台上的核心业务实体,这使得无法就通用接口或 API 达成一致。
提出的解决方案
MINO 提出的解决方案仅仅是引入一个中间件平台,而没有过多关注如何使用它。通过引入现代中间件平台,至少可以部分掩盖遗留系统的复杂性和不灵活性,从而取得良好的初步结果。
也就是说,MINO 表面上看似正确,但如果中间件的实现只是以新的形式复制现有的混乱,那么收获相对较小。并不是完全没有收获;你仍然可能获得一些基本的中间件能力,如更好的错误日志记录、重试机制或更易于使用的协议转换。
另一个,往往更具影响力的原因是,这种反模式使得核心平台的团队不必直接处理彼此之间的关系。如果你在 CRM 方面工作,你的视角通常会与在 ERP 方面工作的视角非常不同,尤其是在关键集成的情况下。
MINO 允许不同的团队只需与共同的中间件团队打交道,后者则负责管理其余部分。不幸的是,这通常会导致架构只停留在基础层面。
结果
MINO 的结果往往是将你的系统景观变成比之前更加混乱的“意大利面条”式的架构。毕竟,现在中间件处于核心位置,因此你可以减少对集成细节的关注。
这种忽视通常会带来以下后果:
-
难以理解的集成架构,存在过多的单独接口和点对点连接,尽管这些连接通过中间件进行调解
-
维护成本增加,因为复杂度仍然很高,而且现在涉及更多的团队
-
缺乏技术治理,以及潜在的对这种治理必要性缺乏认知
-
集成中的错误率增加,以及由于团队试图跨平台追踪错误而导致的修复时间相应增加
-
性能下降,因为存在更复杂的流程,跨越多个平台
总体而言,如果你只是让中间件充当点对点连接的代理,可能完全不使用中间件更好。
更好的解决方案
MINO 反模式教给我们的是,没有捷径可以走来正确建立集成架构。你必须仔细考虑系统之间的连接和依赖关系,当前及未来的业务需求,主数据的分布情况,关键平台所具备的核心功能,以及如何构建接口和模式,以最佳方式支持这些元素。
以下图展示了一些常见的中间件功能:
图 6.2 – 常见的中间件功能
考虑到这一点,你可以选择适合的工具来完成任务,这很可能是一个中间件工具。然而,在你尚未思考清楚将支持哪些跨业务的接口、为不同场景支持哪些集成模式、并确定如何在不同团队之间进行技术治理之前,不能急于选择任何工具,不论它看起来多么酷。接下来我们将讨论下一个反模式——服务膨胀综合症。
服务膨胀综合症
服务膨胀综合症是一种反模式,指的是在没有充分的理由或考虑替代方案的情况下,创建过多的自定义服务。
示例
OmniCo 始终将自己定位为技术领导者,并在多个多元化的服务领域中部署了许多前沿的软件平台。该公司是面向服务架构(SOA)的早期采纳者,并结合事件驱动架构(EDA)在高速数据和流程中取得了巨大优势。
OmniCo 现在正在实施 Salesforce,作为其旧 Siebel CRM 系统的替代品,后者曾作为许多其他系统的集成中心。Siebel CRM 系统被高度定制以适应 OmniCo 的流程,公司期望新的 Salesforce 系统也能如此。虽然实施伙伴提出了保持标准功能的合理论点,但这与 OmniCo 历史上的做法相悖,且他们并不打算在 CRM 项目中改变这种做法。
下面是旧的 Siebel 设置:
图 6.3 – OmniCo 的旧 Siebel 设置
对于负责实施项目集成部分的咨询经理 Erhat 来说,这引发了很多焦虑。他正受到来自 OmniCo 的多位高级利益相关者的压力,要求构建一系列能够融入 OmniCo SOA 的特殊业务服务。
Erhat 曾尝试在纯净的 Salesforce 平台上构建定制的 API,虽然最终成功,但过程既不简单也不快。事实上,考虑到提到的定制服务数量,他对于在时间、预算和具备必要技能的人员限制下的基本可行性存有疑虑。
经过一些反对意见后,他同利益相关者达成一致意见,使用类似于旧 Siebel 系统中用于订单管理的接口来交付两项关键服务,这需要大量时间来在不同模式上重新设计。
这些服务已经交付,但在测试过程中证明非常困难,部分原因是服务的测试协议不完整,部分原因是复杂性异常高。
当头两项服务接近完成时,OmniCo 的企业架构委员会召开了一次危机会议。他们刚刚意识到在新的 Salesforce 设置中,并不是所有由 Siebel 提供的业务服务都将可用。在董事会的几位成员看来,这将从根本上破坏一系列业务流程,因为其他系统需要大幅改变它们的集成方法,或者转向某些步骤的手动处理。
Erhat 对 OmniCo 的流程不太了解,因此无法就案件的优点进行辩论。董事会成员向他提供了另外 13 项服务的定义,涵盖了从潜在客户到现金流程的不同部分,并且这些服务在之前的 Siebel 设置中是可用的。以下是集成的示意图:
图 6.4 – OmniCo Salesforce 集成的示意图,不包括 ESB
Erhat 实际上只能在实际层面上进行反对,他这样做了,认为这些服务超出了范围,不包括在定价内,并且他没有团队来提供解决方案。OmniCo 有些不满,并且进行了一些升级会议。然而,最终告诉 Erhat 不要担心——他们会以其他方式解决这个问题。
结果是引入了一个由各种承包商组成的团队,他们将快速构建这些服务,与主要的咨询合作伙伴的团队并肩作战。Erhat 只能等待和观察,看承包商们遇到不可避免的技术复杂性。他在项目上线前离开,留下一些不愉快的味道。
十二个月后,他再次回到了 OmniCo。他被引入作为该公司 Salesforce API 的专家,这些 API 显得非常容易出错且维护成本高昂。
OmniCo 正在寻找建立此类系统的原因以及如何修复它的理由。他们还在考虑不同的方法,比如改变集成模式或引入一些中间件。Erhat 深吸一口气,开始规划分析工作。
问题
服务扩展综合症所构成的问题是如何将 Salesforce 融入现有的企业架构中,同时又要满足这些架构中已经存在的对关键系统能力的期望。这可能是一个 SOA,正如我们例子中所示,或者是一个不同的组织原则,但通常来说,要求关键平台提供非常具体的功能。
这种反模式在各种平台中都很常见,因为它可能影响任何新的集成平台。在过去,这种情况更为常见,因为组织们忙于构建 SOA,而往往没有深入考虑具体服务的组织结构。
这种反模式通常源于对微服务架构的误解,或者是希望通过定制服务解决每个集成挑战的愿望。
今天,这种情况最常见于老旧系统被替换时,所需的接口与内建系统 API 的标准功能不完全匹配。虽然 Salesforce 提供了广泛的 API,但它们非常依赖于数据模型,而许多集成架构是基于不同的原则构建的,例如粗粒度的业务服务,而这些原则与 Salesforce 的数据模型完全不对齐。
提出的解决方案
服务扩展综合症处理的是在集成过程中如何应对这个问题,倡导为每个集成需求不必要地创建新的定制服务。这种方法忽视了利用现有服务或标准 API 的潜力,而这些现有服务或 API 足以满足这些需求,且不会增加不必要的复杂性。
这是另一个反模式,尽管它看起来似乎合乎逻辑,因为毕竟,你是在直接交付业务价值,并且有时符合跨公司技术治理论坛的预期。因此,你可能会在很大压力下走这条路,明知这样做会在长期内对平台造成损害。
因为平台上具备相关能力,而企业环境中又有这种需求,反抗这种反模式有时几乎是不可能的。这一点尤其正确,因为这些成本通常是随着时间的推移才逐渐累积的。
结果
你最先会遇到的服务扩展综合症问题是复杂性和构建成本的增加。尽管在 Salesforce 上创建定制服务是可行的,有时也是正确的选择,但它们很难做到完美。Salesforce 本身并不是一个 API 平台,这也是它几年前收购 MuleSoft 的重要原因之一。
随着时间的推移,复杂性增加将导致维护成本上升,而且不仅仅是 Salesforce 的成本。使用这些扩展服务的各个团队也可能面临重新工作和升级其连接的持续成本。
在 DevOps 环境下,服务过度繁杂会给 CI/CD 管道带来显著挑战,增加的复杂性使得自动化和编排变得更加困难。这种复杂性可能导致更频繁的部署失败,因为众多服务之间的相互作用是不可预测的。此外,潜在问题的增多会延长恢复时间,因为团队必须遍历更多组件以诊断和解决故障。因此,组织可能会发现更难实现 DevOps 旨在提供的速度和可靠性,最终影响软件交付的整体效率。
有时,自定义服务是正确的选择,且其好处可以超越初始构建和维护的成本。但对于我们示例中的 15 个自定义服务来说,这种情况几乎是不存在的。如果你认为你需要这些服务,那么你可能需要重新考虑你的方法。
更好的解决方案
第一个建议是,首先查看标准的集成模式,看看你是否能找到合适的标准技术。也许你可以使用标准的 API,也许你可以使用批处理过程,也许你可以发布事件并让其他系统订阅它们。
你应该广泛地考虑,而不是立刻跳到自定义接口,尽管这看起来是一个好的初步选择。危险在于,你可能会选择看起来光鲜的解决方案,却没有意识到这个决策在长期内的实际成本。
如果你确实决定需要大量的自定义 API —— 在某些情况下这可以被证明是合理的 —— 你应该选择一个专为此目的构建的平台来实施。对于 Salesforce,MuleSoft 是经典的选择,但市场上也有其他可以填补这个空缺的解决方案。
为了增强我们的服务产品,我们可以采取逐步推进的方法:
-
识别核心业务能力。
-
映射现有的服务和 API。
-
识别我们服务中的空白。
-
在选择自定义服务之前,考虑标准化解决方案。
此外,我们还可以考虑实施一个强大的 API 管理策略,以促进服务的重用并避免不必要的服务创建。
在 DevOps 环境下,服务过度繁杂可能导致 CI/CD 管道中的复杂性增加,发布管理变得更加困难。因此,采用更为规范的服务创建方法至关重要,因为这与 DevOps 的简化和自动化原则更为契合。这确保了流程的流畅性并提升了整体运营效率。
总体而言,如果盲目地构建服务,你会冒着使你的 Salesforce 界面和集成环境过于复杂的风险。像往常一样,考虑实际的利弊权衡,并基于真实的优缺点做出决策。接下来,我们将进入下一部分,讨论与接口设计相关的反模式。
不当的接口设计
在本节中,我们将探讨影响集成设计的两个常见反模式。在具体层面上,第一个是繁重接口,着眼于接口设计中的问题,而第二个是频繁通信集成,着眼于接口使用中的问题。
繁重接口
当一个接口开始处理太多任务时,你会遇到一系列问题。
示例
Joe 是一个集成架构师,供职于一家专门从事复杂实现的小型 Salesforce 合作伙伴公司,通常需要大量代码或其他类型的定制。他刚刚开始与 RealCo 签订的新合同,RealCo 是一家主要的房地产投资公司,Salesforce 是其整个业务中主要的互动系统。
他最初承包的工作包括为访问估值信息构建一个定制接口,供 RealCo 的合作伙伴在进行交易时使用。信息存储在 RealCo 的 Salesforce 组织中,需要实时可用。
Joe 在 RealCo 的中间件平台上设置了组成接口的 API,并协调对几个不同的 Salesforce 标准 API 和一个自定义 API 的调用,作为实现的一部分。然而,接近新接口上线时,一大堆新的用例掉到了他的桌子上。
这些不仅包括对估值 API 的扩展,例如获取历史估值和趋势数据,还包括完全不同类别的物业数据,包括通过平台事件进行的实时更新、使用变更数据捕获(CDC)的数据流变化、建筑结构信息、从各种评估中获取的关键指标访问,以及从 RealCo 合作伙伴进行看房时收集的反馈洞察。
Joe 稍微反驳了一下客户,说如果他早知道会有这么多新的功能进来,他可能会以不同的方式构建 API,可能会做一些在当前上线中不是最优的处理来包含这些功能。
RealCo 的经理专心地听 Joe 讲话,但最终表示,决定是继续增加额外的功能。RealCo 意识到潜在的弊端,但它可以接受这些问题。
在上线前一天,同样的事情再次发生。这一次,信息不仅包括更多与物业相关的信息,还包括完全不同类别的信息,如与物业所在区域相关的人口统计和细分数据,如下图所示:
图 6.5 – RealCo PropertyService 视图
没有办法在一天内完成这项工作,RealCo 虽然不情愿,但还是接受了这个事实。然而,它希望 Joe 提供一个计划,尽快将其包含进去。鉴于巨大的压力,Joe 只是扩展了当前的接口,而这个接口现在变得庞大,涉及到几十个 Salesforce 服务,包括标准和自定义服务。
幸运的是,初始上线和随后的更新都相对顺利。RealCo 合作伙伴组织的团队对接口的复杂性抱怨了一些,并报告了若干 bug。但它仍然能够正常工作,合作伙伴们可以继续处理接口所需驱动的各种应用程序。
变更请求的轰炸仍在继续。而且这些变更总是特别紧急,且对于某个合作伙伴的关键用例来说是必须的。更糟糕的是,越来越多的团队依赖于这个接口,这使得升级变得越来越困难。
即使有良好的 API 版本管理,版本之间的变化仍然让合作伙伴团队感到相当吃力,他们大声抱怨频繁的版本变化和 API 实现中逐渐出现的高错误率。
最后的压垮骆驼的稻草出现在新版本发布前发现了一个关键性 bug。Joe 被告知需要优先发布新功能,于是他将一个热修复与新版本一起发布,这实际上强制所有主要合作伙伴进行升级。
然而,事实证明新 API 版本中存在其他破坏性的 bug,这意味着关键合作伙伴失去了访问关键功能的权限,直到 Joe 能够控制住局面,至少一周的时间。
召开了一次升级会议,合作伙伴们可以在会上提出他们的各种投诉。Joe 尽力解释当前情况的历史背景和原因,但不幸的是,复杂的细节在嘈杂的讨论中被淹没了。
Joe 被告知他的合同不会续签,另外一个顾问将被引入来重构和重组接口。他松了一口气,开始期待下一个工作机会。
问题
“胖接口”所带来的问题本质上是接口结构的问题——也就是说,如何安排功能,使得那些需要接口提供服务的客户端可以调用它。
注意
最初,这种反模式更多地应用于 面向对象编程(OOP)中的接口。然而,它在集成环境中同样适用。
在接口设计上有几种不同的哲学观点。如今,大多数人本能地偏向于微服务,它们是执行一组单一、明确且连贯功能的小型服务。举个例子,一个通知服务,它的唯一作用就是发送通知。
然而,几年前,人们更倾向于使用粗粒度的业务服务,这些服务为业务流程提供了一个入口点——例如,处理订单。这就是与 SOA(面向服务的架构)相关的基础风格,我们之前曾提到过。
然而,使用臃肿接口时,你违反了大多数(如果不是所有)这些哲学中普遍适用的一个基本原则。这个原则叫做接口隔离,要求客户端永远不应被迫依赖它不需要的方法。
提议的解决方案
臃肿接口提议简单地将逻辑继续添加到现有接口中,因为这是最简单的做法。设计良好的隔离接口可能需要更多的工作和仔细思考,而将所有功能放在一个接口中则简化了问题。
此外,你有时可能会说服自己,所有功能确实应该放在一起,因为它们之间有一些间接的共同点,尤其是当你有大量消费者使用你所暴露的功能时,这种情况可能尤其成立。
这种反模式通常只是随着时间推移产生的结果。代码最初做一件事,然后做另一件事,接着做第三件事,最终它什么都做,甚至连狗都带走了。
如果不是因为有许多隐性成本需要考虑,这一切看起来应该是好的。我们接下来将探讨这些问题。
结果
如果你一直在阅读本书,你一定会熟悉臃肿接口反模式的结果。这类似于在多个领域中可能发生的糟糕结构后果。
当你的接口变得臃肿到不可管理的地步——也就是说,它现在包含了太多不同的功能,实际上已经变得无法管理——你可能会看到以下一些或全部后果:
-
复杂性增加,导致变更成本、周期时间和错误率的提高
-
维护成本增加,因为错误会带来额外的后果,客户端依赖接口的各种现有部分,且代码库庞大且难以理解
-
只有某些开发人员能够对臃肿接口进行更改,因为更改接口的互依性和对接口用户的影响需要对整个代码库有深入的了解。
-
接口中的 bug 可能会影响那些根本不使用失败方法中暴露功能的客户端
-
大量客户端依赖接口,使得解开现状变得困难
总的来说,尽管这种模式乍一看可能只是一个轻微的代码异味,但如果你在中心位置有一个失败的臃肿接口,它实际上可能会为你的公司范围的集成架构带来严重问题。
更好的解决方案
这种反模式是少数几个可以通过应用良好实践和开发过程中的自律来避免的。如果你严格遵循接口标准,并在添加新功能时始终应用接口隔离原则,这种反模式将永远不会发生。
尽管可能会有诱惑去走捷径,而这些捷径短期内可能不会带来严重后果,但你应该了解长期后果,并应用良好的设计和编程实践。这也是一个架构师或开发人员可能会有很多发言权的领域,因为这是一个技术性太强的领域,大多数业务用户难以真正发表意见。
难点在于,在面临巨大的交付压力时,如何保持所需的纪律性。当然,希望通过在描述中提到的要点,能帮助你抵制“速成思维”的诱惑。
聊天集成
聊天集成是一种反模式,其中集成了任意模式,导致对一个或多个接口发出过多的调用,常常导致性能下降。
示例
WoodCo 是一家有着悠久历史的家具制造商,专门为富裕客户定制高端家具。近年来,由于推出了基于 Salesforce Experience Cloud 并结合 B2B 电商的电商平台,WoodCo 的业务增长迅速,该平台将客户社区与指定负责其项目的家具制造商直接连接起来。
这样,客户和制造商可以直接连接并讨论定制建造的要求。客户还可以在家具的整个生命周期中跟踪其进度。
WoodCo 负责管理项目建设,包括预算,并确保尽可能通过友好协商解决任何冲突。他们在一个旧的项目控制模块中跟踪这些项目,该模块也用于管理他们自己的业务。
这个项目模块最近通过一个定制构建的 REST API 进行了扩展,该 API 建立在传统应用程序之上。供应商专门为 WoodCo 构建了这个 API,花费巨大,但这被认为是毫不犹豫的选择,因为它将直接实现门户与项目控制模块的集成,取代了当前由数据输入人员手动将所有数据重新输入项目控制模块的过程。
Lina 被 WoodCo 聘用,负责数字化项目,其中第一个项目是将电商平台与项目控制模块连接起来。她委托了一家专业的 Salesforce 合作伙伴来主导这一工作。
他们建立了一个轻量级的中间件平台,订阅 Salesforce 的事件并将其转换为新 REST API 格式的 REST 调用。由于 REST API 不支持任何聚合,所以它严格遵循一对一事件调用。
在 Salesforce 方面,事件最初仅在状态更新时触发,或者在输入或更改诸如项目标题之类的重要信息时触发。然而,随着时间的推移,应该扩展到跟踪项目中的活动状态以及制造商与客户之间的沟通。
你可以在这里查看 WoodCo 集成架构的概览:
图 6.6 – WoodCo 集成架构
集成成功上线,WoodCo 的每个人都为此欢呼。然而,尚未实现完全的好处,因为活动和客户沟通仍然仅存在于客户门户中,而 WoodCo 员工仍然通过重新输入数据并在多个系统间切换来绕过这个限制。
最终,更新的日子到来了,这次更新将包括完整的同步,大家兴奋地等待着上线。然而,在启动后的几分钟内,项目模块崩溃了。
供应商进行调查并将错误归因于与初始同步相关的可扩展性问题。上线被推迟到周末,并经过多次重启后,初始数据确实得以同步。
星期一到来,大家开始愤怒地使用系统。项目控制模块的慢速问题引发了一些抱怨,但至少集成似乎在工作,并成功传递了关键数据。
然后,在周二早上,一名管理员正在客户门户上运行一些常规批处理作业。几乎立刻,项目控制模块再次崩溃,新的集成被下线以便恢复。
WoodCo 的首席信息官(CIO)召集了一个危机会议。这一问题已经引起了 CEO 的关注,需要采取措施解决。Lina 委托她最有技术才能的下属 Aki 找出根本原因。
此时,两个供应商互相指责失败,并且都不肯采取单方面行动解决问题。因此,Aki 直接深入到技术设置的中间。
他检查了 Salesforce、中间件和项目控制模块的日志文件和代码,几个小时后,他确认找到了根本原因。问题出在一个递归更新规则上,该规则将某些更新(例如更改计费代码)应用于父项目的所有活动。
在新更新之前,这并不重要,因为活动层级的变动并没有进行同步。然而,更新后,每一次这样的变化都会触发 Salesforce 上成百上千个更新事件,每个事件都会触发对项目控制模块的调用。
你可以在这里看到 WoodCo 项目的整体结构:
图 6.7 – WoodCo 项目结构
这个遗留系统可能同时处理一到两个这样的更新,同时仍能正常服务用户,但任何超过这个数量的更新都会引发问题——首先是性能下降,最终导致崩溃。当管理员启动批处理作业以重新分配一些项目标识符(PIDs)时,这触发了数十个项目及其活动树的更新,在此过程中导致项目控制模块崩溃。
在晚上的会议上,气氛沉重。然而,随着 Aki 解释事情的事实,没人能真正反驳。决定是暂时禁用活动级别,并让 Aki 领导一个团队重新设计集成,以避免过载项目控制模块。
问题
聊天式集成反模式是解决其他集成问题的副产品,出于某些原因,这些问题需要系统之间非常频繁的通信。通常,像我们示例中的问题涉及在两个或更多系统之间转移状态。
它是一个在开发过程中很难发现的反模式,因为它通常只在规模扩大时才会变得成问题。毕竟,在大多数测试场景中,除非是明确的性能测试,否则我们更新的数据不足以真正达到一个有问题的集成调用数量。
问题的实施可能是由于不良的实践,例如在循环中为每个记录单独发出调用,或者可能更为隐蔽,如我们示例中的情况,订阅事件被 1:1 映射到中间件中的 REST 调用。不管是哪种情况,至少是浪费,最坏的情况下是灾难性的。
提出的解决方案
如前所述,聊天式集成往往是解决另一个问题的副产品;因此,它并不完全符合我们的模型。然而,就算我们可以说它提出了一个解决方案,那就是跨系统边界进行尽可能多的调用,以支持业务用例,而不考虑系统的限制。
这通常是出于简化的原因。一旦你开始引入批量处理、排队、系统延迟、调用聚合、限流或你可能考虑的任何其他机制来限制调用其他接口的速率,你也会在实现中引入复杂性。
你可能已经注意到,其他反模式表明,复杂性往往是导致严重负面后果的驱动因素,因此避免它通常看起来是件好事。然而,这是一个让解决方案尽可能简单,但不要 更简单的例子。
在聊天式集成中,你实际上让解决方案变得过于简单,因为它在没有额外复杂性的情况下不能满足基本的功能需求。这可能意味着你需要更多的时间和额外的工具来使解决方案正常工作,但在这种情况下,真的没有捷径可走。
即使使用低代码集成工具,这一点依然成立,这些工具的销售目的是让你的生活变得更简单。如果集成策略错误,集成就无法按预期工作。毕竟,架构就是在权衡中做出选择。
结果
聊天式集成的结果形成了一个谱系:
-
通常,如果目标系统能够应对大量的调用,并且你也保持在 Salesforce 的限制内,那么不会立即出现后果。
-
有时你会看到性能下降。这可能是因为在 Salesforce 端,如果你在一定时间内发起了太多异步调用,而在目标端,如果你开始超载它的容量,也可能发生类似问题。
-
性能下降可能会转化为周期性错误,特别是当你开始遇到超时问题或目标服务器临时过载时。
-
最终,你有时可能会使目标系统彻底崩溃,导致严重错误。
你可以参考以下图示以获得可视化演示:
图 6.8 – 聊天型集成谱系
这并不意味着如果你恰好处于谱系的左侧,就不会存在反模式。它只是意味着目前,你尚未遇到问题。
更好的解决方案
避免聊天型集成反模式的一般建议是理解并在设计时考虑系统的限制。我们并不是在为理论系统创建理论架构。如果我们这样做,我们就会处于学术领域。
当你作为架构师设计集成时,通常是针对一个明确定义的目标环境进行设计。这意味着你应当考虑以下几点:
-
了解硬性限制,例如系统限制——例如,某一时间段内支持的最大调用次数。
-
获取目标系统在当前负荷下的实际性能信息
-
不要在没有考虑性能影响的情况下随意发起调用。
为了缓解这种反模式,组织可以利用 Salesforce 的批量 API 来高效处理大量记录,并使用复合 API 在一个请求中发起多个相关调用。这种方法可以最小化独立事务的数量,提升整体性能,同时确保数据完整性并减少潜在错误。
相反,可以使用以下一种或多种策略来确保目标系统能够应对:
-
批量化:将多个逻辑调用合并到同一消息中。
-
合并:将多个更新合并为一个调用。
-
聚合:将多个区域的变化合并为一个调用,涵盖多个领域。
-
延迟:在性能波动时引入延迟,推迟发送调用。
-
减少频率:减少更新的发送频率。
-
缓冲:将调用添加到一个队列中,随着目标系统的容量逐渐排空该队列。
-
事件:考虑使用 Salesforce 的流式 API,以减少调用次数并实现更加事件驱动的架构。通过利用流式 API,你可以实时监听 Salesforce 记录的变化,使你的应用能够迅速响应数据变化,而无需频繁轮询。这种方法提高了数据处理的效率和响应性,使其成为现代应用的重要集成方案。
总体来说,如果不小心,一个冗长的集成可能会让你的集成环境陷入困境。因此,即使你认为短期内不会遇到问题,也应避免使用这种集成模式。
错误的模式选择
本节中,我们将探讨过于执着于单一集成风格如何通过集成模式偏执症反模式造成严重问题。
集成模式偏执症
集成模式偏执症发生在仅使用单一集成模式,而忽略所有其他模式的情况下,不管该模式是否适合正在考虑的需求。
示例
WineCo 已经使用 Salesforce 技术超过十年,拥有多个核心云服务组织:营销云和商务云。
他们已经开发出了一种基于 Salesforce 的定制方法,包括一系列框架和库,这些框架和库在项目中一致使用。尽管其中许多需要更新,但出于一致性的考虑,它们仍然是首选。
Clare 被一家领先的咨询公司引入,负责领导 WineCo 为其分销商开发的一个新应用程序的构建。该应用程序将包括 WineCo 管理人员与分销商之间的沟通、标准商品的电子商务、返利管理、定制定价逻辑、联合机会管理以及为特殊需求请求报价的功能。
为了提供所需的功能并实现分销商门户所带来的商业价值,Clare 需要确保与多个系统的集成已经到位。
她必须将所有通信都通过中央通知服务进行处理,以确保所有通信都得到了适当的记录并且有正确的页脚。然后,她还需要与现有的返利管理系统进行集成,该系统根据分销商的细分和历史订单计算应支付给分销商的返利。
定价将来自 Salesforce CPQ,但在不同的组织中,因此需要进行 Salesforce 到 Salesforce 的集成。门户网页的内容将来自公司 CMS。然而,也有一些用户和行为跟踪服务需要从 CMS 集成到门户网站中。
最后,ERP 系统需要更新通过分销商门户生成的任何定制报价和标准订单。分销商门户还需要从 ERP 系统获取大量关于分销商的数据,包括他们的现有订单以及关于他们的基础数据。总的来说,虽然在 Salesforce 上的基础构建非常复杂,但集成环境则更加复杂。
提议的架构在下图中展示:
图 6.9 – WineCo 的提议集成架构
更加复杂的是 WineCo 的企业集成标准。它规定所有来自 Salesforce 的集成必须使用公司的集成库来实现。那本来是可以的;然而,这个库只支持同步或异步的 REST 调用,极大地限制了集成设计的选择。
Clare 和她的团队不管怎样继续进行。他们提前完成了大部分核心 Salesforce 的构建,但集成部分进展滞后,遇到了一些不同的问题。
第一,返利系统不支持任何形式的批量处理,导致大量调用其 API。系统所有者质疑当前的设置是否能在上线场景中扩展,最终,需要采购四台新服务器,以确保系统能够承受负载。
第二,对 ERP 系统的查询过多,导致响应时间慢,UI 界面等待时间长。现有架构下无法解决此问题,因此决定将其视为培训问题来处理。
第三,CMS 服务从服务器端调用时困难重重,最终作出妥协,通过 JavaScript 包含追踪代码,尽管这需要正式的例外,并且会导致显著的延迟。
最后,通知服务并不适合分销商门户的许多消息需求,导致格式异常的消息,许多情况下很难回复。这也被接受,并被视作一个培训问题来处理。
项目完成并上线,几乎没有太多宣传。内部用户不喜欢新界面,分销商的采用程度也不热烈。Clare 做出最后的论证,建议重新设计基本的集成架构,使其更合适,然后再进行下一个项目。
问题
集成模式的单一主义试图解决一个问题:设计一个好的集成架构是根本上困难的,确定具体集成的正确模式、设计和实施特征也同样困难。
因此,它试图通过专注于一种在许多情况下都有效的方法来简化问题。通过这种方式,你可以定义一个标准的做事方法,而不必在每个具体案例的细节上纠结。
这有几个吸引人的原因:
-
第一点,标准往往有效。在许多情况下,采用标准化的做事方式是正确的选择。然而,整个集成架构是一个太广泛的目标,难以使用这种方法来解决。
-
第二,一旦你选择了一个方法,你可以创建支持资产,比如代码库和框架,用于日志记录和错误处理,这些资产能够在不同的集成中使用,这通常是有益的。
-
第三,你只需要让开发者掌握一项技能。这样可以减少开发复杂度、培训和入职需求。
如果不是因为一个不方便的事实——没有任何单一的集成模式是普遍适用的——这一切本来都很完美。
提出的解决方案
集成模式偏执建议对所有—或者至少几乎所有—在集成架构中所需的具体集成使用单一的集成模式。这可以通过公司标准明确规定,或者通过架构师和开发人员的工作和思维方式隐性体现。无论哪种情况,当这种偏好变得过于强烈时,你就会遇到反模式。
集成模式偏执的目标通常是相当合理的:
-
通过限制架构师和开发人员需要做出的选择,来减少集成的复杂性。
-
在企业架构中强制一致性,以避免不良副作用。
-
通过为开发人员提供明确的前进方向,并支持他们使用相关工具和框架,使开发人员的工作更轻松。
问题在于,并非所有具体集成都能适配某一给定模式。更新速度、可接受的延迟、数据量以及用户体验(UX)等特征,意味着长远来看,过度依赖单一的集成模式是有害的。接下来我们将探讨这一点。
结果
集成模式偏执引发的问题归结为技术不匹配。这是我们在其他反模式中也看到的情况——例如“金锤法则”。虽然在特定情况下可能有一些积极影响,但总体来看,你可能会看到以下一些后果:
-
你的集成环境由于需要多种变通方法来适应所使用的集成模式的局限性,反而变得更复杂,而不是如预期那样减少复杂性。
-
一些集成可能由于技术不匹配而无法在预期的质量参数内运行。这可能意味着周期性错误、性能差或类似问题。
-
这些因素通常意味着需要在持续的基础上承担更高的维护和支持负担,以修正问题。
-
最终,在某些领域的用户体验(UX)将让终端用户失望,因为该模式无法满足期望。
总的来说,你不会得到预期的好处,反而会陷入一团乱麻。
更好的解决方案
集成模式偏执的解决方案很简单。不要过于专注于单一的集成模式,无论是 RESTful 调用、EDA 还是批量传输。
相反,你可以为应用开发人员和架构师提供明确的指导,告诉他们在什么情况下哪些模式是合适的。在其他条件相同的情况下,偏好是可以的,但在实践中,很少有事情是完全相同的。
以下是 Salesforce 集成模式的概述:
图 6.10 – Salesforce 集成模式概览
对选择集成模式持一定保守态度是有道理的。这可以带来一些好处,比如采用一致的方法,利用标准框架和库。
你还可以使用中间件在系统之间创建一定的集成共性,尽管这只是将复杂性转移到了另一个平台。然而,当关键时刻来临时,如果某种方法是适合你的集成需求的,那么你应该使用它。
事件地狱
当基于事件的架构出现问题时,会导致这种反模式,涉及到可扩展性 和控制的失败。
示例
SalesCo 是一家中型公司,专注于定制制造设备,已经使用 Salesforce 作为他们的 CRM 多年。他们的实施是自然增长的,从基本的潜在客户和机会管理开始,逐渐扩展到包括用于管理复杂产品配置、报价和订单履行的自定义对象。
随着业务的增长,SalesCo 的领导层决定现代化他们的系统集成方法。他们听说了 EDA 的好处,并希望利用 Salesforce 的事件功能来创建一个更加灵活和集成的系统架构。
Sarah,SalesCo 的高级 Salesforce 开发人员,负责实施这种新的事件驱动方法。她对使用平台事件解耦不同的过程并创建更灵活的系统充满了期待。
Sarah 首先通过识别可以受益于事件驱动方法的关键业务流程来开始。她为销售过程的各个阶段、产品配置更新、报价生成和订单履行创建了平台事件。目的是让系统的不同部分对这些事件做出反应,而不是有紧密耦合的同步流程。
例如,当销售代表将一个机会标记为Closed Won时,系统会触发一个OpportunityClosedEvent。这个事件会触发多个操作:
-
订单履行团队将收到通知,开始处理订单。
-
财务系统将会收到通知以生成发票。
-
库存管理系统将会预留所需的产品。
-
客户成功团队将会被提醒开始客户入职。
类似地,当产品配置更新时,系统会发出ProductConfigChangedEvent,触发报价的重新计算、相关机会的更新以及通知相关销售代表。
最初,这种方法似乎运作良好。系统变得更加灵活,不同的团队可以更加独立地工作。在这种成功的鼓励下,Sarah 和她的团队继续添加更多的事件和事件驱动的流程。
然而,随着事件和事件处理程序数量的增加,问题开始显现:
-
调试变得越来越困难。当问题发生时,很难追踪导致问题的具体事件和处理器的顺序。
-
性能开始下降。随着每个事件触发多个处理器,一些处理器又会触发额外的事件,系统开始变慢,尤其是在高峰使用时段。
-
数据不一致开始出现。随着多个进程基于事件更新相关记录,维护数据完整性变得困难。
-
开发速度下降。随着事件驱动系统的复杂化,即使是小的变动也需要仔细考虑可能对整个系统产生的连锁反应。
-
新成员的入职变得具有挑战性,因为理解完整的系统行为需要了解分布在代码库各个部分的众多事件及其处理器。
尽管存在这些问题,SalesCo 团队仍然不愿意放弃他们的事件驱动方法。他们已经在这个架构上投入了大量时间和资源,许多流程现在都依赖于它。Sarah 发现自己处于一个困难的境地,试图维护和扩展一个变得庞大且难以管理的系统。
问题
事件地狱反模式发生在系统过度依赖事件进行组件间通信时,导致代码库变得复杂且难以维护。这个反模式在那些采用事件驱动架构(EDA)但没有充分理解其影响或没有为其使用制定适当指南的系统中尤为普遍。
在 Salesforce 环境中,事件地狱通常表现为过度使用平台事件、流媒体 API 和基于触发器的自动化。虽然这些技术为构建响应性强且解耦的系统提供了强大的能力,但其误用可能导致一张错综复杂的事件发出和处理器网络,这会掩盖系统的行为,并使其维护变得具有挑战性。
事件地狱的关键特征包括以下几点:
-
过度使用事件:事件被用于几乎所有的组件间通信,即使是那些不需要事件驱动设计复杂性的简单同步操作。
-
复杂的事件流:随着事件和处理器数量的增加,控制流变得越来越难以跟踪。一个单一的用户操作可能触发一连串的事件,这使得很难预测或理解任何给定操作的全部影响。
-
缺乏明确的责任划分:在事件地狱的场景中,通常难以明确哪个组件或过程对特定的数据或功能负责。多个组件可能会发出或响应相同的事件,从而导致对某些操作发生位置的混淆。
-
调试难题:在事件地狱场景中跟踪执行路径非常具有挑战性。当问题出现时,开发人员可能需要在多个组件中的众多事件处理程序之间筛选,以理解发生了什么。
-
性能问题:事件的不断发布和处理可能导致性能下降,尤其是在交易量较大的系统中。
-
数据不一致:由于多个进程基于事件更新相关记录,维护数据一致性变得越来越困难。
-
测试挑战:事件地狱使单元测试尤其困难,因为组件通常依赖于复杂的事件交互,而这些交互在隔离环境中很难模拟或模拟。
在 Salesforce 生态系统中,事件地狱尤其成问题,因为平台的限制条件。过多的事件发布和处理会迅速消耗 CPU 时间、SOQL 查询限制和 DML 操作,从而导致系统超时和故障。
提议的解决方案
事件地狱反模式通常作为解决实际架构问题的提议解决方案出现。它承诺通过利用 EDA 的强大功能,提供一个高度解耦、响应迅速且可扩展的系统。这种方法的吸引力很强,特别是在 Salesforce 生态系统中,平台事件和流式 API 提供了强大的能力,用于构建事件驱动的系统。
该方法的支持者认为,通过使用事件进行大多数组件间的通信,可以实现以下目标:
-
松散耦合:组件只需要知道它们发布或消费的事件,而不需要知道系统中其他组件的情况
-
可扩展性:事件驱动的系统理论上可以通过增加更多的事件消费者来处理增加的负载
-
适应性:可以通过创建新的事件消费者来添加新功能,而无需修改现有代码
-
实时响应性:事件允许对系统状态变化做出即时反应
-
集成简化:事件可以作为集成各种系统和服务的通用语言
在 Salesforce 上下文中,提议的解决方案通常涉及以下内容:
-
使用平台事件进行大多数对象间和进程间的通信
-
实现众多 Apex 触发器以响应记录更改发布事件
-
创建多个 Apex 类来订阅和处理各种事件
-
利用流程生成器或 Flow 响应事件并更新记录
-
主要通过事件发布和消费来集成外部系统
这种方法似乎解决了许多常见的架构挑战。它似乎减少了系统不同部分之间的直接依赖,允许轻松扩展功能,并提供了一个明确的实时更新和集成机制。
然而,正如我们在下一节中将看到的,这种解决方案在被不加区分地应用时往往会带来比解决更多问题。
结果
当事件地狱反模式占据主导时,系统的结果将是:尽管它承诺提供灵活性和解耦,系统却变得越来越脆弱、难以理解,并且难以维护。在 Salesforce 实现中,事件地狱的后果可能是严重的:
-
系统稳定性下降:随着事件和处理器的网络不断增长,系统变得更加容易出现意外行为。系统中某一部分的微小变化可能会产生深远且不可预见的后果,导致更多的 bug 和系统不稳定。
-
性能下降:事件的不断发布和处理可能对系统资源造成重大压力。在 Salesforce 中,尤其是在高负载情况下,这很快会导致治理限制异常。用户可能会体验到响应时间变慢和更频繁的超时错误。
-
调试噩梦:当问题发生时,追踪根本原因变得极其困难。开发者必须追踪复杂的事件发布和处理链,这些链通常分布在多个对象和类中。这大大增加了解决问题所需的时间和精力。
-
数据一致性问题:由于多个进程基于事件更新相关记录,保持数据一致性成为一大挑战。当多个事件处理器试图同时更新相同的记录时,可能会发生竞态条件,导致数据冲突和一致性问题。
-
降低的开发者生产力:随着系统复杂性的增加,即使是小的变更或功能添加,也需要仔细考虑它们在整个事件驱动架构中的潜在波及效应。这减慢了开发进度,并增加了每次变更的风险。
-
入职困难:新团队成员很难理解系统的行为,因为逻辑分布在众多事件处理器中,而不是集中在更传统的服务层或控制器中。
-
测试挑战:编写全面的单元测试变得极其困难,因为各个组件与事件系统紧密耦合。集成测试变得更加重要,但也更难配置和维护。
-
扩展性问题:具有讽刺意味的是,尽管事件驱动架构(EDA)通常因其潜在的可扩展性优势而被采用,但事件地狱可能导致相反的结果。随着事件量的增加,系统可能难以跟上,导致事件积压和处理延迟。
-
增加的运营成本:事件地狱引入的复杂性通常需要更强大的(且更昂贵的)计算资源来保持可接受的性能水平。这也可能需要更复杂的监控和警报系统,以跟踪事件流并识别问题。
-
可见性有限:理解系统当前状态变得更具挑战性,因为重要的业务逻辑和数据转换作为事件的副作用而不是通过更可见和可追溯的直接操作进行。
-
集成复杂性:虽然事件可以简化集成的某些方面,但事件混乱可能会使系统之间的清晰契约难以维护。对事件结构或处理逻辑的更改可能会对集成系统产生意外影响。
-
治理挑战:在受管制行业中,事件混乱可能会使提供清晰的审计跟踪和证明合规性变得困难,因为重现导致特定系统状态的操作顺序可能很难。
在 Salesforce 环境中,这些问题通常会因平台特定限制而加剧。例如,无法控制触发器执行顺序可能导致事件发布者和处理程序之间的竞争条件。类似地,复杂事件驱动场景中可能很快超出平台的治理限制,导致运行时错误和事务处理不完整。
更好的解决方案
要避免陷入事件混乱反模式,同时仍然利用 Salesforce 中事件驱动架构的好处,请考虑以下策略:
-
保留事件用于真正的异步或解耦操作。并非每个状态更改或业务流程都需要基于事件驱动。对于简单的线性流程,请使用直接方法调用或同步操作。
-
在 Salesforce 组织中建立明确定义的领域,并主要用于跨领域通信的事件。在一个领域内,更倾向于更直接的交互形式。
-
在设计事件结构时要考虑周全。使用版本化事件,并且每个事件中仅包含必要的信息。这可以帮助管理系统演化并减少事件生产者和消费者之间的耦合。
-
对于需要完整状态变更历史记录的复杂领域,请考虑实施事件溯源。这种模式可以提供更好的可追溯性,并使系统状态推理更加容易。
-
使用平台事件触发器来集中事件处理逻辑,与拥有多个独立处理程序类相比,这样做可以更容易地管理和调试。
-
使用断路器模式防止事件处理在高负载情况下或经历下游系统故障时压倒系统。
-
对于复杂领域,请考虑使用命令查询职责分离(CQRS)来分离读写模型。这可以简化您的事件处理逻辑并提高性能。
-
接受在某些情况下,最终一致性是足够的事实。这可以帮助简化您的事件处理逻辑并提高系统性能。
-
为事件处理实施一致的错误处理和死信队列。这可以帮助更快地识别和解决问题。
-
保持清晰、最新的事件模式、生产者和消费者文档。考虑使用工具生成事件流的可视化表示。
-
使用 Salesforce 的事件监控功能,并考虑实施额外的日志记录以跟踪事件的发布和消费。这有助于识别性能问题并协助调试。
-
在实现复杂业务流程之前,使用事件风暴会议与团队共同建模。这有助于识别适当的边界和事件使用。
-
对于某些场景,其他集成模式(如请求-响应或发布-订阅)可能比纯事件驱动方法更为合适。
-
对于可能接近治理限制的复杂事件处理,考虑使用 Queueable Apex 将处理分解为可管理的块。
-
使用 Salesforce 的平台缓存存储频繁访问的数据,这些数据源自事件,从而减少重复复杂事件处理的需求。
-
使用功能标志逐步推出事件驱动的功能,并在生产环境中出现问题时快速禁用有问题的事件流程。
通过应用这些策略,您可以在 Salesforce 中创建一个更易维护且高效的事件驱动系统,避免事件地狱的陷阱,同时仍能收获反应性、解耦架构的好处。记住,目标是将事件作为您架构工具包中的强大工具,而不是将其作为应对所有集成和通信挑战的万灵药。
我们现在稍作偏离,探讨新兴人工智能技术对集成反模式的普遍影响。
人工智能对集成的影响
随着人工智能的不断发展并渗透到软件开发和系统集成的各个方面,必须考虑其带来的潜在好处与风险。本节探讨了人工智能如何影响集成实践,可能引发新的反模式,同时也提供了避免现有反模式的机会。
随着人工智能技术的广泛应用,集成领域正处于重要转型的边缘。虽然人工智能驱动的集成前景令人振奋,但我们需要以批判的眼光看待这一新前沿。与任何技术进步一样,人工智能的引入可能会导致新的反模式,从而可能破坏它们本应带来的效率。
可能出现的一个潜在反模式是我们可能称之为AI 过度依赖综合症。当组织过度依赖 AI 驱动的集成工具,忽视人类监督和领域专业知识时,就会发生这种情况。例如,考虑一种情境,一家公司实施了一个 AI 驱动的集成平台,承诺自动映射数据字段并优化 Salesforce 与其遗留 ERP 系统之间的数据流。初期结果令人印象深刻,他们可能会减少集成团队的人员,并完全依赖 AI 系统。然而,AI 可能无法理解复杂的业务规则和数据关系,从而导致库存管理和订单处理中的关键错误。这种过度依赖可能会导致人类专业知识和背景的流失、由于误解业务逻辑而产生的系统性错误的可能性,以及在排查和解决复杂集成问题时的困难。
另一个我们可能会看到的潜在反模式是黑箱集成。当用于集成的 AI 模型变得如此复杂,以至于人类开发者和架构师无法理解时,就会出现这种情况。假设一家公司采用一个复杂的机器学习模型来管理 Salesforce 与多个外部系统之间的实时数据同步。该模型会根据数据模式不断演化。随着时间的推移,集成行为可能变得不可预测,团队可能会很难解释或控制某些数据转换。缺乏透明度和可审计性可能会导致在遵守数据法规方面遇到困难,并增加在关键业务流程中出现意外行为的风险。
我们还可能会遇到我们所说的训练数据偏见放大现象。当用于集成的 AI 模型在有偏见或不完整的数据集上进行训练时,可能会导致结果失真,并可能引发歧视性后果。例如,一家金融服务公司可能会使用 AI 模型将 Salesforce 中的客户数据与其信用评分系统进行集成。如果该模型主要在城市地区的历史数据上进行训练,它可能无法准确评估乡村客户的信用 worthiness,导致不公平的贷款拒绝。这可能会导致现有偏见的延续和放大、潜在的法律和道德问题,以及对 AI 驱动的集成系统的信任破坏。
尽管这些潜在的反模式描绘了一幅警示图景,但需要注意的是,AI 也为缓解现有的集成反模式提供了显著的机会。例如,AI 可以通过分析使用模式并建议最优的接口结构,帮助防止臃肿接口反模式。它还可以通过根据实时系统行为和需求,建议最合适的集成模式,从而解决集成模式狂热的问题。此外,AI 模型可以通过预测潜在的性能瓶颈并提出优化建议,帮助防止多余的集成。
为了在集成中利用 AI 的好处并避免潜在的陷阱,采用平衡的方法至关重要。这可能涉及将 AI 推荐与人工专业知识结合,用于关键集成决策,优先选择能提供明确决策解释的 AI 模型和工具,实施强大的监控系统来跟踪 AI 驱动的集成性能,确保 AI 模型在多样化和具有代表性的训练数据集上进行训练,以最小化偏差,并定期审计 AI 驱动的集成系统。
随着 AI 继续重塑集成领域,Salesforce 架构师和开发人员必须保持对其带来的机会和风险的了解。AI 在集成领域的旅程刚刚开始,随着技术的演进,新的反模式和解决方案可能会不断出现。保持灵活、批判性思维,并时刻保持信息更新,将是驾驭这一既激动人心又充满挑战的领域的关键。
我们现在已经完成了本章中的模式内容,将继续讨论关键要点。
了解关键要点
在本节中,我们将稍微抽象一下特定的模式,而是试图提取您在日常工作中作为 Salesforce 架构师或为 CTA 评审委员会准备时可以使用的更广泛的学习要点。
在架构 Salesforce 解决方案时,您应注意以下几点:
-
中间件可以是创建秩序并改善系统结构的绝佳方式。然而,您也可以以某些方式使用它,导致弊大于利。
-
如果您所做的仅仅是用中间件通过等效的点对点流替代直接连接,您可能已经进入了反模式的领域。
-
在某些情况下,自定义服务可以是 Salesforce 组织的一个极好的补充。然而,它们会带来相当大的复杂性。
-
您不应因为看似是业务需求的定制服务而冲动地添加大量服务。相反,您应该退一步,从大局来看需求,看看有哪些选项可以实现所需的特定集成流。
-
如果您正在构建自定义接口,无论是在 Salesforce 上还是在您的中间件平台上,都应确保有适当的治理措施,以避免最终产生一个做所有事情的臃肿接口。
-
如果可能的话,避免过于频繁的集成调用。
-
如果你确实需要高频率的状态传输,考虑使用像 CDC 这样的专用技术。
-
一般来说,设计集成时必须明确考虑系统的限制。例如,不要假设一个旧的 ERP 系统能够处理无限次的调用。Salesforce 当然也有明确的限制。
-
保持灵活的集成架构方法。不要对某一种风格过于执着并用它处理所有事情。仅仅因为事件驱动的微服务很流行,并不意味着它适合每个场景。考虑参考 Salesforce 的集成模式指南,帮助你选择合适的集成模式。
-
给出清晰的指导,帮助你团队成员和外部合作伙伴选择集成模式。不要认为他们能自行做出正确的决策。
在准备 CTA 审查委员会时,你应该注意以下几点:
-
几乎每个场景都会有中间件的需求。你应该了解常见平台(如 MuleSoft)的关键能力,并能够智能地讨论它们如何融入系统架构。
-
尽管你可能不会在场景中看到足够的集成,形成类似 MINO 模式的问题,但仍然值得思考中间件为你正在传递的每个集成流程所带来的具体价值。
-
不要一味地通过中间件处理所有的集成——往往有一些例外情况需要不同的处理方式。
-
建议定制 Web 服务是一项重要的定制内容,需要强有力的理由才能在审查委员会架构中包含。
-
如果你需要定制接口,那么在大多数情况下,你应该通过中间件来构建和暴露接口。
-
虽然在审查委员会中你不太可能遇到一个接口臃肿的情况,但仍然值得考虑如何构建你的集成接口,以及它是否平衡。
-
你需要考虑你所建议的设计可能带来的性能影响。通常情况下,场景会有高频率的要求,如果以明显的方式指定这些要求,可能会导致类似于多次集成模式的性能问题。
-
准备讨论如何在 Salesforce 环境中应用 DevOps 实践来管理和部署复杂的集成。
-
审查 CTA 审查委员会的关键目标,并准备好阐明你的经验如何与这些目标对接。
-
熟悉与你项目相关的最新 Salesforce 功能和最佳实践。
-
确保所有的支持文档和资料准备齐全,能够顺利展示。
-
你可能会被问到 Salesforce 平台的集成限制,因此值得事先记住这些限制,便于在委员会中作答。
您应该彻底掌握 Salesforce 平台上所有常见的集成模式。这包括关于何时选择哪种模式的决策指导。在工作中,您可能需要多种模式,并且应该能够清晰地阐明您为何做出这样的选择。
我们现在已经讲解完本章节的内容,可以继续进行。然而,首先我们将总结一下我们的学习内容。
总结
在本章节中,我们回顾了五种不同的反模式,这些反模式在不同方面可能导致集成架构失败。值得时刻牢记这些反模式。
集成领域极为复杂,且在多个层面上都可能出错。从选择错误的集成模式或误用中间件,到具体实现的技术细节,反模式可能会在项目层面,甚至企业架构层面,造成严重问题。
这种复杂性强调了为何经验丰富的架构师在处理集成时总是保持谨慎。集成是项目失败的最常见原因之一,无论是在 Salesforce 上,还是在一般情况下。
值得重申的是,本章节是唯一一个所有反模式不仅适用于 Salesforce,而且适用于所有企业软件系统的章节。学习了这些内容之后,您应该能够稍微更好地准备迎接集成领域中即将遇到的挑战。
在已经讲解了集成领域之后,我们将继续讨论适用于您部署过程和治理的反模式。
第三部分:流程和沟通反模式
本部分将教您如何识别和缓解与流程、治理和沟通相关的反模式。
本部分包含以下章节:
-
第七章,避免开发生命周期偏离轨道
-
第八章,无误译的沟通
-
第九章,结论
第七章:防止开发生命周期脱轨
在本章中,我们将探讨现代 DevOps 实践,特别是持续集成和持续部署(CI/CD),如何与软件开发中的各种反模式相关。我们将首先识别显著的过程级反模式,然后讨论 CI/CD 如何影响软件打包。最后,我们将探讨与测试相关的常见反模式。在本章末尾,我们将总结与现实应用和 CTA 复习委员会考试相关的关键要点。
在本章中,我们将讨论以下主要内容:
-
如何避免在项目交付中犯大方向性错误,例如如何结构化发布和处理关键权衡问题
-
如何避免以可能对组织有利但在架构上存在问题的方式来构建您的包
-
如何避免在面临交付压力时妥协代码和部署质量的陷阱
完成本章后,您将理解常见错误如何影响开发生命周期和相关活动,并掌握一些工具,帮助您避免这些问题。
过程对齐错误
在本节中,我们将讨论两种反模式,它们以不同方式使开发生命周期脱轨。首先,我们将探讨大爆炸发布如何在许多情况下导致灾难性结果。其次,我们将讨论项目分配主义——这种错误的信念认为可以避免做出重要的权衡。
大爆炸发布
大爆炸发布反模式将所有功能的发布集中在项目的最终单一事件中。
示例
RollerCo 是一家主要生产滑轮鞋和滑板的制造商,正在经历一场以创建一个数字化驱动的业务为中心的重大业务转型,以更好地满足当今买家的需求。尽管这场转型并非最终目标,但作为过程中一部分,计划了几个系统替换项目,旨在提供更大的 IT 灵活性。
Anandh 正在领导一个项目,该项目旨在替换 RollerCo 使用了 15 年的老旧自主开发 CRM 系统。该系统将被 Salesforce Sales Cloud 和 Service Cloud 的组合所替代,但由于老旧系统的高度定制化,已经证明无法使 Salesforce 设计保持接近标准。
高度定制化的另一个后果是,整个系统将需要作为一个整体上线。在全面上线之前,无法发布更小的最小可行产品(MVP)增量,因为那样会使客户支持人员的工作过于复杂。
在项目启动后不久,Anandh 被告知董事会已批准升级企业资源规划(ERP)到 SAP S/4HANA。由于 CRM 和 ERP 在多个流程中紧密耦合,这意味着 Anandh 不仅需要应对增加的集成积压,而且两个系统的上线计划也需要协调,以确保它们能同时上线。
很快就发现,ERP 升级带来的额外复杂性意味着原始的 Salesforce 实施计划必须推迟。特别是,集成的复杂性超出了任何人的预期。
首席信息官(CIO)在与一位可信的供应商代表会面后宣布,为了解决 CRM/ERP 集成问题,RollerCo 将投资建设一个新的战略中间件平台。这将替代现有的中间件,并与整体的 CRM/ERP 上线时间表同步上线。
当 Anandh 和他的团队忙于重新设计所有集成以适应新的中间件平台时,又有一个新发现。负责 RollerCo 网络商店的团队发现,让它与新的 CRM/ERP 设置兼容几乎是不可能的。
这需要更改应用程序数据层的基本架构,而当初构建该架构的开发人员已经不在公司。其他人无法弄明白如何操作,因此一个新的电子商务应用程序也被加入到整体项目积压中。为了方便起见,时间表与整体 CRM/ERP 上线时间表对齐:
图 7.1 – RollerCo 的新平台
该项目遭遇了不断的延迟。尽管有些领域比其他领域受影响更大,但没有一个主要平台在实施阶段表现得很好。三年过去了,初步版本终于接近完成。
RollerCo 已建立了一个复杂的部署流水线和切换计划,以处理多系统的同时上线,所有这些都计划在公司淡季的一个周末进行。上线前的测试花费了超过三个月的时间,并且需要进行一些范围缩减和紧急修复。
即便如此,参与该项目的人员也不敢明确说出系统会按预期运行。各种可变因素实在是太多了。
上线周末一开始表现不错,所有必要的数据迁移活动顺利完成。然而,一旦真实的业务用户进入系统,各种问题开始浮现。
到了周日晚,问题的数量已经达到一种让继续推进显得过于冒险的程度。虽然到目前为止没有任何单一问题是致命的,但由于小问题引起的整体干扰已经相当严重。在一个深夜电话会议中,指导委员会决定回滚并推迟上线。
后果是显著的。毕竟,项目已经有三年的时间来完成工作。然而,很快就变得清楚,问题无法在几周内解决。仍然有很多工作需要完成。
团队们将在接下来的六个月里共同寻找解决方案。在这段时间里,他们专注于缩小范围并简化功能,以便让推出过程更容易管理。
最终,包含 CRM、ERP、中间件和电子商务的综合平台上线。然而,它上线时带着一大堆已知问题和解决方法,而且其范围大大缩小,远低于最初的设计。
问题
大爆炸发布是一种反模式,通常尝试解决在发布过程中如何处理复杂依赖关系的问题。这些依赖关系可能存在于系统之间或系统内部。它最常出现在没有强有力的数字化转型领导的地方,而且现有的领导层往往高度规避风险。
依赖关系通常与某些业务流程相关,这些流程有着长期以来以某种方式进行的惯例,这意味着大量的功能必须作为一个整体进行部署。有时候,像我们在这个例子中所见的那样,这甚至可能导致系统级别的巨大依赖关系。
解构现有的业务流程并提出过渡架构(在部分解决方案存在的情况下,满足完成工作的需求)可能相当困难,像功能的最小可行产品(MVP)子集那样可以独立提供价值也同样困难。大爆炸发布通过简单地将一切推迟到未来的一个大事件来避免这些问题。
提议的解决方案
大爆炸发布反模式建议在漫长的交付过程中,最后进行一次大的发布,涵盖所有相关功能。这可能意味着几年积累的工作同时上线,而没有任何中间的反馈。
这种解决方案对于交付团队和客户来说,因各种原因可能非常有吸引力:
-
它将整个系统简化为一个单一的部署单位,可以作为一个整体进行管理。
-
它简化了规划过程,因为你不需要为多个发布、部分数据迁移和共存场景做规划。这意味着整体架构也被简化,因为不需要为项目的范围设计过渡架构。
-
你还避免了在什么时候包含哪些内容、可以满足哪些业务需求以及何时满足的艰难决策。
-
对于交付团队和客户来说,这很容易理解。
-
你成功地将问题推迟了,把它变成了以后再处理的事情。在某些情况下,到时候可能会有其他人来做这件事。
因此,你可以理解为什么——即使在小范围发布和 DevOps 思维已经成为主流范式的今天——许多项目仍然最终以大爆炸的方式进行部署。不幸的是,这通常不会顺利进行。
结果
Big-Bang 发布反模式的根本问题在于,你往往无意间承担了大量的风险。技术风险不会随着部署组件数量的增加而线性增长。相反,由于组件间连接和依赖关系的超线性增长,风险会以更快的速度增加。
简而言之,如果你只部署一个组件,你需要处理的风险仅限于该组件的故障。如果你部署了两个互联的组件,那么你就需要应对最多四种故障模式:
-
组件 1 独立故障
-
组件 2 独立故障
-
组件 1 故障并触发组件 2 的次级故障
-
组件 2 故障并触发组件 1 的次级故障
这四种故障模式可能会表现出独特的症状,根本原因可能并不明显。试想一下,如果你同时部署 20 个组件,并且它们之间有大量的相互连接,你将面临多少潜在的故障模式。
在软件开发中,流水线就像是代码的工厂装配线,每个步骤会自动流向下一个。就像汽车在不同的工位进行组装、测试和质量控制一样,代码也会经历构建、测试和部署的各个阶段。DevOps(开发和运维结合)是一套将软件开发和 IT 运维团队结合起来的实践,旨在加速、更可靠地交付软件。可以把它看作是打破了编写代码的人员与维护这些代码运行的系统之间的传统壁垒。
现代 DevOps 实践高度强调自动化测试和部署流水线,它们充当着防范“爆炸式”发布(一次性发布多个更改)风险的安全网。当开发人员修改代码时,这些更改会自动触发一系列的测试——单元测试检查单个组件,集成测试验证不同部分的协作,系统测试确保整个应用程序功能正常。这种被称为持续集成的自动化流程,帮助团队及早发现和修复问题,避免问题影响整个系统。持续交付会将这些经过验证的更改自动准备好发布,确保每次更改都能随时部署。
CI/CD 框架的实施将传统的、少量大规模发布的方法转变为一系列更小、更易于管理的更新。团队不再将数十个更改积累到一个重大发布中(这可能很冒险,就像试图同时更改发动机的多个部件一样),而是可以在每个更新准备好并经过验证后立即部署。这个增量方法使得识别和修复问题变得更加容易——如果出现问题,团队可以迅速定位到是哪个具体的更改导致了问题,并修复它或回滚这个更改,而不是一次性撤销多个更新。结果是更稳定的软件系统,因为团队可以监控每个小更改的影响,并在问题成为大问题之前解决它们。
由于大规模部署的故障模式非常多,这意味着测试变成了一个巨大的任务,通常你可能测试数周,仍然无法确定是否已经测试了所有重要的案例。调试错误也变得更加困难,因为追踪各个组件之间可能的连锁反应比仅仅找出单个组件中的错误要困难得多。
相同的困难也适用于推出和回滚任何需要完成的切换任务。在“大爆炸”场景下,甚至培训和变更管理也变得更加困难。
总的来说,发布越大,失败的风险越大。如果你不是赌徒,应该避免走这条路。
更好的解决方案
如果大规模发布是问题,那么小规模发布显然是解决方案。从风险管理的角度来看,每次发布的理想功能量是一个单独的特性或一个单独的用户故事。这正是持续交付(CD)的前提,正如许多领先的 DevOps 导向的组织所实践的那样。
然而,我们必须承认,并非所有组织都具备规模或技术成熟度来采用允许每次只交付一个功能的纯 DevOps 配置。然而,如果你追求小规模发布的理想,至少你将开始减轻这些问题。
小规模发布具有以下特点:
-
风险更小
-
更容易测试
-
更容易调试
-
更容易在发现错误后进行修复
-
更容易推出和回滚
-
更快地向业务用户交付价值
-
促进并增加系统的采纳
-
使变更管理更容易控制
总体来说,一旦完成了必要的技术和业务流程工作以启用小规模发布,那么几乎没有——如果有的话——缺点。
一般来说,旨在提高韧性将有助于避免本章中提到的问题。一个好的起点是使用完善架构框架:architect.salesforce.com/well-architected/adaptable/resilient
。
项目派系主义
Project Pieism 未能处理关键架构权衡,而是坚称你可以既享有它又能够使用它。
示例
ConglomoCo 是一家大型多元化企业集团,拥有许多业务单元(BU),有些与业务领域相关,有些与地理位置相关。大多数业务单元在运营和信息技术基础设施方面相当独立。此外,业务单元负责人相对于总部(HQ)员工拥有更多权力,因为他们实际上是自己业务的主宰。
当 ConglomoCo 的 CIO 决定推动 Salesforce 的全球推广时,他们因此遇到了多个业务部门负责人强烈的抵制,这些部门有自己的 CRM 策略,并不希望总部插手。然而,作为新倡议的一部分,首席执行官(CEO)和首席财务官(CFO)要求提供全球销售漏斗的汇总视图,而 CIO 正是借此来推动他们的 Salesforce 战略。
金,作为 ConglomoCo 总部的高级 IT 项目经理,因此被赋予了推动 Salesforce Sales Cloud 和 CPQ 全球推广的责任。首席信息官(CIO)希望借此机会在各个业务单元之间标准化核心销售流程,并简化销售数据的报告。
因此,在与他的架构师进行沟通后,金提出了基于单一组织和标准流程的计划。业务单元内部将有一些本地化的变化,但这些变化的范围将被限制在一定程度上。
当金开始向利益相关者展示这个计划时,他发现这显然不是他们所期望的。各个业务单元(BU)有各自独立的流程、用户体验(UX)期望、本地集成以及他们希望新系统能满足的报告需求。
在一场高级领导研讨会上,许多问题浮出水面,并在最高层达成了妥协。新系统必须能够满足独立的销售流程、自动化、本地集成,并且能够为每个业务单元(BU)提供一定程度的用户体验(UX)定制:
图 7.2 – ConglomoCo 组织
然而,所有这些仍然必须在同一个 Salesforce 组织内进行,并利用相同的数据模型,以简化跨业务单元(BU)的报告。可以理解,这将导致更加定制化的实施,并带来成本上的影响,但首席信息官(CIO)仍然希望实施尽可能接近标准化。
实施过程漫长且缓慢。必然地,它包含了许多与不同业务单元相关的独立工作流。每个工作流似乎都有其复杂性,工作流之间的协调是一个持续且艰难的挑战。可以说,随着实施的推进,人员的疲劳感逐渐增加,大家对未来系统的期望也有所下降,更加看待它为一种必要的“恶”而非推动积极变革的工具。
金与业务部门进行谈判,并成功使两个较小的领域以试点方式上线。这些领域上线时并没有太大宣传,且存在许多漏洞。然而,比这些漏洞更糟糕的是,低采纳率。各业务单元的销售人员似乎尽一切可能避免将数据录入系统,而即使录入,数据质量也很低。
鉴于初期结果不理想,后续的推广被暂停。相反,一家管理咨询公司被请来调查为何采用情况如此差劲,并探讨如何改进。
问题
项目派系主义是一种反模式,其根本原因在于避免在实施系统时做出艰难的权衡。这可能是因为政治上的困难或项目领导力不足,但始终涉及未能承认一个需要决策的关键权衡。
从某种意义上来说,大多数软件架构中的工程问题,乃至一般问题,都涉及在一系列权衡之间找到平衡。然而,这些权衡往往令人不舒服,且往往无法取悦所有利益相关方。
因此,很多项目在没有做出必要的权衡的情况下继续进行,抱有后来可能找到解决方案的希望,或干脆闭眼不看事实。在任何情况下,这都是一种反模式。
提议的解决方案
项目派系主义建议,将一个或多个重要的权衡视为解决方案的一部分,认为这个权衡并不存在,你实际上不需要做出妥协,甚至可以既得到自己的“蛋糕”又能“吃掉”它。有时,这种做法通过忽视权衡或把它扫到地毯下完成;有时则是承认了权衡,但通过特殊请求来暗示这个情况是特殊的,因此这个权衡不适用。
这个位置显然很有吸引力。当在实施项目中需要做出关键权衡时,你可能不得不让一个或多个利益相关方失望。如果这些利益相关方在你的组织中很有权力,这可能并不是一件容易或愉快的事。你甚至可能发现自己由于公司政治被迫陷入项目派系主义(Project Pieism)的困境。
然而,即使是你组织中最有权力的高管,也无法改变软件架构的基本事实。总是存在权衡。每当在技术项目中出现你认为不需要做出权衡的情况时,你应该感到担忧。
结果
项目派系主义的结果是,你试图忽视的权衡最终会回归。根据墨菲定律,这通常会发生在项目生命周期中最不方便的时候,并对项目造成重大损害。
当然,具体的损害将取决于你忽视的权衡。在我们之前的例子中,我们忽视了全球与本地流程的优先级之间的权衡,以及标准功能与定制化之间的权衡。
ConglomoCo 曾试图建立一个具有全球流程的标准化系统,同时兼顾所有相关的本地变更。这导致了一个没人愿意使用的系统,因为它无法很好地满足任何人的需求。
其他权衡会产生不同的后果,但如果你未能做出关于推动架构的关键权衡的重要决策,你可以预见到不利的后果。
更好的解决方案
朝着更少的妥协未来迈进的方式,就是公开承认需要做出的权衡,并与利益相关者建设性地讨论选项。通常,确实有办法让利益相关者获得更多他们都想要的东西,但可能会以额外的成本或更长的时间线为代价。
让这个参与过程正式化的一种方式是,在项目早期建立良好的架构治理,并在架构论坛和业务论坛上讨论关键的架构权衡,以确保考虑到所有的视角。在我们的例子中,一个称职的架构委员会可能会指出,在 ConglomoCo 的情境中,根本无法让单一的组织策略有效运作。
作为架构师,我们需要对业务保持诚实,明确什么是可行的,什么是不可能的。我们是那些在技术方面了解可能性的专业人士,我们不应该假装我们最喜欢的技术能够超越必须做出艰难选择的现实。坚定立场,保持建设性,提供选项,且不忽视重要的权衡。
不频繁的检查
不频繁的检查是一个反模式,指的是开发者长时间在隔离的环境下工作,而没有将他们的更改集成到主代码库中,这会导致显著的集成挑战、减少可视性,并可能导致 项目延误。
示例
CloudTech,一家快速增长的科技公司,一直在开发定制的 Salesforce 解决方案,以管理其复杂的合作伙伴生态系统。该项目涉及多个团队,分别负责解决方案的不同方面,包括合作伙伴入驻、认证管理和收入分成计算。
高级开发者莎拉被指派构建收入分成计算引擎,这是一个关键组件,需要与系统的多个部分进行接口。鉴于计算的复杂性和涉及的众多业务规则,她决定在与主代码库集成之前,先完成整个功能。
项目经理汤姆对这种方法感到满意,因为他相信这能让莎拉完全专注于正确完成复杂的计算,而不会被集成问题分心。团队的技术负责人马库斯对长时间的隔离期表示了一些担忧,但最终同意了,考虑到莎拉的经验以及该组件的重要性。
Sarah 花了六周时间工作在计算引擎上。在此期间,她取得了显著进展,并在站会期间定期向团队更新她的工作。然而,她将所有更改保留在本地开发环境中,认为这是最安全的做法,直到功能完成并经过彻底测试。
与此同时,其他团队成员继续他们的工作。合作伙伴入驻团队对数据模型进行了一些更改。认证团队添加了新的验证规则,这些规则影响合作伙伴状态。集成团队修改了计算引擎需要交互的几个 API。
当 Sarah 最终完成计算引擎并准备将其与主代码库集成时,出现了几个问题。合作伙伴入驻团队对数据模型所做的更改与 Sarah 对架构结构的假设发生了冲突。新的验证规则影响了合作伙伴状态的确定,而这正是计算引擎的关键输入。修改后的 API 需要不同的参数和返回结构,而这与 Sarah 代码的预期不符。
团队现在面临危机。冲刺截止日期临近,但集成 Sarah 的代码将需要大量重构。代码审查过程变得令人不堪重负,因为团队成员难以理解和验证庞大的变更集。在测试过程中发现了几个关键的 bug,但由于变更之间的相互关联,修复变得复杂。
在额外的三周密集工作后,解决了集成问题,功能最终合并到了主代码库。然而,延迟影响了其他依赖的功能,项目时间表需要调整。团队还发现,Sarah 的一些工作在她孤立工作期间与其他团队成员已经实现的解决方案重复。
问题
不频繁检查的反模式出现在开发人员长时间独立工作且不将更改合并到主代码库的情况下。这种模式通常出现在涉及复杂功能或关键组件的场景中,团队认为隔离可以带来更好的集中和更少的干扰。
反模式通过开发人员在数周或数月内没有合并代码而表现出来,导致大规模、单一的变更集,难以审查和测试。这种做法限制了开发进度的可见性,并与不断变化的代码库和团队决策之间隔离开来。
虽然这种做法对复杂功能来说似乎是合乎逻辑的,但它从根本上误解了软件开发的协作性质以及持续集成(CI)的重要性。
提议的解决方案
不频繁检查合并方法认为,复杂的特性最好独立开发。支持者认为,开发者可以完全专注于他们的任务,而不必担心集成问题,保持代码“干净”,并在特性准备好之前不受持续变化的影响。他们相信,在特性完成后,测试会更为彻底,代码审查也会在检查完整功能时更有意义。通过将功能视为单一工作单元,项目管理看起来会更简单。
这个解决方案看起来很有吸引力,因为它承诺通过避免持续集成(CI)的开销并处理代码库中持续的变化,来减少复杂性。它建议开发者能够完全专注于特定功能,避免外部干扰,从而提高质量。
结果
不频繁检查合并反模式会导致几个显著的问题。集成成为一个重大挑战,最终与主代码库集成时会出现大量的合并冲突。通常需要进行显著的重构,以适应在隔离期间所做的更改,并且集成错误和 bug 的风险也会增加。
在整个开发过程中,可见性受损。团队对实际开发进展的了解有限,难以及早识别潜在问题,降低了做出明智项目决策的能力。
随着团队成员独立工作,合作问题随之而来。知识共享和同行学习受限,关于设计决策和实现方法的反馈也会延迟。这通常会导致重复劳动,因为不同的团队成员在解决类似问题时,彼此并不了解对方的工作。
质量影响变得明显,代码审查可能会错过关键问题。由于大型变更集,全面测试变得困难,并且由于复杂的集成场景,bug 更有可能漏网。
项目延期是常见的,因为初步时间表中没有考虑到延长的集成周期。这会导致一系列的延迟,影响相关特性,并增加了解决冲突和问题所需的时间。
技术债务通过架构不一致的原因积累,因为开发过程中的分歧导致团队发现重复的解决方案和不一致的方法,同时很难维持代码历史记录并理解更改的理由。
更好的解决方案
为了避免不频繁检查合并反模式,团队应当实施真正的持续集成(CI)。这意味着要建立自动化的构建和测试流程,要求开发者每天至少集成一次更改,设置集成问题的监控和警报,并使用功能开关在主代码库中管理不完整的功能。
复杂的功能需要拆解成更小、更易管理的部分。团队应计划增量开发,明确集成点,尽早识别依赖关系,并主动管理它们。每个组件的明确验收标准有助于保持关注,同时允许定期集成。
明确的集成政策至关重要。团队应定义集成之间的最大可接受时间,以及变更集大小的指南。代码评审流程应鼓励频繁的小规模评审,并应制定功能切换使用的标准。
在开发过程中,必须优先考虑沟通与可视化,定期进行设计评审,并在复杂功能上进行结对编程。团队应保持最新的架构决策文档,并定期进行团队同步会议,讨论技术挑战。
现代开发实践在防止这种反模式中起着至关重要的作用。基于主干的开发最小化了长期存在的分支,而全面的自动化测试有助于及早发现问题。功能标志有效地管理不完整的功能,适当的监控和可观察性确保团队能够快速识别和解决问题。
团队文化是成功的基础。组织应鼓励知识共享与协作,同时促进集体代码所有权。应支持持续学习和改进,团队应为早期反馈创造一个安全的环境。
避免这种反模式的关键是认识到软件开发本质上是协作性和迭代性的。成功的关键不在于避免集成挑战,而在于通过频繁集成和清晰沟通,使这些挑战足够小,能够有效管理。通过实施这些解决方案,团队可以保持高质量,同时避免孤立开发的陷阱。
解开流水线
本节将介绍与如何为基于包的开发构建包结构相关的一个关键 DevOps 反模式。
使用包创建孤岛
使用包创建孤岛是根据团队结构将 Salesforce 项目的包划分,而不考虑架构问题。
示例
MillCo 是一家生产 CNC 铣床的公司,拥有遍布欧洲和北美的子公司,正在为其 B2B 销售实施 Salesforce。这包括 Sales Cloud、CPQ 和 B2B Commerce。
Abigail 是 MillCo 的 CRM 技术负责人,在加入 MillCo 之前,她曾在另一家 B2B 制造公司领导过一个 CRM 实施项目。她的主要职责是确保来自三个不同供应商的技术交付在实现新系统的不同元素时具有一致性和高质量。
在项目启动时,Abigail 邀请了三个供应商团队以及内部相关方,并多次强调,虽然每个人都为不同的公司工作,但大家应当把自己看作是一个团队的一部分。MillCo 希望大家在同一页面上,共同朝着一个共同目标努力。
事实证明,这一切都是徒劳的。一旦工作正式开始,三家供应商很快就互相对立。Abigail 发现很难让他们达成任何共同的方法和标准。
尽管她可以强制执行某些规定,但她没有团队支持,如果供应商不配合,她所能做的也有限。她将问题上报,但被要求找到一个能够让工作按计划继续进行的解决方案。
她决定的解决方案是将每个供应商隔离在独立的软件包中。这样,供应商可以独立开发,除了他们的工作在平台的关键元素上直接冲突的情况。Abigail 决定亲自监控并调解这些争端:
图 7.3 – 软件包结构
她最终将大部分时间都花在了调解这些跨供应商冲突上。这也意味着她几乎没有时间去调查供应商在那些不涉及争议领域中使用的通用方法。
然而,最终,系统被构建完成。由于每个供应商都只在自己的环境中工作,偶尔才将代码部署到经过薄弱测试的集成环境中,因此准备进行用户验收测试(UAT)的第一步是将所有软件包部署到一个共享环境中,并测试基本流程。每个软件包都在自己的环境中经过了彻底测试,但尚未对跨软件包进行系统性测试。
即使在测试结果开始出来之前,情况也开始恶化。事实证明,供应商之间存在不兼容的系统和软件包设置——例如,CPQ 管理的软件包上就存在这种情况。这意味着部署被迫停滞,直到找到解决方法。
当测试人员真正开始工作时,情况变得更加糟糕。软件包之间存在许多细微的不兼容问题。例如,对于公共字段的解释和使用存在差异,不同的软件包使用相同目的的重复字段,以及部分重叠范围的自定义对象和冗余数据的创建。此外,三个供应商之间在自动化模式上也存在很大差异,尽管这是 Abigail 在项目初期已经指定了标准的领域。
总的来说,差异太大,无法迅速协调一致,项目不得不后退。Abigail 的上司谈判延长了时间表,以便重构软件包并使其统一。虽然她对延期感到高兴,但 Abigail 并不喜欢为了让供应商真正完成这项工作而进行的拉锯战。
问题
有时候,你可能希望让团队独立工作,而不必依赖或协调其他团队。在 Salesforce 的上下文中,这可能是因为各个团队在不同的云环境中工作,来自不同的供应商,或代表着你组织内不同的部门或业务单元(BU)。
这完全可以理解,因为协调问题确实很难解决。然而,当这种情况成为将 Salesforce 平台划分为包的基础时,它就变成了一种 DevOps 反模式。
提议的解决方案
使用包来创建孤岛的提议解决方案是,给每个团队分配自己的包来工作,反映出它们将要处理的内容。这避免了协调问题,但也带来了一系列其他问题。
这意味着你根据组织需求而非架构来结构化你的项目包设置。一开始看起来这可能是个不错的主意,显然也能短期内满足各个团队的需求,但不幸的是,这也意味着潜在的隐藏冲突很可能会存在,并且可能会保持隐蔽很长时间。
结果
使用包来创建孤岛的可能结果是,你将会遇到隐藏的冲突,直到包集成时才会显现出来。
这些冲突包括以下情况:
-
数据模型的不同使用——例如,字段和对象
-
安全模型中的问题,当使用了冲突的配置时
-
冲突的流程、验证规则或其他业务逻辑
-
偏离最佳实践,例如,在同一对象上有多个触发器
-
在同一对象上使用不同的自动化模式
-
关于系统设置的冲突假设
-
在不同的包中复制的功能,经常只是部分重叠
这可能会导致严重问题,而且重构起来会非常麻烦,既昂贵又耗时。
更好的解决方案
通常来说,包设计应当被非常重视。基于包的开发是大多数大规模 Salesforce 项目的正确选择,部分原因是它比其他替代方案更具可扩展性。
为了避免陷入使用包创建孤岛的反模式,请遵循以下准则:
-
在设计包结构时要考虑架构。例如,在典型的按服务线拆分的架构中,你可以将公共功能放在一个“Common”包中,所有其他包都依赖于该包,然后为每个服务线创建包含相关组件的单独包。你还可以有跨服务线的高层次包,处理诸如常见集成之类的内容,并且可以将交叉功能拆分到单独的包中,尽管这可能有些难以管理。重点是,你应该确保干净地管理依赖关系,并避免潜在的冲突重叠。
-
小心处理依赖关系;分层方法可以有效地确保依赖关系仅朝一个方向流动。
-
在需要时,让团队跨包工作。
-
考虑让特定团队拥有特定的包,而其他团队如果需要任何东西,则向它们请求工作。
-
通过技术治理论坛进行协调——例如,架构委员会。
在现代 DevOps 工作流中,利用如 Salesforce CLI 这样的工具对于有效的源代码跟踪和版本控制至关重要。Salesforce CLI 简化了集成过程,使开发人员能够轻松管理和部署跨环境的变更。通过利用源跟踪功能,团队可以确保开发过程中的一致性和准确性,增强协作并减少错误。这种方法使得元数据和代码变更的高效管理成为可能,与敏捷开发的最佳实践保持一致。
Salesforce DX 解锁包是 Salesforce 生态系统中现代开发工作流的关键组成部分。它们使开发人员能够创建模块化和可重用的组件,促进代码组织并改善团队协作。通过有效管理包版本和依赖关系,团队可以简化其 CI/CD 流程。解锁包还支持更细粒度的源代码跟踪方法,允许团队在不影响整个代码库的情况下,专注于不同的功能。通过使用解锁包,组织可以提升其开发实践,使其更加灵活,能够快速响应业务需求的变化。
一般来说,你不想把包设计误认为其他东西。构建你的包结构时,确保它适合你的架构并且对开发人员可行。
无测试的测试
测试是任何大型软件项目中的关键活动。在本节中,我们将看到,试图避免编写必要的单元测试可能会在中长期内引发重大问题。
虚拟单元测试
虚拟单元测试反模式通过编写虚拟测试绕过 Salesforce 内置的单元测试要求,这些虚拟测试优化了覆盖率,但 什么都不做。
示例
TruckCo 是一家初创的汽车公司,专注于构建下一代电动卡车。它更看重自己是科技公司而非制造公司,因此在顶级解决方案上的投资相当重,以保持技术领先。
一般来说,TruckCo 倾向于进行重度定制和高强度的敏捷项目,工作时间长且时间紧迫。TruckCo 目前在 Salesforce 上构建的供应链应用程序也不例外。
该应用程序将把他们的 B2B 商务门户与订单管理和供应链后端系统集成。它将实现来自备件供应商的 准时(JIT)订购,并且通常会显著缩短 报价到收款(QTC)过程,特别是在备件订单方面。
为了实现这些目标,TruckCo 计划将六个关键的后台系统与 Salesforce 集成,构建一个为其特殊流程优化的定制用户界面(UI),并构建一套跨平台的、支持 AI 的自动化系统,以提高订购过程的效率。
由于这个应用程序预计将是一个以代码为主、开发驱动的项目,TruckCo 决定将一支 Java 开发团队从固定员工中调过来参与,认为 Apex 与他们的背景足够接近,能够边做边学。Yana 是项目中唯一的传统 Salesforce 专家,她的角色是引导其他团队成员了解 Salesforce 的工作方式。
团队负责人 Matt 有点特立独行,其他团队成员也是如此。虽然他们使用单元测试,但并不总是坚持使用,通常更倾向于让用户报告错误,然后再修复它们。在 TruckCo 内部,虽然没有明确说明,但存在着强烈的偏好:即使这意味着发布一个有缺陷且不完整的产品,也要按时发布。
来自 Java 背景的开发人员很快开始对 Salesforce 强制要求的 75%单元测试覆盖率感到不满,而这一规定已被 Salesforce 部署工具所内置。Yana 在和团队其他成员共进午餐时,偶然提到了一些通过创建虚拟测试来欺骗 Salesforce 单元测试计算的方法。
尽管她开玩笑提到过此事,但令她懊恼的是,几天后,她发现虚拟单元测试开始出现在代码库中。当她向 Matt 提出这个问题时,他只是耸耸肩,表示他们已经落后于进度,因此没有时间全力编写测试代码。
然而,Yana 并没有气馁,在下次项目会议上,她正式提出了这个问题。她引用了 Salesforce 的指导方针,并得到了公司内部 Salesforce 架构师的支持。
项目赞助人承诺会派人调查这个问题。不幸的是,Yana 之后再也没有听到任何相关信息。似乎 Matt 曾表示,如果需要追溯性地编写完整的单元测试,将会导致项目出现重大延迟。按照 TruckCo 一贯的运营方式,这被视为不可接受,因此虚拟单元测试的问题被忽略了。
因此,随着项目进度的进一步落后,实践的加速也在持续。接近上线时,几乎每一个新的单元测试都是虚拟的。虽然自动扫描工具显示出令人印象深刻的 90%覆盖率,Yana 怀疑实际覆盖率是否高于 10%。
在上线前几周,来自业务利益相关者的一系列最后时刻的变更被提出。Yana 看不出有任何办法将这些变更纳入项目中,但 Matt 同意按时交付这些变更。
最后一段是来回变更的繁忙时期,测试人员发现了许多错误,接着是修复,这通常导致更多的回归问题。这种情况一直持续到实际的用户验收测试期间,又发现了大量问题。然而,没有人决定停止上线,并且在指定的日期,供应链应用程序正式上线。
当用户开始在应用程序上进行登记时,在主要流程中发现了几个严重的错误。这些错误出现在距离上线仅几周之前已经测试并且正常工作的区域,并且也是用户培训的一部分。
应用程序必须下线,并且召开了一次升级会议。在这里,应用程序的基本健全性和质量受到了严重质疑,并且达成了一个新的计划来研究质量问题并设计一种修复它们的方式,以便应用程序可以重新上线。
问题
虚拟单元测试旨在解决一个非常简单的问题:如何绕过 Salesforce 生产部署中严格的 75%单元测试限制?长期运行的 Salesforce 项目通常发现,无论是特定部署还是总体而言,它们都处于这一限制之下。
许多团队发现这种限制很烦人。特别是在开发人员从其他技术平台转移到 Salesforce 时,这一点尤为明显,在压力之下,或者在做一些“简单”的事情时。
提议的解决方案
提议的解决方案是创建虚拟单元测试,仅仅优化代码覆盖率,而不真正测试任何东西。这是少数几个接近糟糕实践的反模式之一。你可以在以下代码片段中看到一个虚拟测试的示例:
@isTest
class dummyTest{
static testMethod void notRealTest(){
//assume A is a class with two methods
A aInstance = new A();
aInstance.methodA();
aInstance.methodB();
//nothing is done to test anything
}
}
然而,这是一种可能会引诱到否认严肃 Salesforce 从业者有时可能会参与的行为。当你在压力下要达到冲刺目标或部署期限时,写一堆单元测试只是为了提高覆盖率,看起来可能是在浪费时间。
但显然,这种态度未能认识到单元测试提供的真正价值以及覆盖率强制执行的原因:没有良好单元测试的代码比有这些测试的代码更加脆弱且容易回归。因此,即使在压力之下,跳过它们也是一个真正糟糕的主意。
结果
这种模式往往导致千刀万剐。虽然你可能短期内不会感受到不良影响,但是过段时间后,你将没有任何真正可靠的单元测试可以依赖。
更糟糕的是,如果你仍然认为你只是在几个地方偷了懒,并且通常可以依赖你的测试,你可能会在心理上产生一种错误的安全感。基本上,你正在欺骗系统,很可能会发布质量低劣的代码。此外,你正在创造大量的技术债务,组织在某个时候必须支付它们。
更好的解决方案
解决这种反模式的方法很简单:构建良好的单元测试,并始终满足最低标准。你绝不能妥协最低要求,否则会导致代码质量和交付质量随时间恶化。
关于构建良好的单元测试,有很多指导意见,所以我们只重复几个基本要点:
-
单元测试应该测试代码中的单一功能
-
测试应该在代码之前编写
-
测试应该以便于重复执行的方式编写
-
测试应该独立于其他测试
-
测试不应依赖于组织数据,而应创建自己的测试数据,理想情况下使用测试数据工厂
-
测试应该简洁
-
应使用断言来检查是否得到了预期的结果
-
测试应该同时测试正面和负面情况
-
测试应该经常运行,最好是自动运行
-
测试应该易于理解和维护
除了传统的测试方法外,考虑加入现代测试框架,如 ApexMocks、Jest 和 Mocha。这些框架提供了强大的功能,用于单元测试和在各种编程环境中的模拟,促进了更高效、更有效的测试过程。熟悉这些工具可以显著提升你的测试策略,并提高代码质量。
这是一个罕见的反模式,通过遵循良好的实践就可以避免,因此一定要避免这种情况。
DevOps 集成的挑战
随着 Salesforce 平台的日益复杂化,组织推动更快的交付周期,许多团队发现自己在将现代 DevOps 实践融入其架构方法中时遇到困难。虽然 DevOps 的承诺非常吸引人——更快的发布、更高的质量和更可靠的部署——但现实往往未能达到这些期望,尤其是在 Salesforce 生态系统中,传统的开发模式可能与 DevOps 原则发生冲突。
考虑一下 FinTechCo,一家快速增长的金融科技公司,正在将 Salesforce 作为他们新的客户互动平台。像许多组织一样,他们以极大的热情开始了 DevOps 之旅,实施了所有正确的工具——Git 仓库、CI/CD 管道、自动化部署和用于开发的 Salesforce DX。它们的首席架构师 Sarah 精心设置了技术基础设施,相信这将改变他们的交付过程。
然而,随着项目的推进,团队发现,单单拥有 DevOps 工具还远远不够。开发人员仍然直接在沙盒中进行更改,只有在被提醒时才会提交到 Git。自动化测试套件依然稀缺,大多数测试仍然是手动执行的。由于不同团队成员遵循不同的流程,CI/CD 流水线经常中断。环境间的集成问题也日益严重——一个开发人员的临时组织中能正常工作的功能,在另一个开发人员的组织中就会失败,而那些通过所有自动化测试的变更,有时会在集成环境中导致功能故障。
这种情况在 Salesforce 生态系统中频繁发生,许多组织在实施 DevOps 工具时并没有充分接受所需的文化和架构变化。挑战不在于工具本身,而在于团队在开发和部署方式上所需的根本转变。团队常常发现自己处于短期内需要交付功能与长期内需要建立可持续交付实践之间的矛盾之中。
这种情况通常是逐渐恶化的。团队开始为紧急修复绕过 DevOps 流程,直接在更高级的环境中进行更改。环境状态变得不一致,跟踪变更也变得越来越困难。最初偶尔偏离流程的情况变成了常态,破坏了 DevOps 本应带来的好处。
在 FinTechCo 公司,这个问题在一次关键的部署过程中达到了高潮,该部署在计划的发布窗口期间反复失败。团队发现,各个环境中的不同组件有不同的版本,而且没有人能自信地说出哪个版本应该被视为正确的。发布不得不推迟,团队需要手动协调这些差异——这正是 DevOps 应该避免的情况。
根本原因通常在于将 DevOps 视为一种技术转型,而非架构和组织层面的转型。团队实施工具时,并未重新设计其开发流程和解决方案架构,以支持现代交付实践。这在理想流程与团队日常面临的实际现实之间制造了脱节。
在 Salesforce 中成功实现 DevOps 需要从根本上重新思考架构方法。这意味着要考虑如何打包和部署元数据,如何管理环境,如何自动化测试,以及如何跟踪和版本化变更。这意味着要做出支持持续交付的架构决策——例如,设计可独立部署的功能,并从一开始就在开发过程中构建自动化测试。
组织需要认识到,DevOps 不仅仅是加快部署——它还意味着在开发过程中构建质量和可靠性。这可能意味着做出架构上的权衡,例如在如何进行更改的灵活性上做出牺牲,以换取更可靠的部署。这也可能意味着重新设计功能,以支持部分部署,而不是要求全部或无部署。
前进的路径通常是从小做起,逐步扩展。成功的组织通常不会试图一夜之间完成全面转型,而是从一个团队或项目开始,允许实践逐渐成熟后再扩展。这种方法可以让团队在适当管理风险的同时学习和适应,也为展示成功提供了机会,从而为更广泛的采纳争取组织支持。
最重要的是,组织需要认识到,DevOps 转型是一段旅程,而非一个终点。它需要持续的改进承诺、从失败中学习的意愿,以及在团队发展新技能和习惯时的耐心。目标不是完美的 DevOps 实施,而是构建一种可持续的交付方法,平衡速度与可靠性。
成功来自于将架构决策与交付实践对齐,构建强大的自动化测试方法,围绕开发过程建立明确的治理框架,并投资于团队培训和文化变革。这意味着在标准化与灵活性之间做出艰难的选择,决定在哪些方面强制执行流程,在哪些方面允许偏差,以及如何平衡短期交付需求与长期可持续性。
通过将 DevOps 视为一种架构挑战,而不仅仅是工具挑战,组织可以避免表面化采用的常见陷阱,并建立真正支持其业务需求的交付实践。这需要仔细思考架构决策如何影响交付能力,以及交付实践如何影响架构选择。只有同时处理这两个方面,组织才能在其 Salesforce 实施中实现现代 DevOps 实践的真正好处。
了解要点
在本节中,我们将从具体的模式中提取一些更广泛的学习要点,帮助您在日常工作中作为 Salesforce 架构师使用,或者为准备 CTA 审查委员会考试做好准备。
在设计 Salesforce 解决方案时,您应该注意以下几点:
-
不要把所有的鸡蛋放在一个篮子里。在可能的情况下计划较小的发布,以降低风险并获得反馈。
-
面对将功能拆分成更小模块时可能出现的艰难决定。不要仅仅接受“从第一天开始必须包含所有内容”的说法。
-
总是在项目时间线的早期阶段就面对关键的架构权衡。这些问题通常不会随着时间推移变得更容易处理。
-
清楚和公开地沟通需要做出的权衡和各种选择的选项。试图取悦每个人并掩盖问题是灾难的开始。
-
不要让团队竞争或组织内部的信息孤岛来决定你的开发模型,无论是基于包的开发还是其他方式。
相反,确保你的开发模型与你追求的架构一致,并相应地组织组件和包。
-
集成现代化的 DevOps 实践,包括 CI/CD 流水线、自动化测试和版本控制,以提升交付质量。
-
在 Salesforce 中,单元测试是一个必须。不要因为压力而妥协。
-
编写高质量的单元测试将确保你拥有更高的代码质量和更少的回归问题。
在准备 CTA 审查委员会考试时,你应该注意以下事项:
-
面对复杂的大型场景时,更倾向于敏捷的、多版本发布的流程,而不是单一的大爆炸式发布。
-
然而,有些情况似乎更适合瀑布/大爆炸式的方法。这可能是理事会最佳实践和现实之间差异的一个领域。在当今快速发展的技术景观中,对于 CTAs 来说,理解 DevOps 和现代开发实践日益关键。这种知识不仅增强了开发与运维团队之间的协作,还使 CTAs 能够更好地支持组织实施敏捷方法、CI 和持续交付,从而推动创新和效率。
-
你应该非常清楚你所做出的权衡,并将其包含在你的理由中。
-
如果你不能做出合适的选择,几乎可以肯定会在问答环节中使你的解决方案崩溃。
-
基于包的开发是 Salesforce 项目的新兴开发模型,但这并不意味着它适合你的场景。如果适合,对一个良好的包结构有所了解将可能给你带来额外的赞誉。
-
知晓单元测试的最低限度以及它们何时适用,以便在被问及时能够作答。
-
同时,准备好回答关于什么是好的单元测试以及如何利用它们提升代码质量的一般性问题。
现在我们已经完成了本章的内容,并准备进入下一章。但首先,我们将总结我们的学习。
总结
在本章中,我们看到了开发生命周期如何受到不同抽象层次的反模式影响的示例。在最高层次上,你如何处理关键的权衡以及如何结构化你的发布对项目的潜在成功有着巨大影响。
然而,我们也看到技术元素,比如你如何组织你的包和是否编写了良好的单元测试,可以成为项目成功或失败的重要因素。这意味着你必须掌握所有这些层次,才能在这个领域成为成功的架构师。
对于许多架构师来说,相较于解决方案架构或硬核技术领域,这个领域可能被视为优先级较低。然而,对这些问题的忽视,可能会导致严重的项目失败,就像一个设计糟糕的解决方案一样容易。
话虽如此,我们现在将继续讨论最后一个领域——即沟通——并看看我们如何通过错误的沟通方式弄乱我们的 Salesforce 项目。
第八章:无误传达的沟通
这一章节在结论之前,将讨论围绕如何向不同受众传达架构的反模式,结合新的变更管理部分的见解。第一部分描述了与信息控制相关的反模式。接着,我们将探讨几个与沟通清晰度相关的反模式。第三部分,我们将分析一个特别针对你创建架构文档方式的反模式。最后,我们将讨论如何避免低估变更管理带来的挑战。正如我们一直在做的那样,我们将在章节结束时总结我们的关键收获。
本章将涵盖以下主要内容:
-
过度沟通在某些情况下可能比沟通不足更糟,特别是当与通才观众沟通时
-
为了避免做出决策而故意保持模糊,可能会对项目造成严重损害
-
人们似乎无法理解你所说的内容,往往是你需要解决的潜在问题的一个症状
-
为什么在记录技术规范时偏离标准几乎总是个坏主意
-
高效的变更管理实践对于成功的架构实现至关重要
完成本章节后,你将更好地理解技术沟通如何出错。更重要的是,你将掌握一系列具体的方法,帮助你避免常见的技术沟通陷阱。
沟通过多
本节将探讨在技术环境中沟通过多时会发生什么。为此,我们将首先探讨一个直接来自认知心理学的反模式:认知负荷。
认知负荷
认知负荷发生在所呈现的信息量变得过于庞大,以至于接收者难以承受,进而影响行动。
示例
LilacCo,全球领先的香薰蜡烛生产商,面临着严重的集成问题。它最近购买了 MuleSoft 平台,但使用率很低,大多数集成仍通过遗留中间件或点对点方式进行。
马丁是一位技术架构师,负责为 LilacCo 提出解决方案,以解决其面临的各种问题。这些问题包括许多集成的高延迟和慢速性能、糟糕的日志记录和监控、冗长且容易出错的开发周期,以及无法为几个关键遗留系统创建新集成。
马丁深思熟虑后得出结论:系统地迁移到 MuleSoft、实施更多事件驱动和异步集成、为老旧遗留系统编写一些关键适配器 API,并提供一个清晰的错误处理和日志记录模式供所有团队使用,将能解决问题。
这不是一个简单的修复方案。马丁制作了一份幻灯片和配套的报告,报告有数百页。材料中包含了许多技术图表,尽管他尽力进行了适当的总结,但他觉得这些材料只能简化到某个程度,否则就会失去所要表达的核心内容。
马丁向董事会展示了他的最新模型。不幸的是,提问的过程中,大家并没有真正理解他试图传达的信息。人们停留在一些相对不重要的细节上,无法抓住整体计划的核心。
他收到了反馈,指出他提出的模型过于复杂,需要找到一种更简化的方案。马丁感到非常恼火。他已经觉得自己提出的计划是最简化的了。各个元素彼此依赖,去除任何一个都会影响整体方案。
马丁试图与他最熟悉的董事会成员安排一对一的谈话,以便重新向他们阐述自己的关键观点。即便在这种更为亲密的环境中,马丁也发现很难传达自己的观点。关键内容似乎总是在沟通过程中丢失了。
接着,马丁被告知,一个新的集成平台供应商已经向董事会展示了他们的方案,大家对他们带来的新方法感到非常兴奋。马丁被要求提供反馈,他以详细而有深度的反驳形式给出了反馈。他总结道,尽管这个新平台确实有一些令人兴奋的功能,但并没有解决 LilacCo 面临的根本问题。
然而,马丁的反馈并没有起到太大作用。供应商提议进行一次免费的概念验证(POC),以增强他们软件能力的信任,董事会接受了这一提议。马丁没有被要求加入 POC 团队。
六周后,POC 以轰动性的成功告终。在这段时间里,团队能够展示出所需的所有功能。当然,这一切都只是试点阶段,且仍有许多复杂性,但董事会通过团队提供的演示感到非常有信心,认为新的软件将能提供所需的功能。
马丁询问是否可以查看 POC 的具体细节以及实际演示了哪些内容,但他的请求被默默忽视。随后,供应商提交了一份正式提案,提案被接受,新项目即将启动,以实施新的集成平台。
问题
认知负荷是心理学中的一个术语,指的是当我们的脑海中充满了过多信息或选择,以至于我们无法采取正常情况下应该采取的行动。在技术沟通中,通过在呈现架构选项时提供过多的信息来创造认知负荷,是一个非常常见的反模式。
这尤其发生在我们向非技术性受众传达信息时。对于技术性受众,我们可以在很大程度上依赖对图表格式、标准做法、良好实践、架构模式等的理解。
这可以减少此类受众的认知复杂性,尽管即使是经验丰富的从业者,复杂的架构也仍然可能很难理解。然而,当你试图向普通受众传达这些信息时,就不能依赖这些支持,因此,传达关键权衡和许多动态部分的任务可能非常困难。
提出的解决方案
认知过载本身并不是解决方案。导致认知过载的原因是认为你需要在展示中包含一定的细节,才能对受众公平或在主题上做到全面。
我个人认为,许多有才华的架构师会因为一种知识上的诚实感而陷入这种反模式。他们已经考虑了许多选择,并且对他们所提议的解决方案的利弊、正反观点都有所了解。
因此,他们会觉得在推荐自己选择的解决方案时,单纯地坚持一个高度简化的版本是不诚实的。在业务利益相关者是最终决策者的情况下——即使是在看似架构的决策中,这种情况也常常发生——几乎不可避免地会导致认知过载。
结果
显而易见的结果是沟通失败。你的主要建议和支持点在一堆受众无法处理的信息泥潭中迷失了。
这意味着你会失去受众的注意力,最终也失去了影响他们做出你希望的决策的能力。认知过载会导致无动于衷,因此最可能的结果是你所提议的内容无法产生任何效果,因为它没有被吸收。
这也为其他竞争者提供了机会来传递不同的信息,正如我们在示例中所看到的那样。在我们这个行业中,不幸的是,往往是最有利的营销信息推动了技术的采用,而不是从技术角度来看最优的选择。
更好的解决方案
有效的沟通不是几句话就能教会的。然而,你应该记住的是,简化复杂的信息使其足够容易理解对于受众来说非常重要。
一般来说,做以下几点:
-
根据受众及其理解程度来结构化信息。
-
除非你确实知道受众了解你所提议的基本内容,否则不要假设他们已经知道。
-
关注一个主要信息;不要在主信息旁边加入太多附加信息。
-
不要包括你在过程中考虑过的所有额外的考虑事项和选项。
-
使用图片、图形、表格等来帮助传递信息。
-
如果有人想深入了解某个领域,请准备好备份材料,但不要事先包含这些内容。
总体而言,你应该小心对观众提出要求。他们有很多事情要处理,有限的时间来参与你所说的内容。确保那段时间是有价值的。
以多种方式不清晰
在本节中,我们将探讨两种反模式,它们通过不同的方式探讨技术沟通中有意或无意的模糊性。我们首先探讨一种反模式,它试图出于战术目的利用模糊性,但最终造成了不利影响。
模糊的解决方案
模糊的解决方案提议通过模糊的语言和表现形式将冲突或不确定的决策隐藏起来,从而推迟作出决策的必要性。
示例
GrillCo,一家专注于户外烹饪设备的主要在线零售商,在其订单管理过程中面临重大问题。经常出现意外的缺货情况,交付时长和费用计算错误,且税务未能 consistently 正确应用。
这并非完全是 IT 问题,实际上,已经确定了许多流程改进的领域。然而,作为更广泛的订单管理转型的一部分,GrillCo 管理层还决定需要为订单管理过程引入一个新的软件平台。
然而,关于该选择哪种软件及如何实施,存在几种不同的意见。有些人支持将其集成到 Salesforce CRM 中,使用现成的订单管理模块。其他人则倾向于与一个专注于零售的供应商合作。最后,IT 部门则更倾向于自己实现该功能,使用他们已经建立的微服务架构。
Rainer 负责订单管理实施的技术项目管理。他试图促进不同提案之间的讨论,但问题在于似乎没有人知道该由谁来做出决策。
与此同时,还有许多其他较小的技术任务需要处理,因此 Rainer 专注于这些任务,将新的订单管理系统作为图表、演示和文档中的通用功能。他认为最终会找到解决方案,因此没有必要激起波澜。
然而,随着其他方面的转型推进,资深利益相关者们开始更加迫切地关注这个问题。由于他未能通过与人交谈达成共识,他提议进行正式的供应商选择,制定明确的标准,并将其作为决策过程。
然而,当他开始为选择过程做准备时,他做出了一个惊人的发现。两个团队分别根据自己对需求的理解,已经分别实施了完全不同的订单管理软件试点。
-
第一个问题出现在 IT 部门,几位开发人员已经开始开发新软件原型,展示他们的微服务平台有多么灵活和强大。尽管它具备一些不错的功能,但在 Rainer 的评估中,它并没有真正满足业务的实际需求。
-
第二个试点更进一步,已经在基于现有电商解决方案的数据的模拟订单场景中运行。它基于一个来自小型零售导向软件供应商的标准软件,该供应商正在大力投资进行必要的适应以满足 GrillCo 的需求。然而,Rainer 再次评估认为,距离这个解决方案真正适用还需要做很多工作。
一场戏剧性的会议随之而来,CIO 和 IT 团队站在一方,COO 和供应链团队站在另一方,双方各自支持其中一个解决方案。会议以僵局结束,决定引入一名独立顾问来评估这两个方案并提出建议。
GrillCo 请来了一位在订单管理解决方案领域享有盛誉并备受尊敬的专家,他花了几周时间审查试点软件。专家的评估令人堪忧。
两个试点方案都没有提供 GrillCo 所需的能力水平。他建议放弃这两个方案,而是重新回到市场寻找更合适的解决方案。Rainer 对技术供应商选择过程的演示进行了修改,并开始着手工作。
问题
一些决策是很难做出的。这可能是因为政治原因——也就是说,不想通过一个不受强大利益相关者或团队喜欢的决策去得罪他们。也可能是因为缺少信息,这些信息只有在过程的后期才能出现,因此现在做决策变得更加复杂。
避免做出有争议决策的艺术,即通过推迟决策来回避问题,是模糊解决方案反模式所涉及的核心问题。虽然花时间收集更多具体信息以显著提高决策质量是合理的,但如果过度推迟决策,无论是出于政治原因还是对决策错误的普遍恐惧,这都会成为反模式。
提议的解决方案
模糊解决方案反模式提出通过将困难决策隐藏在模糊性背后以应对问题。这可以通过诸如能力模型、将决策推迟到独立的决策过程,或者仅仅列出多个备选方案(例如,在图表和文档中)来轻松实现。
在很多情况下,这可能是一个非常有吸引力的选项;例如,你可能知道某些高级利益相关者偏爱某种方法,而你已经确定这种方法不可行。通过掩盖模糊性,你可能希望推迟直到项目进展到无法改变的阶段,再让这一点变得明朗。
你也许还在悄悄地希望,随着项目的进展和更多信息的出现,决策会变得更加容易;要么某些选项将无法激活,要么答案会变得显而易见。
也就是说,你希望通过无限期推迟,避免处理一个充满高度不确定性或冲突的情况。这是非常人类的行为,但不幸的是,这是一个糟糕的架构实践。
结果
当然,最终你必须面对你一直回避的问题。如果你运气好,决策现在会变得容易,因为大部分选择已经被排除。但这其实并不是好事。
很少会出现可以最快实现的选项也是最优解决方案的情况。因此,你拖延处理问题几乎总会导致比早点做出决策更糟糕的解决方案。
在决策不必要时保持选项开放是有其道理的,但如果你保持得太久,会对解决方案产生不利影响。而且,在关键的架构决策上保持选项开放过久通常是有问题的。
如果你运气不好,决策依然不会明显;你仍然必须面对不确定性和冲突,但现在它们会因为你等待所带来的额外时间压力而加剧。这对于你个人和项目来说,都是一个更糟糕的结果。
更好的解决方案
首先,不要把决策推迟到最后期限过期。如果你没有必要的信息,制定一个清晰的计划,设定一个明确的获取信息的最后期限。然后,规划一个决策过程,无论其他情况如何,都将在那个时间点做出决策。
如果决策在政治上不受欢迎,试着让你在组织内的支持者在你做出并传达决策时站在你这边。总有风险因为政治原因做出错误的决策。
然而,即使是错误的决策也总比在某个时刻没有做出决策要好。至少你会有所进展,并且能够更早开始减轻错误决策的后果。
当需要做出决策时,在文档和演示中明确标出,以便利益相关者意识到决策即将做出。即使可以模糊处理,也不要躲在模糊的背后。
如果你无法通过共识做出决策,看看是否能够让利益相关者同意一个正式的决策过程。通常,人们发现自己更容易接受一个正式过程的结果,而不是某个人的个人意见。
土拨鼠日
土拨鼠日反模式发生在即使经过多次反复解释后,人们仍然不断地问同样的问题。
示例
Rolf 正在为 MediCo 领导一个本地 Salesforce 实施项目,MediCo 是一家医疗器械制造商,业务遍及大部分欧洲市场。Salesforce 实施方案由巴黎总部的员工定义,计划按原样推广到其他国家的子公司。
Rolf 被赋予了将该系统推广到德国子公司的责任。德国分公司是 MediCo 的新业务,去年才被收购。因此,它还没有完全融入 MediCo 的标准流程或 IT 基础设施。Salesforce 实施被视为改进这一状况的一种方式。
当他向德国团队展示法国和其他国家现有的 Salesforce 实施方案时,他遭遇了一连串的问题。团队想深入探讨一些非常具体的流程问题,Rolf 无法回答这些问题,因为他不了解德国业务的详细情况。
他收集了大量问题,并尽力以书面形式回答这些问题。然而,他很快感觉自己像是在玩打地鼠游戏。每当他似乎回答了一个问题,另一个相似但略有不同的问题就会从其他员工那里冒出来。
Rolf 开始整理所有问题,并准备了清晰简明的答案。由于困惑程度很高,他无法在实施过程中取得实质性进展,因此决定再尝试一次。
他再次召集德国团队,向团队成员介绍新 Salesforce 系统的要点,并尽可能系统地解答到目前为止提出的所有问题。然而,他再次遇到了更多困惑的目光和那些他认为已经回答过一遍的问题。
感到沮丧,几乎准备放弃时,Rolf 决定打电话给公司的一位老导师,他知道这位导师了解德国子公司现状。她告诉 Rolf,问题可能根本不在于他的沟通技巧。
德国子公司员工更喜欢按自己的方式做事,并且反感总部的强加。Salesforce 只是表达这种反对的借口。即使这个系统是自切面包以来最完美的东西,德国团队依然会原则性地反对它。
在掌握了新知识后,Rolf 决定制定一个新计划。他大胆决定公开问题。他又做了一次演示,明确表示自己知道反对的真正原因,并且他并不打算解决所有的顾虑,而是邀请团队参与其中,看看是否能找到让新系统“自我”的方法。
虽然系统本身已经是现状,并且总部不打算批准许多本地的变化,但德国运营如何决定采用并将其融入到自身流程中仍然悬而未决。罗尔夫将实施过程开放给德国团队,并欢迎他们提出如何最好使用新 CRM 的建议。渐渐地,部分人开始参与,虽然时间表需要调整几次,但最终,采用是成功的。
问题
有时,人们似乎根本不理解你在说什么。无论你多么努力地解释一个观点,或是解释了多少遍,似乎都无法让你的观点传达出去。
“土拨鼠日”反模式,得名于同名电影,描述了这种情况——你似乎无法把某个信息传达足够多次,以至于它产生任何影响。
这意味着你觉得自己一直在往墙上撞头,却没有留下丝毫痕迹。通常,这是因为你并没有真正处理正在发生的根本问题。
提出的解决方案
当你陷入“土拨鼠日”反模式时,你通过大量重复自己来回应那些似乎永无止境的、关于相同问题的提问。你可能用不同的语言或不同的方式重复自己,但你始终是在重申相同的信息。
有时,它让生活感觉像是无休止的重复,仿佛你根本没有任何进展。你开始质疑自己的理智,也开始质疑那些持续质疑你的人们的理智。
这通常是因为你并没有真正关注问题出现的根本原因。通常,当同样的人问你同样的问题超过几次时,某种形式的抵抗在发挥作用。
也许,人们觉得一个不好的决策是在他们不知情的情况下做出的,而他们正在试图拆解这个决策。也许他们担心你提出的方向会给他们带来不好的个人后果。
人们可能会有许多理由抵制你的信息,而这些理由与信息的呈现方式或沟通方式无关。在这种情况下,问题变得更多的是关于变更管理,而不是沟通。如果你是一个实践中的架构师,意识到这一现象并能抓住它是一个关键的软技能。
结果
“土拨鼠日”反模式的结果在个人层面和项目层面都会带来显著的负面影响:
-
首先,你无法通过你尝试传达的信息达到任何目标,而这些信息通常需要被你所沟通的受众接受。
-
这会让你感到沮丧,因为你不断思考如何更好地与受众沟通你的信息,但却始终失败。
-
它让你沟通的对象感到沮丧,因为他们觉得你没有倾听他们真正的关切。
-
同时,项目通常会停滞不前,关键领域的进展可能因沟通障碍而被阻碍。
总体而言,这种反模式可能对你的项目和你个人造成严重的压力。
更好的解决方案
第一步是认识到问题的存在,并且要明白问题不在于你找到一种更好的方式来表达相同的内容。
一般来说,你应该做以下几点:
-
一旦你开始听到类似的问题不断以略微不同的方式重复出现,暂停一下并退后一步。
-
与利益相关者和盟友合作,弄清楚你所面临的抵触背后真正的原因。
-
如果你发现有些问题背后的原因不仅仅是理解上的困难,积极寻找一种替代方法,而不妥协你的核心目标。
-
然后,应用良好的变革管理实践,帮助推动所需的转型。
你不能总是满足人们的所有需求,但你可以找到一种方法来承认他们的真实关切,并对他们的反馈保持开放态度。
画出过于创意的图表
本节探讨了当你尝试用过度创意来传达技术信息,而不是依赖于社区内的既定实践时,会发生什么情况。我们通过查看非标准文档的反模式来阐述这一点。
非标准文档
非标准文档 指的是一种反模式,其中团队以独特的格式编写技术文档,而不是依赖标准的做法。
示例
SafeCo 是一家为设施管理提供安全解决方案的领先供应商,目前处于新的 Salesforce 实施的愿景规划阶段。它正在尝试通过技术彻底转型其业务,并已将 Salesforce 作为解决方案的一部分。
SafeCo 的战略经理秦正在主导愿景规划工作,并得到一家在设计思维方面有独特优势的外部咨询公司的支持。他们举办了一系列极具吸引力的研讨会,最终得出了新战略技术平台的愿景和关键需求。
研讨会的成果以大量富有表现力的图画和临时图表形式记录下来,许多图表结合了流程设计、数据模型和用户体验原型的元素。参与研讨会的高级管理人员对成果非常满意,甚至决定将这些成果包含在将发送给潜在供应商的提案请求(RFP)材料中。
SafeCo 从三家供应商中筛选出符合要求的公司,这些公司在其 RFP 响应中明确提到了研讨会的成果。经过最终展示后,SafeCo 选择了全球最大的 Salesforce 合作伙伴之一,根据研讨会成果中所陈述的要求执行实施。
然而,一旦供应商动员起来并且项目进入正式的探索阶段,问题就变得明显了。SafeCo 认为在提供的文档中显而易见的许多功能和需求,并没有包含在供应商的估算中。
SafeCo 向供应商施压,指出 RFP 中提供的文档。然而,供应商对文档的解释提出异议,且证明无法明确展示争议中的许多要点的意图。
一度,SafeCo 考虑重新寻找供应商,但该供应商是唯一一个能够在其所需时间表内提供所需技能组合的公司。高级管理层不愿在项目截止日期上妥协,因此重新进行采购似乎不可行。
因此,唯一需要做的就是就供应商未包含的附加功能进行协商。在一番争执后,达成了一个妥协方案,最终没有一方完全满意。
项目的价格上涨,但没有达到供应商期望的程度。此外,供应商坚持要求对项目中将要实现的需求进行更正式的文档记录,这削弱了原计划中的一些灵活性。达成妥协后,项目终于可以启动。
问题
非标准文档反模式所解决的问题是如何最好地传达复杂的需求、架构、设计以及技术系统的一般期望。这涉及到如何在面对非专业受众时与技术概念进行沟通的问题。
通常,在研讨会环境中,高度视觉化且具有吸引力的材料会表现良好,比如定义新系统的愿景或如何利用像 Salesforce 这样的企业软件平台来获得战略优势。在这种情况下,你需要使用与你的受众产生共鸣的格式,建立共同理解。
然而,当沟通需要精准和技术正确时,这种方法可能会让你陷入麻烦。
提出的解决方案
非标准文档提出,最佳的文档是那些对参与编写的关键利益相关者最清晰的文档,无论它可能是什么。这是一个极具诱惑力的立场,因为在许多情况下确实如此。
例如,前述说法在以下情况下成立:
-
如果你正在尝试就某个愿景或项目达成一致
-
如果你正在尝试在组织内就某个话题促进相互理解
-
如果你正在尝试提高对某个问题的普遍认识
在所有这些情况下,完美的文档是能够为受众提供良好效果的文档。然而,当涉及到技术规格、架构和设计时,这不再适用。
结果
普通语言容忍很多模糊性,绝大多数概念的视觉表示也如此。然而,模糊性是技术规格的死敌。
为了减少在编写技术规格时的模糊性,无论是需求、架构、设计,还是一般情况下,我们使用了许多工具。以下是其中的一些:
-
使用去除日常客套话、始终追求清晰的语言。
-
指代具有明确定义的共同理解的技术标准。
-
指代在我们技术社区中常见的模式,并且这些模式很可能被我们交流的接收者理解。
-
指代在我们技术社区中常见的约定或做事方式,并且这些方式很可能被我们交流的接收者理解。
-
使用标准格式的文档,这些格式有明确的结构,能够满足我们技术社区成员的常见关注点。
-
使用我们技术社区成员都能理解的标准格式图表。
所有这些元素有助于减少技术规格中的模糊性,尽管即使在所有这些因素的作用下,仍然存在大量误解的空间,任何有经验的架构师都会告诉你这一点。
这就是为什么有标准的方式,如用户故事或传统的需求规格说明书,用来传达需求,还有标准的图表类型,如系统景观、流程图和数据模型,用来传达技术设计。
如果偏离这些标准,你会增加总的模糊性,这会引发沟通问题,而这种问题可能会很昂贵,因为你的供应商或员工无法准确理解需要做什么。即使在要求和设计明确的情况下,沟通也已经够麻烦的了——不要再增加麻烦。
更好的解决方案。
根据上一节的描述,猜测你应该做什么可能并不难。我们列出以下几点供参考:
-
编写你的技术规格时,要减少模糊性。最重要的是要追求清晰。
-
在创建需要共享的技术规格时,尽可能依赖标准的图表类型、材料呈现方式、命名方式等。
-
遵循在你的技术社区中常见的模式和约定。对于 Salesforce 专业人员来说,这通常意味着遵循 Salesforce 本身使用的方法。
通过这种方式,你可以清晰地与供应商和你雇佣的新技术人员沟通,避免可避免的模糊部分。
记住——与大多数沟通不同,在技术沟通中,你的目标是传达一个准确的观点。这是一个非常难做到的事情,事实证明如此。
对于 Salesforce,具体来说,Salesforce Architects 网站(architect.salesforce.com/diagrams
)将帮助你全面了解 Salesforce 目前提供给所有架构师的资源,以避免在记录和展示 Salesforce 解决方案时重新发明轮子。对于有兴趣准备 CTA 考试的读者,这是一个值得记住的好地方。
错误管理变革
在本节中,我们讨论了错误管理变革。错误管理变革可能导致组织遭遇重大挫折,通常是由于沟通不足、培训不充分,或未能将利益相关者纳入过程。常见的陷阱包括低估变革阻力、未能明确目标和期望,以及忽视结构化变革管理计划的重要性。这些错误会导致员工困惑、士气下降,并最终阻碍组织适应能力,导致资源浪费和错失成长机会。领导者必须意识到这些挑战,并实施促进平稳过渡的策略,同时培养一种拥抱变革的文化。
忽视利益相关者的关注
忽视利益相关者的关注是一种反模式,实施团队在推进 Salesforce 开发和定制时忽视或轻视关键利益相关者的意见。虽然这种做法往往源于有效的技术考虑,但最终导致的解决方案未能满足业务需求。
示例
MedSupply 是一家成长中的医疗供应分销商,决定通过实施 Salesforce 来现代化他们的销售运营。公司原有的 CRM 系统已经显得有些陈旧,用户多年来一直抱怨其笨拙的界面和有限的功能。由高级开发人员马库斯领导的 IT 团队对构建一个现代且技术先进的系统感到兴奋。
销售团队有一个复杂的报价到订单流程,涉及多个审批和特定的合规检查。销售运营经理莎拉曾多次尝试与马库斯的团队安排会议,逐步了解他们当前的流程,并详细解释他们的需求。然而,马库斯对在 Salesforce 中复制过于复杂的传统流程有合理的担忧。从他的角度来看,许多现有的流程步骤似乎是旧系统限制的产物,而非真正的业务需求。
在最初的需求收集阶段,莎拉就某些合规检查表达了担忧,这些检查需要在报价发送给客户之前完成。她解释说,当前的流程需要交叉参考多个数据库,以确保他们不会将受限的医疗用品销售给未经授权的设施。马库斯认为,Salesforce 的验证规则和审批流程可以显著简化这些检查,消除他认为当前流程中的冗余步骤。
开发团队利用 Salesforce 的标准报价功能并结合一些定制的审批流程,创建了他们认为优雅的解决方案。他们为能够充分利用平台功能并将定制化保持在最低限度而感到自豪,因为这将使系统更容易维护和升级。当莎拉指出该解决方案没有考虑到他们需要维护所有合规检查的详细审计记录时,马库斯坚称 Salesforce 的标准历史跟踪足够用,并反对建立需要大量维护的定制审计功能。
在用户验收测试(UAT)期间,技术优雅性与业务需求之间的固有矛盾显现出来。销售代表认为新流程繁琐,因为它与他们的工作流程不匹配,尽管他们的一些抱怨源于不熟悉 Salesforce 的界面模式。合规团队发现他们无法在系统中执行所有必要的检查。莎拉在项目会议中提出了这些问题,但 IT 团队看到他们解决方案的优雅性,认为这些问题大多是“对变革的抵触”或“用户培训问题”。
系统按计划上线,尽管销售和合规团队仍有未解决的担忧。在第一周内,出现了两个重大问题。首先,由于系统强制销售代表进入一个与他们需求不匹配的工作流程,导致他们处理报价的时间翻倍。其次,更严重的是,合规团队发现一些报价在未进行完整的监管检查的情况下发送给了客户,因为系统没有强制执行所有必要的验证。
在一次险些将受限物资运送到未经授权的设施的事件后,高层管理介入。公司不得不回滚到旧系统,同时重新评估他们的方案。这个项目花费了超过 150 万美元,但并没有带来任何销售操作上的改进。
问题
忽视利益相关者的意见通常发生在实施团队在 Salesforce 项目中忽视或最小化来自关键利益相关者的有效意见时。然而,这种反模式的根源比简单的忽视更为复杂——它通常源自真正的技术考虑,以及平衡相互竞争的项目目标的挑战。
技术团队通常有充分的理由希望紧密遵循 Salesforce 的标准功能。他们明白,过度定制化的解决方案更难维护,在更新时更容易出现故障,并且从长远来看成本更高。他们常常亲眼见证过当组织通过定制将自己逼入死角,创造出实际上无法维护的系统时所出现的问题。
与此同时,利益相关者通常有合理的需求,这些需求与平台标准相抵触。这些需求可能源自法规要求、既定的业务流程或真正的效率问题。挑战在于区分那些可以通过培训和变革管理来解决的利益相关者偏好与那些真正需要技术适配的基本需求。
这种反模式特别危险,因为双方通常都认为自己在为组织做出正确的长期决策。技术团队推动标准化和可维护性,而业务利益相关者则倡导功能性和熟悉性。如果没有适当的调解,这种紧张关系往往会偏向技术考虑,原因仅仅是技术团队对实施过程有更直接的控制。
提出解决方案
这种反模式表现为一种高效的 Salesforce 实施方法,承诺通过依赖平台的标准功能和实施团队的专业知识,快速交付结果。这个解决方案看起来很有吸引力,因为它解决了关于可维护性和可持续性的非常现实的技术问题。
提出的解决方案通常强调平台最佳实践和标准功能,将利益相关者关于流程适配的关注点视为变革管理问题,而非技术需求。这种方法并非完全错误——许多传统业务流程在迁移到新平台时可以并且应该简化。然而,这种方法往往过于偏向平台纯粹性,忽视了在此过程中有效的业务需求。
这种方法看起来具有吸引力,因为它承诺显著的好处:更快的实施时间、较低的开发成本和更容易的维护。这些好处是实实在在的,但它们需要与强制将业务流程强行适应平台标准所带来的成本相权衡,尤其是在这些标准无法完全满足业务需求的情况下。
结果
当忽视利益相关者的关注时,结果通常对技术实施和业务运营都产生负面影响。用户采纳不仅仅因为对变革的抗拒,更因为系统确实未能支持关键的业务流程。一些用户抱怨可能确实反映了变革管理问题,但其他抱怨则凸显了功能上的实际缺陷,妨碍了业务运营。
技术团队关于干净、可维护实现的愿景常常证明是虚幻的。随着业务需求的不断强化,系统通常会积累一层匆忙的定制和变通,这些问题比经过良好规划的定制解决方案更加混乱。这些紧急修复往往比故意设计的定制解决方案更严重地违反了平台最佳实践。
财务影响不仅仅局限于即时项目成本。虽然定制开发很昂贵,但由于系统不合适所带来的业务中断成本往往更高。然而,同样也存在这样一种情况:过度定制的系统可能变成昂贵的维护负担,几年后可能需要完全替换。
组织影响通常会导致“技术最佳实践”和“业务需求”之间的虚假二分法,这种情况可能会对未来的项目造成毒害。技术团队变得越来越确信业务用户提出了不合理的要求,而业务用户则变得越来越确信技术团队不理解或不关心他们的需求。
更好的解决方案
避免这种反模式需要用更细致的方法替代技术卓越与业务需求之间的虚假二分法,这种方法需要认识到技术和业务的约束都是系统设计中必不可少的考虑因素。
有效的利益相关者沟通并不意味着毫无批判地接受所有利益相关者的要求,而是要创建关于业务需求和技术约束的真正对话。技术团队应解释各种方法的长期维护影响,而业务相关方应澄清哪些需求是真正的业务需求,哪些是基于当前流程的偏好。
技术方法需要在平台最佳实践和业务需求之间取得平衡。团队不应从平台功能或业务流程出发,而是应从理解核心业务目标和约束开始。解决方案应该慎重地将平台能力与业务需求相结合,在真正增加价值的地方合理使用定制开发。
需求收集不仅仅是记录当前的流程或平台功能。团队需要理解为何流程以当前形式存在,区分历史遗留问题和真正的业务需求。这种理解有助于识别出在哪些情况下流程的改变可能比技术定制更好,同时也能凸显出哪些地方确实需要定制。
实施应由业务价值和技术可持续性指导,而非平台的纯粹性或流程的保存。团队应愿意在标准功能无法满足关键需求时进行定制,但也应该在标准功能提供更简洁的解决方案时,愿意对流程变更提出挑战。
有效的治理意味着创建一个平衡的决策过程,既考虑技术问题,也考虑业务问题。这要求技术领导者理解业务影响,业务领导者理解技术影响。定期的检查点应评估技术质量和业务适配性,并在这些目标发生冲突时设有明确的升级路径。
通过遵循这些更好的解决方案,组织可以创建平衡技术卓越与业务需求的 Salesforce 实施方案。关键在于认识到技术最佳实践和业务需求都代表着必须认真平衡的实际约束,而不是相互竞争的优先事项,其中一个必须胜过另一个。
低估变更的影响
低估变更的影响是一个反模式,实施团队未能充分认识和规划 Salesforce 组织中的修改可能对整个生态系统产生的连锁效应,导致广泛的中断和技术债务。
示例
全球制造公司(GMC)已将 Salesforce 作为其主要 CRM 平台使用了五年。随着时间推移,其实施系统逐步扩展,包括 Sales Cloud、Service Cloud 以及支持各种业务流程的多个自定义对象。该系统服务于超过 2000 名销售、客户服务和运营团队的用户。
Sarah,一位资深 Salesforce 管理员,收到了销售副总裁看似简单的请求。销售团队希望修改机会阶段字段,以更好地与他们演变后的销售流程对接。此更改涉及添加两个新阶段,并将现有阶段拆分为两个更细化的阶段。
请求看起来足够简单——这只是更新一个已经稳定多年的选择列表字段。Sarah 的初步评估表明,这只是一个小改动,应该能在一天之内实施。她计划在一个相对安静的时间段直接在生产环境中进行更改,认为由于范围有限,没必要进行广泛的测试或沟通。
Sarah 没有充分考虑的是机会阶段字段在 GMC 的 Salesforce 生态系统中是如何深深嵌入的。该字段驱动了许多自动化流程,包括基于阶段变化触发的多个审批工作流、财务使用的复杂预测规则、与其 ERP 系统的集成以启动订单处理、整个组织使用的几十个报告和仪表板、依赖标准机会阶段的多个第三方应用程序,以及基于阶段进展的定制佣金计算。
Sarah 在一个星期二早晨实施了变更。到星期三,问题开始浮现。财务团队发现他们的预测报告显示了不正确的数字,因为新的阶段无法映射到他们已建立的预测类别。财务副总裁非常生气,因为他们正处于季度计划的中期。
销售运营团队发现他们的佣金计算失败,因为逻辑没有考虑到新的阶段。几个销售代表担心这将如何影响他们的佣金支付。他们与 ERP 系统的集成开始抛出错误,因为它未被更新以处理新的阶段值,导致订单在处理中卡住。组织内多个仪表盘显示空白值或不正确的数据,导致大量帮助台工单的涌入。他们使用的第三方销售分析工具停止了正确同步数据,破坏了几个高管仪表盘。
最初看似简单的变更已演变成一个影响多个部门的危机。Sarah 和她的团队接下来的两周都在忙着解决这些问题,需要与财务部门紧急开会重新设计预测规则,紧急更新佣金计算逻辑,与集成团队协调修改 ERP 接口,重建多个报告和仪表盘,并向用户多次沟通问题及解决时间表。此事件促使 IT 治理进行正式审查,GMC 意识到他们需要为 Salesforce 组织建立更强大的变更管理流程。
问题
低估变更影响的反模式发生在团队未能认识到现代 Salesforce 实现之间的相互关联性时。这个反模式尤其危险,因为它通常始于看似简单且局部的变更,但却具有深远的后果。
问题表现在未能映射现代 Salesforce 组织中复杂生态系统的依赖关系,在这些组织中,看似孤立的组件往往通过自动化、集成和报告关系紧密相连。团队通常仅进行提案变更的表面级审查,错过了关键的依赖关系和下游影响。测试往往只关注直接变更的功能,而不是整个受影响的系统和流程链条。团队可能未能识别出所有受变更影响的群体,导致沟通和准备不足。
这种反模式在成熟的 Salesforce 实施中尤为常见,因为原始架构师和开发人员可能已经离开,带走了有关系统依赖关系和设计决策的关键信息。现代 Salesforce 实施的复杂性意味着即使是小的更改也可能在整个组织中产生连锁反应,影响流程、集成和报告,且这些影响可能并不立即显现。
提议的解决方案
导致这种反模式的表面解决方案是将 Salesforce 更改视为孤立的技术修改,可以迅速和直接地实施。这种方法看似有吸引力,因为它承诺能更快地交付请求的更改,减少开销和官僚主义,最小化资源需求,简化变更过程,并减少初期的规划工作。
团队通常通过指出 Salesforce 强大的平台能力和内建的保护机制来为这种方法辩解。他们可能会争辩说,由于 Salesforce 自动处理了许多依赖关系,广泛的影响分析并非必要。在那些有压力要求快速交付、更有资源约束、文档不完整、系统未经严格治理自然生长,或者团队过去曾成功进行类似更改而没有问题的组织中,这种心态尤其具有诱惑力。
这种方法的诱惑在于其表面上的高效性和它为要求更改的利益相关者提供的即时满足感。它看起来像是对业务需求的务实回应,尤其是在团队面临快速交付压力或资源有限时。
结果
当团队陷入低估变更影响的反模式时,后果可能是严重且深远的。即刻的技术问题通常表现为集成和自动化过程中的破坏性更改、数据完整性问题、性能下降、批处理作业和自动化失败以及错误的计算和工作流程。
业务影响可能是毁灭性的,涉及关键业务流程的中断、不准确的报告和预测、由错误计算引发的财务问题、多个部门的生产力丧失以及用户对系统的信任下降。这些即时问题通常会引发长期后果,包括因匆忙修复而积累的技术债务、系统文档的退化、对未来更改的抵触情绪、增加的维护成本以及系统可靠性的下降。
反模式通常会导致恶性循环,其中紧急修复引入额外的计划外更改,可能会导致进一步的问题,进而需要更多匆忙的解决方案。这可能导致每次修复都会引入新问题,系统的整体稳定性和可靠性逐渐下降。
更好的解决方案
为了避免低估变更影响的反模式,组织应当实施一个全面的变更管理方法,从根本上转变变更的评估和实施方式。关键在于将变更管理从反应式转变为主动式。
强大的影响分析流程构成了更好实践的基础。组织需要保持详细的系统文档和依赖关系图,尽可能使用自动化工具识别字段和对象依赖关系。定期的系统审计有助于了解集成点,而全面的测试清单确保在变更实施过程中没有遗漏任何部分。
变更过程本身需要精心结构化。这意味着对于重大修改要实施正式的变更咨询委员会,确立明确的标准来区分重大和次要变更,并要求在批准变更前进行文档化的影响评估。标准化的变更请求模板应当促使考虑依赖关系和潜在的系统影响。
测试策略在避免这种反模式中尤为关键。组织需要维护多个沙箱环境以用于不同的测试目的,并在可能的情况下实施自动化回归测试。对所有受影响的过程进行端到端测试,包括集成测试,应成为任何重大更改的标准程序。
利益相关者管理在成功的变更实施中扮演着至关重要的角色。组织应当清楚了解哪些小组受不同系统组件的影响,并建立清晰的沟通协议来处理系统变更。用户反馈渠道以及可见的变更日历有助于保持透明度和信任。
风险缓解策略需要在变更过程中内建。这包括为所有重大更改制定回滚计划,尽可能分阶段实施更改,在适当的业务窗口期安排更改,并保持对关键问题的应急响应程序。
知识管理在防止这种反模式中变得至关重要。组织需要记录所有系统依赖关系和集成点,保持更新的流程图和系统架构图,并创建一个包含以前更改及其影响的知识库。定期对团队成员进行系统架构和依赖关系的培训,有助于保持对系统复杂性的认知。
需要记住的关键原则是,适当规划和影响分析的成本几乎总是低于从糟糕的变更中恢复的成本。在 Salesforce 生态系统中,变更可能会产生广泛的影响,因此必须保持对系统复杂性及即使是看似微小的修改也可能产生的影响的高度敬畏。避免这种反模式的成功并非来自避免变更,而是来自以适当的谨慎态度和对其潜在影响的尊重来处理变更。
现在,已经讨论了本章的模式,让我们继续讨论关键的要点。
了解关键要点
在这一部分,我们将从具体的模式中进行抽象,转而尝试提取你作为 Salesforce 架构师或在准备 CTA 评审委员会时可以在日常工作中使用的更广泛的学习要点。
在架构 Salesforce 解决方案时,你应该注意以下几点:
-
在向业务利益相关者呈现你的架构时,不要包含过多的信息。
-
相反,专注于你的主要信息,并仅包含必要的支持性信息。
-
不要因为没有包含你在提出解决方案时考虑的所有额外因素而感到不好。如果有人需要更多的细节,他们可以在事后询问。
-
不要将决定推迟到做决定已经没有意义的时刻,即使做出决定很困难。
-
如果某个决定具有争议或政治敏感性,推迟到正式的决策流程可以提供前进的途径。
-
如果你遇到让你的听众似乎无法理解你的情况,你应该开始怀疑是否存在一些潜在的抗拒来源。
-
在这种情况下,你很可能需要专注于该情况的变更管理方面,才能取得真正的进展。
-
当需要为技术受众准备文档时,无论是外部受众还是你的内部技术团队,你应该严格遵循你所在技术社区内的公认实践。
-
对于 Salesforce 专业人士而言,这通常意味着采用 Salesforce 本身传播的最佳实践。
在准备 CTA 评审委员会时,你应该注意以下几点:
-
在呈现你的解决方案时,要简洁明了。评审官是经验丰富的架构师,因此你可以依赖大量的背景知识。
-
包括你推荐方案的明确理由,但不要过多纠结于备选方案。
-
不要包含不必要的额外考虑,专注于你的主要观点。如果有人想要验证你的思路,他们会在问答环节中提出来。
-
模棱两可对任何人都没有好处。不要呈现不清晰或没有做出重要架构决策的解决方案。
-
法官们在发现你表达不清楚的地方方面非常有经验,因此,如果你不确定正确的决定是什么,你也应该做出一个决定。
-
如果评委多次提出相同或几乎相同的问题,他们很可能在暗示你的解决方案中存在某个弱点,你可能需要立即重新考虑。
-
使用之前成功的 CTA 候选人所采用的标准图表和展示格式。
-
在模拟考试中反复以相同的方式做事,以培养熟练度和速度。
我们现在已经涵盖了本章的内容,可以继续前进。然而,在此之前,我们将总结一下我们的学习。
总结
在本章中,我们看到沟通如何严重影响我们项目的结果。你可以拥有世界上最好的架构,但如果你未能正确传达它,或者未能处理它在目标受众中引发的阻力,它仍然可能无法取得任何进展。
这对一些更理性派的架构师来说可能是令人沮丧的。事实和实质应该是决定因素才对。但不幸的是,在大多数组织中,更好的沟通技巧往往比更强的技术架构技能在完成任务上更有优势。
好消息是,沟通技巧和所有技能一样,都是可以学习的。作为架构师,想要取得更大的成功,沟通方式并没有特别困难的地方——只是需要一些练习。
我们现在已经涵盖了本书的所有内容,可以进入结论部分,在这里我们将总结我们一起走过的旅程,并展望接下来的方向。
第九章:结论
本结论提供了本书内容的概述,包括前几章的核心收获。接着,解释了如何在自己的工作中使用反模式方法和视角,以提高架构技能。最后,它还提供了如何在这一方向上进一步发展的指引。
本章我们将讨论以下几个主要内容:
-
本书的关键内容——特别是我们将讨论一些反模式的根本原因
-
如何在自己的建筑实践中使用反模式来提高你创建的架构质量
-
如何进一步理解反模式并发展你自己的架构技能
完成本章后,你将能够较好地理解如何进一步发展自己的架构能力,并知道如何将基于反模式的思维整合到你作为架构师的日常实践中。
总结关键内容
本书涵盖了七个不同架构领域的几十种反模式。然而,细心的读者会发现,许多问题及其建议的解决方案在多个看似不同的领域中是相似的。
这表明,从更深层次看,反模式有着相似的根本原因,通常源于更大的组织因素甚至心理因素。我们来看看这些重复出现的原因:
-
一厢情愿的想法:一些反模式基于某种形式的一厢情愿的想法——也就是说,不愿面对眼前的技术现实。在“Project Pieism”中,它表现为无法面对取舍和不确定性;在“Golden Hammer”中,是过度乐观地相信单一工具;在“Unplanned Growth”中,是认为可以在以后找到解决方案。这也扩展到了新模式,比如AI 架构与常规架构相同,其中团队未能意识到 AI 所面临的独特挑战。在技术架构中,始终要警惕过度乐观的情绪。
-
系统性盲点:许多反模式源于无法看到整个系统,专注于局部解决方案而忽视整体架构。这包括反模式,如孤立的实体、忽视生态系统、用包创建孤岛和事件地狱。现代 Salesforce 实现的复杂性日益增加,特别是在 AI 集成和 DevOps 实践的背景下,使得这一问题变得更加重要。忽视你所处的整体社会技术系统,肯定会导致反模式的出现。
-
用实际问题替代简单问题:许多反模式源于希望简化问题。许多架构问题是棘手的,只能提供不完美且高度复杂的解决方案。通常,这对于那些寻求简单易懂答案的利益相关者来说并不完全令人满意,而这种需求的满足往往会导致反模式。例如,安全领域中的合规即安全和声明式即安全,就是我们用简单的答案替代复杂现实的两个例子。这也扩展到新的模式,如让我们加点 AI,将复杂的 AI 实施挑战过度简化。
-
组织约束:另一个常见的反模式根本原因是受到当前组织结构的约束。无论是因为组织内部的孤岛、与供应商的糟糕关系,还是政治游戏,你所处的组织环境有时会导致甚至迫使你走上反模式的道路。这在新的模式中尤为明显,比如忽视利益相关者关切和低估变更的影响。
-
技术治理薄弱:缺乏有效的技术治理是另一个常见的反模式原因。当你没有任何架构权威、明确的标准或规范时,通常会出现漂移,从而产生反模式。这包括许多模式,如强耦合、系统扩散和不受约束的数据同步。DevOps 实践和 AI 能力的日益普及使得强有力的治理变得更加重要。
-
缺乏纪律性:最终,一些反模式归结为软件开发生命周期中缺乏纪律性。这包括泥球、意大利面共享模型、臃肿接口和虚拟单元测试等模式。新的模式,如不频繁提交代码,也属于这一类。这些在某种程度上是最容易解决的,因为解决方案显而易见,但推动团队走捷径的潜在压力往往更难应对。
解释如何在实践中使用反模式
如果你已经通读了本书,你会遇到大量关于 Salesforce 项目可能出错的模式。我们按架构领域进行结构化,以帮助你理解并提供更多的背景信息。
然而,你可能仍然对如何在日常工作中应用这份新知识库存在一些疑问。我们建议你可以通过两种主要方式,主动利用反模式知识来提升你的架构实践并磨练你的架构技能:
-
首先,你可以将其作为架构和设计过程的一部分,建设性地使用。
-
其次,你可以将它作为诊断工具的一部分,用来理解其他人设计的架构
建设性地使用反模式
建设性地使用反模式意味着你将基于反模式的思维纳入到你的正常架构过程当中。你可以通过几种方式做到这一点,从简单地拥有一个常见反模式的心理检查清单,来验证你的工作是否符合要求,到系统地检查所有适用于当前架构过程阶段的反模式。
我们建议在这两种极端之间选择一个折衷方案,你可以采取以下步骤:
-
在架构过程的开始,基于上一节中提到的六个因素进行评估。对于每个因素,按照标准的 1-5 评分标准评估你的环境,看看它可能对你的工作产生多大影响。
-
对于你在评估中评分为 4 或 5 的所有因素,列出在你的环境中可能发生的各种反模式。特别关注与 AI 集成、DevOps 实践和变更管理相关的新挑战。
-
对于你选择的那些反模式,在初步设计时以及项目的整个过程中定期进行检查,看看它们是否开始出现。
-
如果你开始看到某个反模式的倾向,按照模式描述中更好的解决方案部分的指示,采取主动措施。
诊断性地使用反模式
当你作为架构师进入一个现有环境时,基于反模式进行分析以诊断现有架构的健康状况是一个非常有成效的努力,我们强烈推荐这样做。这个分析不仅有助于你理解当前环境的优缺点,还可以指示出你可能开始重构它的方式。
我们建议你执行以下操作:
-
收集来自现有用户和熟悉现有环境的团队成员的信息,特别是那些可能表明存在反模式的非功能性特征。
-
根据你收集的信息,列出可能出现在该架构中的潜在反模式,包括与 AI、DevOps 和变更管理相关的新模式。
-
对相关技术文档进行彻底检查,确认或驳斥每个反模式的存在。
-
根据你的发现,开始考虑潜在的缓解措施,并评估你被带入的工作对环境的影响。
更进一步使用反模式
虽然这本书提供了大量信息,但显然你的架构学习之旅并不会止步于此。我们建议你考虑以下三条前进路径:
-
更深入地研究反模式文献
-
扩展你对 Salesforce 架构的知识
-
扩展你的一般架构知识
对于这些领域,我们已经精选了一系列有用的资源,并将在接下来的章节中进行讲解。
深入反模式文献
有三个资源,我们特别推荐它们来深入理解反模式的概念:
-
原版书籍是反模式:重构软件、架构和危机中的项目,作者为 Raphael C. Malveau、William J. Brown、Hays W. “Skip” McCormick 和 Thomas J. Mowbray。尽管这本书已经非常过时,但它在正式化和普及反模式概念方面起到了极为重要的作用。书中介绍的多个反模式可以追溯到这本书。
-
对反模式的整体讨论,无论是通用反模式还是具体反模式,都可以在 WikiWikiWeb 上找到,网址是
wiki.c2.com/?Anti-patter
。 -
DevIQ 拥有一个极好的反模式资源库,讨论了许多在多个平台上常见的反模式,可以在
deviq.com/anti-patterns/anti-patterns-overview
找到。
接下来,我们将探讨如何将对反模式的知识与对 Salesforce 架构的深入理解结合起来,以取得更好的成果。
扩展你的 Salesforce 架构知识
运用你新获得的 Salesforce 反模式知识的最佳方式之一是将其与对关键 Salesforce 架构领域的深入了解结合起来。我们推荐以下几本书:
-
首先,我们推荐 Tameem Bahri 的成为 Salesforce 认证技术架构师,适合那些正在准备 CTA 认证或未来有意向的读者。像这本书一样,它按照 CTA 架构领域进行结构化,因此具有很高的互补性。
-
另一本非常好的 Salesforce 架构书籍是 Mike King 的Salesforce B2C 解决方案架构师手册。
-
对于那些特别关注数据领域的人,我们强烈推荐 Ahsan Zafar 的Salesforce 数据架构与管理。
然而,Salesforce 架构只是需要考虑的一个方面。你还应该考虑扩展你的通用架构知识。
扩展你的通用架构知识
尽管反模式很重要,我们也应该努力提升我们对架构的整体理解。以下是一些可以帮助做到这一点的资源:
-
首先,我们推荐 Saurabh Shrivastava 和 Neelanjali Srivastav 的解决方案架构师手册,这本书很好地介绍了许多通用架构主题。
-
对于 CRM 及其架构的通用介绍,我们推荐 Max Fatouretchi 的CRM 的艺术。
-
最后,我们推荐 Jeroen Mulder 的多云架构与治理,以获得对日益普及的多云架构场景的良好概述。
我们已经覆盖了本章内容和书籍的要点,接下来将以最终总结结束。
总结
做得好,你成功了!这是本书的最后一章,现在你已经成为一名正式的反模式爱好者。
在这一章中,我们总结了本书的主要内容。特别是,我们分析了六个普遍存在于许多反模式中的根本因素,它们是这些反模式的根源。这些因素为架构师提供了指示标志,帮助他们在特定的架构环境中识别出可能出现的反模式,并了解可以采取哪些措施来缓解这些问题。
为了将这些知识应用于实践中,我们概述了两种将反模式融入架构流程的方法。首先,我们探讨了如何在自己的架构中建设性地运用反模式,其次是如何在检查现有架构时以诊断的方式使用它。
最后,我们探讨了你接下来可能的学习方向,以进一步扩展你的知识。我们概述了你可以采取的三条路径,并给出了一些书籍和其他资源的建议。
反模式是通用架构中最有趣的领域之一,因为它们告诉你事物是如何以可重复的方式出错的。从他人的错误中学习通常比自己犯所有错误要好,我真诚地希望阅读本书能让你更不容易重复这些反模式,并且能在你的环境中识别出他人即将犯的错误。
软件系统至关重要。组织依赖于它们。用户在工作中花费大量时间与它们互动。作为架构师,我们有责任帮助避免那些导致系统无法发挥最佳效能的常见错误。随着人工智能、DevOps 实践的普及以及架构解决方案中对有效变更管理的需求,这一责任变得愈加重要。