此文本使用 Salesforce 的自动翻译系统翻译。参加我们的调查,提供有关此内容的反馈,并告诉我们您接下来想要查看的内容。

Salesforce 平台不断推进其自动化架构,以满足复杂业务流程的需求。早期版本 — 工作流规则和进程构建器 — 提供了事件驱动逻辑的初始步骤,扩展了事件驱动逻辑的自动化功能,并将覆盖范围扩大到更广泛的构建者。

这种演变最终形成了以两个互补支柱为中心的高性能整合架构:记录触发的流和 Apex 触发器。本文档提供了在设计触发器自动化时做出明智决策的框架和指南。

Salesforce Flow 是一款功能强大的点击式自动化工具,可让用户使用 Flow Builder 直观地构建复杂的业务流程、屏幕和逻辑,而无需编写代码。它自动化数据更新、发送电子邮件和指导用户等任务,并通过屏幕流(用户交互)和触发的流(记录/计划的事件)等类型提供灵活性。
Apex Salesforce Apex 是适用于 Salesforce 平台的专有的、面向对象的编程语言,与 Java 相似,用于构建自定义业务逻辑、自动化流程并将核心 CRM 功能扩展到声明性工具之外。

在 Salesforce Platform 上构建可扩展、可维护和高性能的记录触发自动化需要一种有章可循的、以架构为导向的方法。Flow 和 Apex 之间的选择,以及每个流的实施,都遵循一套明确的原则。这些要点总结了这些原则,并作为现代自动化设计的基本规则。

  • 根据 Salesforce 对象自动化密度,为作业选择合适的工具。

    • 将 Salesforce 对象的记录触发流用于低密度自动化。

    • 使用可调用 Apex 扩充记录触发的流逻辑,以实现中等密度的自动化。

    • 对 Salesforce 对象使用 Apex 触发器实现高密度自动化。

  • 在触发异步进程时要谨慎小心。
    无论您是在记录触发的流中调用异步进程,还是从 Apex 将可排队作业排队,此规则都适用。虽然这种模式对卸载工作很有诱惑力,但它会引入复杂的错误处理场景,并增加达到调控器限制的风险。

  • 每个 Salesforce 对象使用一个入口点。
    对于给定的 Salesforce 对象,使用一个机制作为自动化的入口点。尝试避免将 Flow 和 Apex 触发器混合为同一对象的入口点。

Flow 和 Apex 共享一组共同的基本功能。每个工具都可以查询记录、执行条件逻辑、分配变量并执行 DML 操作,例如创建、更新和删除记录 — 按照指定顺序运行。

但是,这种功能重叠并不意味着这些工具可以互换。架构选择不是关于任务_是否_可以完成,而是_如何_完成以及对性能、可扩展性和可维护性的长期影响。Flow 在声明清晰度和实施速度方面表现优异,可实现简单流程,而 Apex 提供了复杂解决方案所需的精细控制和原始功能。

自动化密度是对特定 Salesforce 对象施加的负载。它作为一种启发式方法来确定对象的最优实施。随着自动化密度的增长,违反事务限制的可能性也越来越大。

通过检查数量和复杂性的三个特定维度来计算自动化密度:

  • **自动化数量:**在单个数据操作语言 (DML) 事件期间执行的唯一自动化元数据条目(流、触发器操作等)的原始数量。

  • **记录量:**通过 API 加载或繁重批处理处理的每个事务记录,其中性能变得至关重要。

  • **依赖性蔓延:**初始 CRUD 操作触发的下游 DML 操作的评测。它量化了一个更新层叠到相关对象更新的图表深度(例如,个案 → 客户 → 联系人 → 自定义汇总)。

自动化密度尺寸

随着 Salesforce 应用程序的范围和复杂性的增长,请提交到单个主要入口点 — 记录触发的流或 Apex 触发器。避免在单个 Salesforce 对象上跨多个机制划分自动化,因为这会导致可维护性差和治理分散。

使用此矩阵来确定 Salesforce 对象所需的架构标准。

  • 记录触发流是低自动化密度的首选解决方案。它提供了功能和可访问性的平衡,是直接且相互独立的自动化的理想选择。

  • **混合模式(带有可调用 Apex 的记录触发流)**对于复杂性不断上升的中等密度自动化来说是一个强大和可维护的选择。这种模式使团队能够在声明性流中维护有序的编排,同时将计算繁重的操作委托给 Apex,平衡可访问性和性能。

  • Apex触发器为支持高密度自动化奠定了坚实的建筑基础。Apex 的性能、粒度控制、面向对象的抽象和多态性更适合管理这些场景的复杂性和规模。

