Salesforce Flowアーキテクチャ:スケーラブルな自動化とガバナンスへのガイド

Salesforceアーキテクトとして、本日はSalesforceプラットフォームにおける自動化の要であるFlowについて、アーキテクチャの観点から深く掘り下げて解説します。

背景と応用シナリオ

Salesforceの自動化ツールは、Workflow RulesやProcess Builderから、現在の主力であるFlow Builderへと進化を遂げてきました。この進化の背景には、ビジネスプロセスの複雑化と、より高度で柔軟な自動化への要求があります。アーキテクトとして私たちが考慮すべきは、単に「要件を満たすか」だけでなく、「その実装はスケーラブルか、保守性に優れているか、そしてプラットフォーム全体の健全性に寄与するか」という点です。

Flowは、もはや単なるレコード更新ツールではありません。その応用範囲は広く、アーキテクチャ設計において中心的な役割を担います。

主な応用シナリオ:

  • 複雑なビジネスロジックの宣言的実装:複数のオブジェクトにまたがるデータの作成、更新、削除を、条件分岐やループを用いて宣言的に構築します。これにより、開発サイクルを短縮し、ビジネス部門による変更要求にも迅速に対応できます。
  • ガイド付きユーザーインタラクション:Screen Flow (画面フロー) を使用して、ユーザーを特定の業務プロセスに沿ってガイドします。例えば、複雑なサポートケースの受付プロセスや、段階的な営業案件のクロージングプロセスなどが挙げられます。これにより、入力ミスを減らし、業務の標準化を推進します。
  • 非同期処理と長時間プロセスのオーケストレーション:Flow Orchestration (フローオーケストレーション) を利用することで、複数のユーザーやシステムが関与する、承認プロセスやオンボーディングプロセスのような長時間にわたるビジネスプロセスをモデル化し、自動化できます。これは、従来であればカスタム開発や複数のツールを組み合わせる必要があった領域です。
  • 外部システム連携の起点:HTTP Callout (ベータ) や、Apex経由でのコールアウトを活用し、Flowを起点とした外部システムとのデータ連携を実現します。例えば、取引先が作成された際に外部の与信管理システムへ問い合わせを行う、といったシナリオが考えられます。

これらのシナリオにおいて、Flowをアーキテクチャの構成要素として適切に位置づけることが、持続可能で堅牢なシステムを構築する鍵となります。


原理説明

Flowの動作原理を理解することは、パフォーマンスとGovernor Limits (ガバナ制限) を考慮した最適な設計を行う上で不可欠です。

Flowが実行されると、SalesforceはFlow Interview (フローインタビュー) というインスタンスを生成します。このインタビューが、Flowのロジックを実行し、ユーザー入力やデータベースの変更を管理します。アーキテクトとして特に注意すべきは、Flowが実行されるトランザクションのコンテキストです。

実行コンテキストとトランザクション

Record-Triggered Flow (レコードトリガーフロー) は、Salesforceの保存順序 (Order of Execution) の中で特定の位置で実行されます。ここでの重要な選択肢は、「Before-Save」と「After-Save」です。

  • Before-Save Flow (保存前フロー): レコードがデータベースにコミットされる「前」に実行されます。トリガーとなったレコード自身の項目値を更新するのに最適です。追加のDML (Data Manipulation Language) 操作が発生しないため、非常に高速に動作し、Apexの`before`トリガーと類似したパフォーマンス上の利点があります。アーキテクチャとしては、同一レコード内の項目更新は、可能な限りBefore-Save Flowで実装することを第一に検討すべきです。
  • After-Save Flow (保存後フロー): レコードがデータベースにコミットされた「後」に実行されます。関連レコードの作成・更新、メール送信、外部システムへのコールアウトなど、トリガーとなったレコードIDが必要なアクションや、追加のDML操作を伴う処理に適しています。ただし、再帰的な実行や複数の自動化ツールによる連鎖的な更新を引き起こす可能性があるため、慎重な設計が求められます。

Flow Orchestrationのアーキテクチャ

