アーキテクチャパターン
適切に設計されたリソースとコストの最適化 → 最適化の責任についての詳細
このページでは、機能単位、懸念の分離、状態管理、API 管理、メッセージングなど、アーキテクチャの懸念事項に関する包括的なパターンガイダンスが提供されます。これらのパターンは、サービス境界、データアクセスパターン、コンポーネントの責任に関する慎重な設計上の決定を通じて、長期的なソリューションの成功を形成します。
パターン
| 参照すべき場所 | 外観 |
|---|---|
| Apex クラス | ✅ サービスクラスは、目的を明確に示す名前 (AccountService、OrderProcessor、InventoryManager) を使用して単一責任の原則に従います。各サービスクラスは、1 つのドメインまたはビジネス機能に焦点を絞ります。サービスクラス内のメソッドには、20 行未満の 1 つの集中した責任があります。 |
| トリガー | ✅ トリガーは、ビジネスロジックを直接含めるのではなく、ハンドラークラスに委任します。コンテキストごとに明確なメソッド名を使用して一貫して使用されるトリガーハンドラーパターン (handleBeforeInsert、handleAfterUpdate)。ハンドラークラスは、トリガーイベントごとにロジックを整理し、メソッドごとに 1 つの責任を割り当てます。 |
| Lightning Web コンポーネント | ✅ コンポーネントは単一責任の原則に従い、設定用の明確なプロップインターフェースを備えています。各 LWC は 1 つの UI の懸念事項 (データ表示、ユーザー入力、ナビゲーション) に焦点を絞ります。一体式の実装ではなく、構成用に設計されたコンポーネント。 |
| サービスレイヤー | ✅ サービスクラスは、エントリポイント (トリガー、API、フロー、バッチ) に依存しないビジネスロジックをカプセル化します。同じサービスクラスで重複のない複数の呼び出しコンテキストが処理されます。サービスレイヤーでは、プレゼンテーションやデータアクセスに関する懸念からビジネスルールが分離されます。 |
| 再利用可能なコンポーネント | ✅ 複数のプロジェクトやチームで再利用できるように設計されたコンポーネント。カスタムメタデータ型を使用する設定駆動型の動作により、コードのリリースなしで動作を変更できます。呼び出し可能なアクションでは、Apexロジックがフローおよび外部オーケストレーションで使用できる宣言型ビルディング ブロックとして公開されます。 |
アンチパターン
| 参照すべき場所 | どんな悪い感じか |
|---|---|
| 神クラス | ⚠️ 1つのクラスで過剰な責任を蓄積しないでください。大きなクラス (500 行以上) を 1 つの責任で焦点を絞ったクラスに分割します。クラスが複数の関連のない懸念を処理する場合、クラスを再編成します (OrderProcessor はメールの送信とレポートも処理しないでください)。 |
| 混在する懸念 | ⚠️ トリガーロジック、ビジネスルール、データアクセスを 1 つのクラスに混在させないでください。コントローラーで表示ロジックをビジネスロジックから分離します。インテグレーションの懸念事項はコアドメインロジックから分離します。 |
| Triggers のトリガーロジック | ⚠️ トリガーファイルに直接ビジネスロジックを埋め込むことは避けてください。ネストされた条件付きで 300 行以上のトリガーを使用しないでください。トリガーコンテキストによる明確なメソッド構成を使用して、常にハンドラークラスに委任します。 |
パターン
| 参照すべき場所 | 外観 |
|---|---|
| ビジネスロジック | ✅ トリガー、コントローラー、一括処理クラスに分散することなく、サービスクラスで一元化されたビジネスルール。ドメインクラスは、レコードがシステムに入力される方法に関係なく、レコードレベルの動作 (検証、デフォルト値、派生値) を一貫してカプセル化します。エントリポイント間で重複するのではなく、サービスレイヤーで再利用されるロジック。 |
| データアクセス | ✅ リポジトリまたはセレクターパターンクラスの背後で抽象化されたデータアクセス。SOQL クエリはセレクタークラス (AccountSelector、OpportunitySelector) で一元化され、項目リストと WHERE 句の一貫性が確保されます。リポジトリパターンを使用すると、ビジネスロジックを変更することなく、疑似データソースを使用してテストできます。 |
| インターフェイス契約 | ✅ コンポーネントは実装の詳細ではなく、明示的なインターフェースを介して通信します。Apex インタフェースは、レイヤー間の契約を定義します。カスタムメタデータ設定では、動作の境界を定義します。プラットフォームイベントは、生産者と消費者間のメッセージング契約を提供します。 |
| モジュール境界 | ✅ 境界付きコンテキストでは、データモデルとビジネスルールの明確な所有者境界を定義します。各モジュールは、そのデータ、自動化、ビジネスロジックを所有します。モジュールは、データベースオブジェクトを直接共有するのではなく、定義済みの API を介してやりとりします。ドキュメントでは、どのチームがどのオブジェクトとサービスを所有しているかを明確に示します。 |
| 連動関係フロー | ✅ 連動関係は一方向 (プレゼンテーション → ビジネス → データ) に流れます。コアビジネスロジックは外部に依存しないため、独立した進化が可能です。インフラストラクチャの問題 (ロギング、キャッシュ、外部 API) は、インターフェイスを介したビジネスロジックに依存します。その逆ではありません。 |
アンチパターン
| 参照すべき場所 | どんな悪い感じか |
|---|---|
| ロジックの複製 | ⚠️ トリガー、API エンドポイント、バッチクラス間でビジネスロジックが重複しないようにします。サービスレイヤーで一元化し、エントリポイント全体で再利用します。同じビジネスルールが複数のクラスに表示されるたびに、共有サービスに抽出します。 |
| 分散データアクセス | ⚠️ 項目リストと WHERE 句が一貫していないトリガークラス、コントローラークラス、バッチクラスに SOQL クエリが分散しないようにします。セレクタークラスでクエリを一元化することで、パターンの一貫性を確保し、LDV の最適化を 1 か所で実現できます。 |
| トリガーのビジネスロジック | ⚠️ トリガーコードに直接組み込まれている入力規則、項目の計算、ワークフローオーケストレーションは避けてください。サービスクラスまたはドメインクラスに移動します。トリガーは薄くし、適切なハンドラーへの委任のみに焦点を絞ります。 |
| コントローラのビジネスロジック | ⚠️ Aura/LWC コントローラーメソッドでの複雑な計算、検証、データ操作は避けてください。コントローラーは、ビジネスルールを直接実装するのではなく、サービスレイヤーへのコールを調整する必要があります。 |
| 循環連動関係 | ⚠️ A が B に依存し、B が A に依存する循環型の連動関係を持つパッケージやクラスは避けます。共通の懸念事項を別のモジュールに抽出したり、連動関係の方向を反転したり、イベント駆動型通信を使用して結合を解除したりして解決します。 |
パターン
| 参照すべき場所 | 外観 |
|---|---|
| プラットフォームキャッシュ (組織パーティション) | ✅ カスタムメタデータルックアップ、選択リスト値、構成設定、コストのかかる操作の計算結果など、組織パーティションにキャッシュされた頻繁にアクセスされる参照データ。データの変動性に基づいて設定されるデフォルトの TTL (毎月更新される参照データの場合は時間、頻繁に更新される設定の場合は分)。キャッシュキー戦略により、さまざまなデータ型での競合を回避できます。 |
| プラットフォームキャッシュ (セッションパーティション) | ✅ セッションキャッシュに保存されるユーザー固有の設定、計算されたパーソナライズデータ、セッション範囲の状態。ユーザー間で共有する必要があるデータに使用されないセッションキャッシュ。キャッシュ無効化戦略では、ユーザー設定の更新が適切に処理されます。 |
| Lightning Data Service | ✅ LDSは、Lightning Webコンポーネントのクライアント側レコードの自動キャッシュを提供します。標準の CRUD 操作では、カスタム Apex コントローラではなく LDS が使用されます。LDS により、冗長なサーバの往復が不要になり、UI の更新が楽観的になります。コンポーネントでは、ページ全体で共有 LDS キャッシュが使用されます。 |
| カスタムメタデータ型 | ✅ クラスでハードコードされるのではなく、カスタムメタデータ型に保存される設定ルールと動作ルール。変更セットまたはソース駆動型開発を介して環境全体にリリースできるカスタムメタデータ。カスタムメタデータへの変更では、リリースサイクル全体は必要ありません。パフォーマンスのために、カスタムメタデータクエリをプラットフォームキャッシュにキャッシュします。 |
アンチパターン
| 参照すべき場所 | どんな悪い感じか |
|---|---|
| Query in Loop | ⚠️ 反復ループ内で SOQL を実行しないでください。ループ外の 1 つの SOQL ステートメントですべての必要なレコードを照会します。反復時に参照できるように、結果を親 ID で Maps に整理します。これは、1 つの最も一般的な Salesforce アンチパターンです。 |
| 繰り返しクエリ | ⚠️ トランザクションごとに同じカスタムメタデータ、カスタム設定、参照データを複数回照会しないでください。1 回照会し、プラットフォームキャッシュまたはトランザクション静的変数にキャッシュし、トランザクション全体で再利用します。 |
| ミッシングキャッシュ戦略 | ⚠️ 頻繁にアクセスされる参照データをキャッシュせずに繰り返し照会しないでください。カスタムメタデータ、設定、および計算結果用のプラットフォームキャッシュを実装します。データのボラティリティに基づいて適切な TTL を定義します。 |
| 無効化なしのキャッシュ | ⚠️ 無効化戦略を考慮しないでデータをキャッシュしないでください。更新頻度に適したキャッシュ TTL を定義します。TTL だけでは不十分な場合、ソースデータが変更されたときにキャッシュを手動でクリアします。 |
| 未管理セッション状態 | ⚠️ 検証なしでセッション状態がページナビゲーション全体で保持されると想定しないでください。Lightning コンポーネントは、ページ読み込み時の状態更新を処理する必要があります。Lightning データ サービスを使用して自動的に状態を同期します。 |
パターン
| 参照すべき場所 | 外観 |
|---|---|
| ソリューションアーキテクチャ計画 | ✅ アーキテクチャ計画は、要件分析 (機能および非機能)、予測されるデータ量のガバナ制限分析、要件に適したパターンの選択、主要なコンポーネントとインターフェースを定義するコンポーネント設計など、大規模な構築投資の前に実行されます。 |
| デザインパターンの選択 | ✅ ビジネスロジックの再利用のためのサービスレイヤーパターン、データアクセスの抽象化のためのリポジトリ/セレクターパターン、交換可能なアルゴリズムのための戦略パターン、レコードレベルの動作のためのドメインパターン、一貫したトリガー整理のためのトリガーハンドラーパターンなど、実績のある Salesforce 設計パターンが一貫して適用されます。 |
| アーキテクチャ決定レコード | ✅ バージョン管理に保存されている ADR で重要なアーキテクチャ上の決定が文書化されている。ADR は、コンテキスト (ビジネスの推進要因、技術的な制約)、決定 (選択された内容)、考慮された代替案 (他のユーザーが却下した理由)、結果 (トレードオフ、技術的負債、再訪問トリガー) を取得します。 |
| Build vs Buy Evaluation (構築評価と購入評価の比較) | ✅ AppExchange評価は、総所有コスト分析を使用したカスタム開発の決定の前に行われます。評価基準には、戦略的価値 (競合製品との差別化要因)、TCO の比較 (構築工数、メンテナンス、アップグレードコスト)、インテグレーションの複雑さ、ソリューションが適切でない場合の終了コストが含まれます。 |
| ガバナ制限分析 | ✅ アーキテクチャ計画では、予想されるデータ量とトランザクションパターンに基づいて、どのガバナが最も制約設計を制限するかを特定します。ピーク状態で 1 つのガバナ制限の 80% 未満しか消費しないように設計されたトランザクション。成長、将来の機能、および予期しない使用パターンのために構築されたマージン。 |
| リスク評価 | ✅ プラットフォームの境界を押し広げるアーキテクチャアプローチで特定された技術リスク。重大なリスクごとに定義された緩和戦略。完全な構築コミットメントの前に、プロトタイプまたは概念実証作業でリスクの高い技術的アプローチの前提条件を検証します。 |
アンチパターン
| 参照すべき場所 | どんな悪い感じか |
|---|---|
| 計画なし | ⚠️ データ量の分析、ガバナ制限の影響、パターンの選択なしで構築を開始することは避けてください。アーキテクチャ計画ワークショップでは、構築を開始する前に主要な制約を特定し、パターンを選択して、ガバナ制限に照らして検証する必要があります。 |
| 文書化されていない決定 | ⚠️ コンテキスト、論理的根拠、代替案、結果を把握せずにミーティングでアーキテクチャに関する意思決定を行わないようにします。バージョン管理に保存されているアーキテクチャ決定レコードを使用して、将来のチームメンバーの決定コンテキストを保持します。 |
| No Build vs Buy Analysis (ビルド分析と購入分析なし) | ⚠️ AppExchange 評価なしでカスタムソリューションを構築することは避けてください。カスタム開発の前に上位 3 ~ 5 個の関連パッケージを評価します。実装作業、メンテナンス、アップグレードコスト、終了コストなどの TCO を比較します。 |
| アンダーエンジニアリング | ⚠️ 増加予測のない現在のデータ量のみの設計は避けてください。2 ~ 3 年間のデータ増加を予測します。5 ~ 10 倍の現在の量に対して検証された選択性を使用してクエリパターンを設計します。成長のためのアーキテクチャマージンを構築します。 |
パターン
| 参照すべき場所 | 外観 |
|---|---|
| 第二世代管理パッケージ (2GP) | ✅ 名前空間の分離、AppExchangeの配信、IP保護が必要な新しい管理パッケージに使用される2GP。モジュールアプリケーション開発を使用したソース駆動型開発ワークフロー。パッケージ連動関係は明示的に管理されます。セマンティックバージョン管理でリリースされたバージョン。 |
| ロック解除済みパッケージ | ✅ 名前空間の制約のないモジュール性を必要とする内部エンタープライズアプリケーションに使用されるロック解除済みパッケージ。組織に依存するアーティファクトのないパッケージの独立したリリース。適切なリリース順序で追跡されるパッケージ連動関係。内部パッケージに対して定義されたバージョン管理戦略。 |
| モジュール境界 | ✅ パッケージごとに定義された所有者境界をクリアします。各パッケージは、そのデータモデル、ビジネスルール、自動化を所有します。パッケージは、直接オブジェクトにアクセスするのではなく、定義されたインターフェースを介してやりとりします。ドキュメントにより、パッケージの所有権とパッケージ間契約が識別されます。 |