密度级别 自动化数量 数据量(批次大小) 依赖性蔓延 架构标准
< 15
自动化
标准
用户驱动的 UI 交互或少量 API 加载(1–200 条记录)
离散
独立逻辑。同一对象或相关对象上的 0–1 下游 DML 操作。
记录触发的流
中等 15–30
自动化
审核
标准批处理(逻辑需要谨慎批量化)
夫妻
父/子级更新 2-4 个下游 DML 操作。递归风险
混合模式
流 + 可调用 Apex
> 30
自动化

具有批量 API 加载的大数据量(2,000 – 10,000 多条记录)
复杂和递归
深度依赖图(5+ 下游 DML 操作)。三角形递归循环的风险
Apex 触发器元数据框架
真实世界的架构决策要求您共同权衡自动化密度的所有维度。为给定的 Salesforce 对象选择自动化机制时,请考虑潜在的未来范围。

此外,考虑每日 DML 操作总数,因为 Salesforce 在多租户环境中强制实施共享资源管理,并限制管理者,以防止失控自动化独占共享资源。每日 DML 用量大的 Salesforce 对象需要谨慎的自动化选择。例如,CPU 时间(60,000 毫秒)和堆大小(12 MB)的异步限制高于同步限制。此外,组织范围内的异步执行 24 小时限制(计算为 250,000 次,或用户许可证的 200 倍)需要在架构设计中考虑每日总 DML,以避免运行时异常。

记录触发的流是平台用于记录触发自动化的首要声明性工具。Flow 的易用性和内置平台保障使团队能够轻松构建可扩展的可靠解决方案。这是大多数在 Salesforce 平台上构建解决方案的团队的理想选择。

Apex 是平台的专有强类型面向对象编程语言。将 Apex 用于具有高自动化密度的 Salesforce 对象,以及需要高性能、复杂逻辑或精细事务控制的用例。

为了有助于决策过程,此矩阵提供了关键架构功能之间流和 Apex 的直接比较。

功能 记录触发的流 Apex 触发器
交付和维护速度 推荐
Flow Builder 的可视用户界面允许管理员和其他声明性生成器创建和修改自动化,比编写、测试和部署 Apex 代码更快。此界面使更广泛的团队成员能够提供业务价值,并减少对简单任务的专业开发人员资源的依赖。
需要专业知识
Apex 需要具备适当技能的软件开发人员来实施、测试和维护代码。
模块化 可用
默认情况下,记录触发的流是模块化的。团队不是单一逻辑,而是针对特定要求构建离散流,并使用流触发器资源管理器一起编排它们。这种模块化实现了隔离修改和简单扩展,大大降低了长期拥有成本。
可用
Apex 按设计分为功能模块。每个 Apex 类旨在实施单个功能模块。
可见性和治理 推荐
流的可视性提供了业务逻辑的直观表示。流触发器资源管理器提供对象上所有流的综合视图,使架构师和管理员更容易理解、治理和排除故障,而无需阅读代码。
需要专业知识
使用元数据框架来组织触发器是有利的,但是 Apex 需要纪律严明的开发团队来保持代码的组织性和可维护性。
高性能批量数据处理 不推荐
在处理复杂逻辑或大数据量时,达到调控器限制的风险更高。
推荐
Apex 代码的执行更接近平台的核心服务,并为开发人员提供了对查询优化、数据处理和算法效率的增强控制。这将带来更好的性能和规模,特别是在涉及大量数据的复杂场景中。
强大的逻辑和数据结构 可用
流转换元素可以帮助完成一些复杂的处理任务。但是,Flow 缺少本地地图和设置数据结构,使得复杂的数据处理很麻烦,计算效率低下。
推荐
Apex 提供对映射、设置和程序循环的完整访问权限,以实现高效、批量安全的数据操纵。Apex 作为一种全功能编程语言,也提供对复杂逻辑结构、数据结构和设计模式的访问权限,有助于以可维护和有效的方式解决复杂的业务问题。Apex 包含丰富的高级函数标准库(例如 BusinessHours、Crypto),目前这些函数在声明性工具中不可用。
交易控制 不可用
对于部分事务提交或回滚,流不提供对“Database.savepoint”、“Database.rollback”或部分成功的 DML 操作的访问权限。
可用
Apex 提供了对事务完整性和复杂错误恢复场景的全面精细控制。
电子邮件分发 推荐
从记录触发的流发送预配置的电子邮件提醒简单且可扩展。自定义电子邮件提醒可以在运行时创建和分发。自定义电子邮件受每日电子邮件发送限制。
可用
Apex 可以生成并发送自定义电子邮件消息。从 Apex 发送的所有电子邮件都受每日电子邮件发送限制
应用平台保障 推荐
流包含内置保护,例如自动批量化和自动重试。这些保障措施提高了价值实现的速度,并防止了否则需要复杂的手动编码的性能缺陷。
需要手动实施
批量化等保护措施必须明确编码(例如,管理集合和避免循环内的 SOQL)。自动重试不是触发器的本机功能,需要复杂的自定义逻辑来实现。
异步处理 可用
对于需要在异步路径中单独交易的自动化,流提供了简单的机制。这些自动化受每日限制。
可用
Apex 通过解耦触发器订阅者处理的变更数据捕获和可排队事件实现完全控制。
计划处理 推荐
流的计划路径提供了独特而强大的计划功能(例如,“在结束日期前 3 天触发”)。如果记录的数据发生变化,此功能包括自动取消和重新计划。这些自动化受每日限制。
不可用
Apex 触发器无法通过自动取消本地计划特定于记录的时间事件。虽然存在计划的 Apex,但它是一种根本不同的机制,它在特定时间运行,并且在作为触发器的一部分处理单个记录的过程中不会被计划。
订单和编排 可用
流触发器资源管理器允许管理员为同一对象上的多个流定义相对执行顺序。
可用
触发器框架提供了对自动化精确顺序的精细控制。
相同记录字段更新 可用(保存前)
记录触发的流是在初始 DML 提交之前更新触发记录的最高性能的声明性选项。
可用(保存前)
Apex 以最少的开销提供最高性能的产品。
跨对象 CRUD 可用(保存后)
流适用于简单、低复杂性的跨对象 DML 操作。
可用(保存后)
Apex 为跨对象 DML 操作提供了对重复数据消除、错误处理和性能的卓越控制。
昂贵的重复数据消除 可用
Flow 擅长通过自动批量化来消除冗余查询和 DML 语句。但是,状态不能在不同流触发器之间或在一个事务中同一流的多次调用之间缓存或共享。在极端性能场景中,此限制可能变得很重要。
推荐
Apex 提供了对昂贵操作进行重复数据消除的机制。开发人员可以使用静态属性和变量的事务缓存和使用平台缓存的平台级缓存来存储和重用数据。这些技术对于减少事务调控器限制(例如 SOQL 查询)的消耗,并确保高性能和可扩展性非常重要。
自定义错误处理 可用
CustomError 元素可以阻止保存操作并向用户显示消息。
推荐
addError() 方法提供了灵活的字段级和条件错误消息。