Flow Orchestrationは、従来のFlowとは一線を画す概念です。これは、単一のトランザクションで完結する自動化ではなく、複数のStage (ステージ)Step (ステップ) で構成される長期的なビジネスプロセスを定義します。

  • Stage: プロセスの主要なフェーズを定義します。各ステージは、特定の条件が満たされたときにアクティブになります。
  • Step: 各ステージ内での具体的なアクションを定義します。ステップには、ユーザーの操作を待つScreen Flow (インタラクティブステップ) や、バックグラウンドで実行されるAutolaunched Flow (バックグラウンドステップ) があります。

この仕組みにより、例えば「従業員のオンボーディング」というプロセスを、「人事部による情報登録(Stage 1) → IT部によるアカウント発行(Stage 2) → 上長によるOJT計画承認(Stage 3)」といった形で、関係者と処理を明確に分離し、プロセス全体の進捗を可視化・管理することが可能になります。

「Clicks and Code」パターンにおけるFlow

アーキテクチャ設計において、「すべてをFlowで実装する」または「すべてをApexで実装する」という二者択一は避けるべきです。最適なアプローチは、Flowの宣言的な利便性とApexのプログラム的な柔軟性を組み合わせる「Clicks and Code」パターンです。

FlowからInvocable Apex (呼び出し可能なApex) を呼び出すことで、Flow単体では実現が難しい複雑な計算処理、高度なWebサービスコールアウト、一括データ処理などを実現できます。これにより、ビジネスロジックの大部分を管理しやすいFlowで構築し、特殊な処理のみを再利用可能なApexコンポーネントとしてカプセル化するという、保守性と拡張性に優れたアーキテクチャが実現できます。


示例代码

ここでは、「Clicks and Code」パターンの中核をなすInvocable Apexの例を示します。このApexクラスは、Flowから呼び出され、渡された取引先責任者のリストの姓をすべて大文字に変換して返す、というシンプルな処理を行います。このような再利用可能なコンポーネントを作成することで、同様の要件が他のFlowで発生した場合でも、コードを再利用できます。

以下のコードは、Salesforce Developerの公式ドキュメントに基づいています。

Invocable Apexの例:

public class ProcessContactNames {

    // @InvocableMethodアノテーションにより、このメソッドがFlowなどの外部ツールから呼び出し可能であることを示します。
    // label属性は、Flow BuilderのUIに表示されるアクション名です。
    // description属性は、そのアクションが何を行うかの説明です。
    @InvocableMethod(label='Process Contact Last Names' description='Accepts a list of contacts and sets the last name to all caps.')
    public static List<Contact> processNames(List<Contact> contacts) {
        
        // 結果を格納するための新しいContactリストを初期化します。
        List<Contact> processedContacts = new List<Contact>();

        // Flowから渡されたContactのリストをループ処理します。
        for (Contact c : contacts) {
            // 新しいContactインスタンスを作成します。
            // Flowに返すために、IDと変更したい項目のみを含めるのがベストプラクティスです。
            Contact processedContact = new Contact();
            processedContact.Id = c.Id;
            
            // 姓がnullでないことを確認し、大文字に変換します。
            if (c.LastName != null) {
                processedContact.LastName = c.LastName.toUpperCase();
            }
            
            // 処理済みのContactをリストに追加します。
            processedContacts.add(processedContact);
        }
        
        // 処理済みのContactリストをFlowに返します。
        // Flowはこの戻り値を受け取り、後続の「レコードを更新」要素などで使用できます。
        return processedContacts;
    }
}

このApexクラスを組織にデプロイすると、Flow Builderのアクション要素で「Process Contact Last Names」という名前のアクションが選択可能になります。これにより、管理者はコーディングの知識がなくても、このカスタムロジックを自身のFlowに組み込むことができるようになります。


注意事项

Flowは強力なツールですが、その力を最大限に引き出し、システムの安定性を損なわないためには、いくつかの重要な点に注意する必要があります。

ガバナ制限とパフォーマンス

  • トランザクションあたりの実行要素数: 1つのトランザクション内で実行できるFlow要素の数は2,000に制限されています。ループ内でDML操作やSOQLクエリを実行する("pinking"と呼ばれるアンチパターン)と、この制限に容易に達してしまうため、ループの前に必要なデータを一括で取得し、ループの後で一括で更新する「Bulkification (一括処理)」の原則を徹底する必要があります。
  • CPU時間: 複雑なロジックや非効率な処理は、CPUタイムアウトを引き起こす可能性があります。特に大量のデータを扱うスケジュールトリガーフローでは注意が必要です。
  • Before-Save vs. After-Save: 前述の通り、同一レコードの項目更新はBefore-Save Flowを優先することで、パフォーマンスを大幅に向上させることができます。これは最も重要なアーキテクチャ上の決定事項の一つです。