此表根据提供的功能,为通用用例提供了通用“最适合”推荐。最终,您将考虑其他注意事项,以得出最适合特定场景的方案,例如本文档_相关最佳实践_部分包含的方案。在那里,您将了解有关 Flow 和 Apex 的特定组合何时提供最佳方法的更多信息。

用例 描述 最适合 理由
高性能批处理 任何必须高效处理数千条记录的自动化 Apex Apex 为与平台的接口和原始速度提供了丰富的 API。
复杂数据处理 需要高级数据操作的场景 Apex Apex 提供在流中本地不可用的数据结构,例如映射和集,对于编写高效的批量安全代码至关重要。
交易控制 控制机制,例如保存点、回滚和部分提交 Apex Apex 提供对 Database.savepoint 和 Database.rollback 等机制的访问权限,并能够处理部分成功的 DML 操作。
复杂的自定义验证 记录中多个字段之间的数据验证 Apex 虽然流可以阻止使用“CustomError”元素保存,但它并非在所有流类型中可用,包括子流。Apex addError() 方法提供了多个特定于字段的错误消息,可以在触发器处理期间随时添加到记录中。
简单流程中的适度复杂逻辑 中等复杂性的逻辑和数据操纵,由标准高级函数库简化,作为不复杂流程的一部分发生 流 + Apex 记录触发的流充当编排层,而高复杂性操作封装在可调用 Apex 中。
简单到中等复杂的逻辑 低到中等复杂性的数据操纵,对主数据和相关数据对象进行触发器更新 流通常是转到选项,因为它基于声明性模型,使管理员和开发人员都可以访问它。
通知和出站消息 发送出站电子邮件和消息 流使发送电子邮件提醒和记录更改的出站消息变得容易和高度可扩展。
计划处理 未来动态日期的自动化(例如,结束日期前 3 天) 计划的路径为流提供了独特的优势,因为如果记录的数据发生变化,平台会自动处理这些路径的计划、取消和重新计划。

可扩展性是设计实施时的一个关键考虑因素。当记录触发的自动化的业务逻辑变得复杂、长时间运行或涉及高数据量时,Salesforce 平台的核心调控器限制将成为架构约束。批量数据更新、复杂 API 标注或繁重计算等操作会增加违反限制的风险,例如总 CPU 时间或单个数据库事务中 DML 语句的数量。由于限制异常而导致同步触发器失败,将导致用户的整个保存事务回滚,从而导致用户体验不佳和潜在的数据丢失。这种内在风险要求一种架构模式来卸载复杂的工作。

在这种情况下,异步自动化变得至关重要。使用异步机制,架构师可以有效地将长时间运行或高用量的工作与主要的同步记录保存事务分离开来。快速可靠地保存完成,而繁重的处理被委托给一个单独的平台管理的事务,该事务稍后执行。解耦提高了稳定性,防止了事务失败,对于构建可扩展的企业应用程序至关重要。该平台为此提供了几种专用工具,每种工具在可靠性、体积和复杂性方面都有不同的好处和利弊权衡。

记录触发的流中的异步运行路径为“触发并忘记”异步逻辑提供了最简单的机制。在原始记录保存事务成功提交到数据库后,此路径将在单独的事务中执行。

  • 理想用例:这非常适合不需要立即执行或自定义错误处理的任务。示例包括发送电子邮件通知、创建跟进任务或对外部系统进行简单的标注。

  • 限制:此机制与其他异步流采访共享相同的每日调控器限制。它并非设计用于极高用量的处理。

变更数据捕获 (CDC) 是一种高吞吐量、可扩展和弹性的模式,用于处理高用量场景中记录变更触发的异步逻辑。在此模型中,触发器的唯一责任是同步保存记录。然后,平台发布详细的事件消息,其中包含记录对高用量事件总线的更改。单独的专用 Apex 触发器订阅此变更事件。它执行复杂的、长时间运行的或异步的工作。

  • 福利:此模式将异步进程与初始用户事务分离。异步处理中的失败不会导致用户的记录保存回滚。该模式还提供了多个内部订阅者或外部系统可以使用的持久事件流,事件可以重放长达 72 小时,提供了强大的弹性。

  • 限制事件消息不包含记录的先前状态——相当于ApexTrigger.oldMap。事件负载包含新字段值,但不包含更改的值。这使得实施基于特定状态转换的逻辑具有挑战性(例如,仅在Status__c从“待处理”更改为“已批准”时运行)。您可以通过在事件订阅者中查询对象的字段历史来缓解这种情况,但这会增加过程的复杂性,并且字段历史跟踪可能对特定感兴趣的字段不可用。这可能会限制您可以卸载到 CDC 的自动化类型。

默认情况下,CDC 可以在最多五个 Salesforce 对象上启用。需要更多资源的组织可以购买一个加载项许可证,以消除此限制并增加事件交付分配。

直接从触发器将可排队 Apex 作业排队应被视为一种风险模式,仅在需要 Apex 提供的控制(例如,对于复杂的逻辑或自定义重试机制)时使用,CDC 不是一个可行的选项。

如果需要 Queueable Apex,实施必须包含适当的保护措施:

  • 限制检查:在尝试添加其他作业之前,代码必须检查事务中已经排队的作业数量。

  • 上下文感知:代码必须检测它是否在异步上下文中运行,例如批处理作业 (System.isBatch()),并修改它的行为以遵守该上下文中更严格的每个事务一个作业的限制。

从同步触发器调用异步 Apex 会产生稳定性风险。为了防止组织级的影响(例如,超出限制),这种模式需要严格的设计和测试。

  • 异步 Apex 执行的每日限制(BatchQueueable@Future)在整个组织中共享(通常是 250,000 个或根据用户许可证计算)。20000 条记录的批量数据加载将导致触发器在 200 条块中执行,从而产生 100 个单独的触发器调用 — 即使批量大小少于 200 条记录,也会更多。如果每次调用都对异步作业进行排队,则单个数据加载的每日限制可能会消耗很大一部分。这种消耗可能会耗尽异步资源的其他关键业务流程。

  • 将作业排队的调控器限制因上下文而异。从 UI 中的用户操作触发的触发器(_同步_事务)中,最多可以将 50 个可排队作业排队。然而,从在批处理 Apex 类的execute方法(_异步_事务)中触发的触发器中,只能将一个可排队作业排队。不考虑这种差异是一个常见和关键的故障点,会导致大型数据操作期间的LimitException错误。

  • 直接从触发器上下文调用可计划 Apex (System.schedule) 或批处理 Apex (Database.executeBatch) 构成反模式。这些方法并非设计用于从触发器上下文调用。这样做将导致异步 Apex 分配的快速消耗,从而导致限制异常。