エラーハンドリング

本番環境で運用される自動化プロセスには、堅牢なエラーハンドリングが不可欠です。FlowではFault Path (フォルトパス) を利用して、DML操作やApexコールアウトの失敗をキャッチできます。エラーが発生した際には、システム管理者にメールで通知する、カスタムの「エラーログ」オブジェクトに記録を残す、あるいはユーザーに分かりやすいエラーメッセージをScreen Flowで表示するなど、適切な対応を設計に組み込む必要があります。

セキュリティと実行コンテキスト

  • Flowの実行コンテキスト: Flowは、トリガーの種類に応じて「ユーザーコンテキスト」または「システムコンテキスト」で実行されます。例えば、Screen Flowは通常、実行ユーザーの権限(ユーザーコンテキスト)で動作しますが、Autolaunched Flowはシステムコンテキストで動作し、オブジェクトや項目レベルのセキュリティをバイパスできます。この違いを理解し、意図しないデータアクセスや更新が発生しないように設計することが重要です。
  • Invocable Apexの共有設定: Flowから呼び出されるApexクラスは、デフォルトでは共有設定を無視する (`without sharing`) コンテキストで実行されます。実行ユーザーの共有ルールを適用したい場合は、クラス定義に`with sharing`キーワードを明示的に指定する必要があります。

まとめとベストプラクティス

Salesforce Flowは、現代のSalesforceプラットフォームにおける自動化戦略の中核です。アーキテクトとして、私たちはFlowを個々の自動化ツールとしてではなく、システム全体のアーキテクチャの一部として捉え、長期的な視点で設計を行う必要があります。

アーキテクチャ上のベストプラクティス:

  1. トリガーの集約とオーケストレーション: 「1つのオブジェクトに対し、トリガー種別(作成/更新/削除)ごとに1つのRecord-Triggered Flow」という原則(またはそれに類する集約アプローチ)を採用し、実行順序を制御します。これにより、自動化の競合や意図しない動作を防ぎ、デバッグと保守を容易にします。複雑なロジックはSubflow(サブフロー)に分割し、メインのトリガーフローから呼び出すことで、モジュール性を高めます。
  2. 適切なツールの選択: Flowは万能ではありません。非常に大量のレコード(数万件以上)を一括処理する必要がある場合は、Batch Apexの方が適しています。リアルタイム性の高い複雑なUI要件にはLightning Web Components (LWC) が、プラットフォームのコアなロジックや複雑な検証ルールの実装にはApexトリガーが依然として有効な選択肢です。要件に応じてFlow、Apex、LWCを適切に使い分けることが、優れたアーキテクチャの証です。
  3. 命名規則とドキュメント: Flow、変数、要素には、その目的が明確にわかるような一貫した命名規則を適用します。また、FlowのDescription(説明)欄を活用し、ロジックの概要、変更履歴、関連する要件ドキュメントへのリンクなどを記載することで、将来のメンテナンス担当者が迅速に内容を理解できるようにします。
  4. 再利用性の追求: 共通のロジックはSubflowとして切り出し、複数のFlowから呼び出せるように設計します。同様に、特定のビジネスロジックをカプセル化したInvocable Apexを作成することで、宣言的なツールとプログラム的なツールの両方から再利用可能なコンポーネントライブラリを構築します。
  5. ガバナンスの確立: 誰がFlowを作成・変更できるか、どのようなテストプロセスを経るべきか、本番環境へのデプロイ方法は何か、といったガバナンスルールを定義し、徹底します。CI/CDパイプラインにFlowのメタデータを含め、バージョン管理と自動テストを行うことで、品質と安定性を確保します。

Flowを戦略的に活用することで、ビジネスの変化に迅速に対応できる、スケーラブルで保守性の高いSalesforceソリューションを構築することが可能です。アーキテクトの役割は、そのための最適な設計指針を示し、プロジェクトを成功に導くことです。

コメント