每个异步机制在性能、调控器限制和可靠性方面都有特定的权衡。使用此决策树作为指南,帮助您导航这些选项,并为用例选择正确的机制。

异步模式决策树

如流程图所示,当您面临大量 DML 操作但无法使用变更数据捕获时(可能由于对象限制),最佳的架构选择通常是完全避免触发器调用的过程。

相反,请考虑使用计划的进程。这可以是计划的流或计划的 Apex。所需步骤是:

  1. 在同步触发器中执行简单的低成本更新。例如,将Status__c字段设置为“待处理”,或插入低成本相关记录,例如 Chatter 帖子,以表示该记录需要处理。

  2. 创建定期运行的已计划作业,即已计划流或已计划 Apex,例如每 15 分钟或每小时运行一次。

  3. 让计划作业查询处于待处理状态的所有记录,在受控的高用量上下文中执行复杂逻辑,然后在处理时更新记录。

此模式将繁重的处理与用户的同步保存完全分离,不受触发器触发批次的每个事务一个作业的限制,并为非实时需求提供了高度可扩展和可管理的解决方案。

如果计划作业的延迟对业务需求来说是不可接受的,并且您仍然被限制使用 CDC 或触发器触发的可排队,这表明架构不匹配。此时,必须考虑不同的机制。重新评估核心应用程序设计可能会导致某些结论,例如:

  • 购买加载项以删除 CDC 对象限制。

  • 从根本上说,确定近乎实时的处理是否真正是“必须拥有的”,或者计划作业的延迟是否是平台稳定性的可接受的折衷方案,是业务需求的挑战。

实施的复杂程度是解决方案总拥有成本的一部分,也是其适应不断变化的业务需求的能力的一部分。如果不遵循最佳实践,复杂性会影响任何实施。在本文档的“相关最佳实践”部分中,提出了降低解决方案复杂性的建议,包括以下模式:

  • 混合模式:适用于流中复杂逻辑的可调用 Apex

  • 使用 Apex 触发器的元数据框架

  • 超大流量与多个流

文档与自动化本身同样重要。它不仅确保可维护性,而且对于 AI 和基于客服人员的工具也至关重要。文档有助于您了解和管理业务流程。

在流中

  • 为所有元素和变量建立一致的命名约定。

  • 使用流的描述字段来解释其整体目的、触发条件和预期结果。

  • 在每个单个元素上使用描述字段(例如,Get RecordsActionTransform)。这种做法是传达意图的最佳方式。它对于可调用操作和子流尤其重要,其中描述是解释操作执行的复杂逻辑的主要位置。

在 Apex

  • 清晰评论您的代码,以解释逻辑背后的_原因_,而不仅仅是_什么_。

  • 如果使用元数据驱动的框架,请确保您的元数据记录包含并填充人类可读的描述字段,以解释每个处理程序类的功能及其应运行的时间。

DevOps 和源控制是成熟开发生命周期的一部分。始终使用源控制工具,例如适用于 Salesforce 项目的 Git。Apex 类和 Salesforce 流都是定义业务逻辑的元数据,必须对其进行版本化和管理。

在记录触发的自动化管理的上下文中,现代 DevOps 漏斗提供了基本的好处。

  • 自动质量检查:Salesforce 代码分析器等工具可以配置为在您的漏斗中自动运行。静态分析可以在升级之前检测这两种自动化工具中的问题模式,并标记出流循环中效率低下的Get Records元素或 Apex for 循环中的SOQL查询等问题,这些都是性能下降的常见原因。

  • **回归预防:**随着自动化密度的增长,对一个流或 Apex 类的更改可能会对同一对象上的其他自动化产生意想不到的后果。确保新流版本不会破坏现有 Apex 逻辑的最可靠方式是强大的 DevOps 测试策略,其中针对任何建议的更改运行自动 Apex 测试(反之亦然)。

  • **协作和可见性:**源控制是“真理的单一来源”。它允许管理员和开发人员并行处理相同对象的自动化。它还提供了宝贵的审计跟踪:当生产过程中断时,您可以立即看到_谁_更改了自动化,他们_何时_更改的,以及他们为_什么_更改它 — — 通过提交消息。

对于管理员和开发人员混合的团队,DevOps Center提供了统一的界面来帮助编排所有这些步骤,使团队中的每个人都可以访问可扩展的、基于源代码控制的开发流程。

文档和 DevOps 的这一组合纪律确保了贵组织的长期运行状况和维护性,这将使关注您的每位架构师和管理员受益。

以上决策指南最适合在计划实施前使用。它旨在帮助您为您的用例选择最佳产品。在产品选择后,了解您的实施的现有最佳实践非常重要。

_每个对象一_个工具原则对于管理高密度自动化至关重要,但请勿将其解释为纯声明性或纯编程堆栈之间的二元选择。更有效和可维护的架构模式利用了混合模型:将记录触发的流定位为编排层,同时将高复杂性操作封装在可调用 Apex 中。

混合模式图

记录触发的流充当业务流程的编排层。它拥有准入条件和执行上下文(什么_和_什么时候)。通过在此层中保留决策逻辑和路由,架构的进程拓扑保持透明,并通过流触发器资源管理器进行管理,防止代码中的关键业务逻辑被模糊。

复杂组件的一个常见示例是实施个案记录的服务级别协议 (SLA) 计算。由于 BusinessHours 对象及其相关逻辑(对于排除非工作时间和假期的准确计算至关重要)无法在流中本地访问,因此使用专用 Apex 类。该类通常命名为 ServiceLevelAgreementCalculator,它使用单个静态方法设计,并使用 @InvocableMethod 注解,以计算经过的工作时间,确定 SLA 是“目标内”还是“已违反”,并返回结构化输出。这种方法在 Apex 中封装了复杂的高性能逻辑,同时允许它无缝执行并集成到记录触发流的声明性编排层中。

一旦定义了 Apex ServiceLevelAgreementCalculator类,它就可以在记录触发的流中使用:

这种模式表明关切事项严格分离。声明层用于管理事务生命周期和编排,而代码用于高复杂性的执行。通过将代码视为功能实用程序而不是基础,我们平衡了性能和可维护性。

模块化:该决策偏离了在整个流程中使用 Apex 或 Flow 的奇异性。相反,该架构将复杂的逻辑封装成离散的、批量安全的和可独立测试的单元。这些单元充当声明层消耗的可重用组件,确保自动化规模,而不会使架构设计复杂化。

重用性:逻辑与触发器事件分离。设计良好的代码单元(例如InvocableMethod)仅编写一次,但会在多个入口点之间使用:记录触发的流、屏幕流或外部集成。这种代码重用消除了冗余开发。

维护性:流程流逻辑在声明性流中保持可见和可管理。这种集中极大地减少了调试开销,并确保系统的执行顺序是确定性和透明的。

虽然使用流中可调用 Apex 的混合模型功能强大,但并非一刀切的方法。在致力于混合解决方案之前,架构师必须了解特定的限制和权衡。

  • 无保存前支持:这是最重要的限制。可调用操作仅在保存后上下文中可用(操作和相关记录的流)。它们不能在高性能保存前上下文中使用(用于快速字段更新的流)。因此,此模式不能用于委派相同记录字段更新。在保存前流或上下文 Apex 触发器中使用本机流元素执行高性能工作。

  • **无取消删除后支持:**记录触发的流目前不支持取消删除后的上下文。如果 Salesforce 对象有在从回收站恢复记录时运行自动化的业务需求,Apex 触发器是唯一的解决方案。

  • **高用量场景下的性能开销:**从流运行时到 Apex 运行时的过渡不是零成本操作。虽然通常速度很快,但从流的运行时进入可调用操作的操作在计算上不如完全在 Apex 触发器内的本地执行快。对于大多数中等密度的自动化,这种微型开销对于提高可访问性来说微不足道,值得权衡。但是,对于极端高性能、高用量的场景,纯 Apex 仅框架将具有原始计算速度优势。

虽然自动化密度启发式为更新的绿地架构提供了明确的指导,但企业 Salesforce 环境的现实往往更加细微。在成熟的组织中,通常可以找到在相同 Salesforce 对象上运行的记录触发流和 Apex 触发器。此场景与之前解释的混合模式不同:这里,流和 Apex 触发器不是耦合的,也不是设计为一起工作的。

这种共存往往是平台功能不断发展或传统技术债务的结果。虽然这是允许的操作状态,但架构师必须将其视为计算权衡,而不是最终状态。

零散的编配造成了巨大的治理和维护开销,使得开发、测试和事件处理活动相互脱节且繁琐。这导致解决时间 (TTR) 和操作复杂性增加。

  • 对于新的 Salesforce 对象,坚持自动化密度原则作为主要指南。

  • 对于具有混合足迹、双 Apex 触发器和记录触发的流入口点的现有 Salesforce 对象,评估密度,然后架构师重构到可维护的混合状态。

    • 对于低密度,将 Apex 触发器重构为记录触发的流,并指定执行顺序,将它们带到单个自动化入口点。

    • 对于中等密度,使用正确的执行顺序将复杂的超大流重构为流子集。仅在绝对必要时引入 Apex 触发器,例如在取消删除上下文后支持。

    • 为获得高密度,最好实施 Apex 触发器。

随着组织在 Salesforce 平台上的业务流程的成熟,记录触发的自动化的数量和复杂性不可避免地会增加。一个基本的最佳实践是维持_每个 Salesforce 对象一个_ Apex 触发器。此规则至关重要,因为平台不保证同一事件同一对象上多个触发器的执行顺序。这种限制会导致非确定性行为、竞争条件和难以调试的问题。

然而,遵守_单触发器_原则带来了一个架构挑战:如何以可维护、可扩展的方式管理和编排从该单一入口点调用的所有业务逻辑。

此架构的第一个演变是 Classic 触发器处理器模式。在这种方法中,单个 Apex 触发器将其所有逻辑委托给相应的处理程序类(例如,OpportunityTriggerHandler)。此方法将逻辑与触发器文件分开,并为开发人员提供对处理器类方法(例如 afterInsert())中执行顺序的确定性控制。

虽然是一种改进,但这种模式通常会导致单片处理器类。随着时间的推移,随着更多业务需求的添加,该类会变得很大,难以管理,并且难以单独测试。所有单个流程的执行顺序都在一个方法中硬编码,这使得类容易出现合并冲突,从而大大增加了大型企业环境中的治理和维护开销。

为了解决模块化和编排的核心问题,架构师转向了元数据驱动触发框架。这是一次重大的架构飞跃,将自动化逻辑本身与_如何_和_何时_运行的配置分离开来。

该框架基于三个关键优势:

  • **分区:**不是单个处理器类,而是将核心业务逻辑分解为小的原子 Apex 类(例如,RecalculateAccountValues类或NotifySalesLeads类),每个类都遵守_单一责任原则_。这种模块化使得逻辑更容易单独测试、调试和理解。

  • **顺序和编排:**执行订单不再在 Apex 中硬编码。相反,它由配置记录进行声明性定义,通常存储在自定义元数据类型中(例如,TriggerAction__mdt)。这允许管理员通过修改元数据记录来重新排序、添加或删除自动化操作,这不需要部署或代码更改。

  • **绕过功能:**该框架提供了标准化的精细旁路功能。每个自动化操作都可以通过其元数据记录配置为全局关闭,或者通过引用自定义权限来绕过特定的管理用户。

然后,对象的单个 Apex 触发器仅用作动态调度人员。它不包含业务逻辑,而是实例化一个中心MetadataTriggerHandler类。该处理器查询自定义元数据记录,以动态确定执行顺序,并按照规定的顺序调用正确的原子 Apex 类。自动化被统一在一个透明和可治理的层下。

在强大的框架中使用 Apex 的一个重要好处是通过消除冗余工作来管理事务状态和优化性能的能力。随着逻辑的累积,保存订单中的不同自动化通常会独立执行相同的昂贵操作,消耗宝贵的调控器限制,并增加 DML 操作时间。

该框架旨在用两个主要策略来解决这个问题:

  • **共享状态管理:**在单个 Apex 事务的范围内,静态属性和变量被用来缓存数据。这确保了昂贵的操作(例如配置设置的SOQL查询)仅执行一次,即使在触发器的不同记录或阶段中多次调用自动化逻辑。事务限制的消耗大大减少。

  • **平台缓存利用率:**要超越简单的事务内缓存,请使用平台缓存来避免查询整个数据库的某些数据。这种受管的内存缓存非常适合检索非原始的、在代码库中频繁读取的、在整个事务过程中不可变的数据(例如简档、角色、工作时间)。使用 Cache.CacheBuilder 界面,系统首先检查缓存,并仅在数据不存在时执行数据库查询,从而最大限度地提高性能和可扩展性。

当您的自动化只需要更改启动事务的记录上的字段值时,请始终使用保存前更新。这适用于流中的快速字段更新(在保存前运行)和 Apex 触发器中的上下文前逻辑(插入前、更新前)。

无论使用哪种工具,此模式都是有效的,因为它避免了第二次 DML 操作和递归保存周期。在提交到数据库_之前_,对内存中的记录进行更改,并作为原始事务的一部分保存。消除了第二次保存的开销,否则将重新执行整个保存订单并再次启动所有自动化。

不受控制的递归是更新后触发器中常见的陷阱,其中触发器的逻辑执行 DML 更新,进而导致同一触发器再次触发。这将创建一个无限循环,并最终以调控器限制异常结束。虽然静态布尔标记或处理的记录 ID 集合历来用于防止这种递归,但更精确和更强大的模式是通过比较记录本身的新版本和旧版本之间的字段值来把逻辑关起来。

仅在特定兴趣领域实际发生变化时执行逻辑。这防止触发器在同一事务中的后续 DML 操作上运行其逻辑,其中关键数据保持不变。

在记录触发的流中,通过将流设置为仅在更新记录以满足条件要求时运行,防止不受控制的递归:

控制记录触发流中的递归

如果您在流中选择使用准入条件公式,您可以通过将$Record全局变量(代表新值)与$RecordPrior全局变量(代表保存前的原始值)进行比较来防止失控递归。例如,要确保流仅在业务机会的金额字段已更改时运行,请在准入条件中使用:

将新版本记录 Trigger.new 中的字段值与旧版本记录 Trigger.oldMap 中的字段值进行比较,以查看您是否发生了您正在寻找的特定更改。这种方法确保自动化是幂等的,并且只在必要时运行,提高了系统的效率,防止了灾难性的递归循环。

架构良好的 Salesforce 组织需要一致可靠的机制来绕过自动化。这不是可选功能,而是维护数据完整性和启用管理任务的核心操作要求。

对于一些场景,旁路框架至关重要:

  • 在加载大量数据时,触发每个记录的触发器会显著减慢进程,导致限制异常,并创建错误的相关记录和通知。旁路允许干净高效地插入数据。

  • 集成用户可能需要同步来自外部记录系统的数据。当更改来自另一个系统时,通常为用户发起的更改触发的自动化(例如,发送电子邮件、创建任务)可能是不可取的或多余的。

  • 管理员或支持人员可能需要对记录执行更正更新。绕过机制允许他们在不触发标准业务自动化的情况下进行这些更改,这可能会产生意想不到的后果。

自定义权限:实施旁路逻辑的现代可扩展标准是自定义权限。这些方法优于旧方法有几个原因:

  • **灵活性:**自定义权限可以通过权限集分配给用户。这种做法符合现代 Salesforce 安全和访问模型,允许精细和灵活的分配。绕过可以授予特定用户,甚至可以临时授予特定到期日期/时间。

  • **可维护性:**使用自定义权限可以避免将简档或用户硬编码到自动化逻辑中。如果用户的角色发生变化或新简档需要绕过访问权限,则更改是简单的权限集分配,而不是需要部署的代码或流修改。

  • **可扩展性:**自定义权限为管理复杂用户群中的异常提供了一个可扩展的框架。它们可以通过权限集、权限集组或简档分配给用户。它们与权限集或简档的关联也可以在源元数据中表示。

实施模式:将一致的绕过模式应用于组织中的所有记录触发的自动化。

绕过记录触发的流:绕过流的最有效方法是完全阻止它运行。通过将条件添加到流的准入条件来实现这一点。

  • 在记录触发的流的开始元素中,将条件要求设置为公式评估为真。

    • 在公式生成器中,使用 $Permission 全局变量包含自定义权限的检查。将检查与您现有的准入条件结合起来。

      • 公式模式:
    • 此模式确保流仅在用户_未_分配指定自定义权限时运行。此检查甚至在创建流采访之前执行,使其成为性能最好的方法。

绕过 Apex 触发器框架:在 Apex 中,将绕过逻辑直接集成到元数据驱动的触发器框架中,允许精细控制。

  • TriggerAction__mdt自定义元数据类型应包含文本字段,例如 BypassPermission__c

    • MetadataTriggerHandler 类中,在动态执行操作之前,代码应读取此字段中的值。

    • 如果填充字段,处理程序会使用 FeatureManagement.checkPermission() 方法确定当前运行用户是否拥有指定的自定义权限。

    • 如果 checkPermission() 返回真,处理程序会跳过该特定操作,并继续序列中的下一个操作。

    • 此模式功能强大,因为它允许全局绕过(如果所有TriggerAction__mdt记录引用相同权限)和精细的每个操作绕过(如果不同记录引用不同权限,或一些记录根本没有绕过权限)。

将对象的所有自动化整合到单个大型流中是一种反模式。合并为一个流与将逻辑拆分为多个条件良好的流不会对性能产生重大影响。最重要的性能提升来自:

  • 使用保存前流进行相同记录字段更新。

  • 编写精确的条目条件,以确保流排除在不会影响特定用例的更改上运行。

流触发器浏览器允许您为对象上的每个流分配顺序值,保证顺序执行。

流触发器资源管理器
Apex 操作