システム設計tips

##### 目録：
- salesfroce
    - [フローの命名規則](#フローの命名規則)
        - [メタフローの命名](#メタフローの命名)
        - [フロー要素](#フロー要素)
    - [フィールド規則](#フィールド規則)
      - [一般規則](#一般規則)
      - [フィールドのグループ化](#フィールドのグループ化)
    - [検証ルールの規則](#検証ルールの規則)
      - [検証ルールのメタデータ規約](#検証ルールのメタデータ規約)
      - [検証ルールの記述規約](#検証ルールの記述規約)
    - [フロー構造規則](#フロー構造規則)
      - [フローごとの設計](#フローごとの設計)
      - [クロスフロー設計](#クロスフロー設計)
      - [ドメイン駆動設計](#ドメイン駆動設計)
      - [レコードトリガーフローの設計](#レコードトリガーフローの設計)
      - [遅延アクションについて](#遅延アクションについて)
    - [apex命名規則](#apex命名規則)
        - [Apexクラス](#apexクラス)
        - [Apexバッチクラス、スケジューラブルクラス、キューアブルクラス](#apexバッチクラス-スケジューラブルクラス-キューアブルクラス)
        - [apexトリガー](#apexトリガー)
        - [apexテストクラス](#apexテストクラス)
        - [apexメソッド](#apexメソッド)
        - [apex変数](#apex変数)
        - [apex定数](#apex定数)
        - [apexタイプ名](#apexタイプ名)

---
### フローの命名規則
*本ページの内容は[SFXD Wiki-Flow Naming Conventions](https://wiki.sfxd.org/books/best-practices/page/flow-naming-conventions)の翻訳*

すべての接頭辞は大文字。接頭辞の後のすべての名前はキャメルケース( camelCase )であり、指定された場所以外ではアンダースコアは付けない。下部のテーブルには、ほとんどのケースの例が含まれています。

#### メタフローの命名
1. フロー名は常に、フロー開始の[ドメイン](https://flt.backlog.jp/alias/wiki/1075654694#loom-header-3)名で始まり、その後にアンダースコアが付く。ほとんどの場合、フローのドメインは、フローが作用されているオブジェクトと同じ。
構造上の規則に従って、複数オブジェクト間のフローの使用は避けるべき、複数オブジェクト間のフローを使用の場合、イベントを作成し、オブジェクト間の操作を行う。
2. ドメインの後で、次の場合に応じて、フローのタイプを示すコードを付く：
     1. フローが画面フローの場合、「SCR」を付く。
     2. フローがサブフローの場合、「SFL」を付く。
     3. フローがバッチ実行且つスケジュールされる場合、「BAT」を付く。
     4. フローがレコードトリガーフローの場合、「TRG」を付く。さらに、フロー名には実行タイミング（BEFORE or AFTER）を含む、その後にCreate、CreateUpdate、Updateのいずれかを付く。
     5. フローがイベント トリガーフロー の場合、「EVT」を付く。
     6. フローがレコード トリガーフロー 、且つ電子メール送信のみを処理する場合、「EML」を付く。
3. フロー名は、出来る限り実行されるアクションで命名。トリガーされたフローの場合、トリガーは何なのかを記録。下記テーブルの例を参照してください。
4. フローの説明は、フローの実行に必要なもの、機能的に何を行うのか、何を出力するのかを常に示す必要がある。

読みやすいフローの例：

| 種類  | 名前 | 説明 |
| ------------- | ------------- | ------------- |
| 画面フロー | QUOTE_SCR_AddQuoteLines |見積明細追加ページをオーバーライドするために使用される画面フロー。「discounts_cmtd」に基づく割引計算に関連する機能を提供します。 |
| スケジュールされたフロー | CONTACT_BAT_SendBirthdayEmails | 毎日実行されるスケジュールされたフロー。連絡先に誕生日メールを送信する期限があるかどうかを確認し、テンプレート「Marketing_Birthday」を使用してメールを送信 |
| 取引先レコード、アップデート前のフロー | ACCOUNT_TRG_BeforeUpdate | 取引先レコード更新前の自動起動トリガーフロー。詳細は機能一覧を参照 |
| 取引先レコード、アップデート後のフロー | ACCOUNT_TRG_AfterUpdate | 取引先レコード更新後の自動起動トリガーフロー。詳細は機能一覧を参照 |
| 商談レコード、レコードトリガーフロー。商談が成立し、アクションが実行され、「Sales Finished」イベントが発生 | OPP_TRG_BeforeUpdate | 商談レコードが更新される前の自動起動トリガーフロー。詳細は機能一覧を参照 |
| イベントトリガーフロー、請求書を作成。「Sales Finished 」イベントが発生後トリガーが起動 | INVOICE_EVT_SalesFinished | インボイスを作成し、売上情報に基づいて新しいインボイスを検証するようインボイス作成部門に通知する |
| 取引先レコード、レコードトリガーフロー。電子メール送信 | ACCOUNT_EML_BeforeUpdate | 取引先レコード変更後、通知メールを送信 |


#### フロー要素
##### データ操作言語 (Data Manipulation Language)
1. データ取得の時、オブジェクトの場合は「Get」で開始、その後にアンダースコアを付ける。CMTD(Custom Metadata Type Driven)またはSettingsの場合は「FETCH」で開始。
2. 更新は「Update」で開始、その後にアンダースコアを付ける。コレクションを更新する場合は、前述のアンダースコアの後に「List」を追加。
3. 作成は「Create」で開始、その後にアンダースコアを付ける。コレクションを更新する場合は、前述のアンダースコアの後に「List」を追加。
4. 削除は「Del」で始まり、その後にアンダースコアを付ける。コレクションを削除する場合は、前述のアンダースコアの後に「List」を追加。

読みやすいフローの例：

| 種類  | 名前 | 説明 |
| ------------- | ------------- | ------------- |
| フロー内の画面 | ラベル: 価格表エントリの選択  名前: S01_SelectPBEs | 取得した価格表エントリーに基づき、どの商品を見積りに追加するかを選択 |
| フロー内のDMLに基づいてエラーを処理する画面 | ERROR_GET_PBE | 価格表エントリの GET が失敗した場合。おそらく権限に関連している。 |
| フローの最初の画面のテキスト要素 | S01_T01 | テキスト要素の実際のテキストを入力 - 説明フィールドはありません |
| フローの最初の画面のデータテーブル | S01_LWCTable_Products | LWC が説明フィールドを提供していない可能性があるため、適用できない可能性がある。 |

##### インタラクション
1. すべての画面は「S」で始まり、その後にアンダースコアを付ける、現在のフロー内の画面数に 1 をプラスし、後に付ける。
2. アクションは「ACT」で始まり、その後にアンダースコアを付ける、アクション名はアクションが何を実行するかを示す。
3. APEX アクションは「APEX」で始まり、その後にアンダースコアを付ける、その後に期待される結果の短縮形を付ける。
4. サブフローは「SUB」で始まり、その後にアンダースコアを付ける、その後にトリガーされたフローのコード (FL01 など)、その後にアンダースコア、その後に期待される結果の短縮形を付ける。
5. 電子メール アラートは「EA」で始まり、その後にアンダースコアを付ける、その後に送信される電子メール テンプレートのコード、アンダースコア、および送信する電子メールの短縮形を付ける。


##### 画面要素
1. 変数は常に「var」で始まり、その後にアンダースコアを付ける。
    - コレクションを格納する変数は、「coll」で始まり、その後にアンダースコアを付ける。
    - レコードを格納する変数は、「sObj」で始まり、その後にアンダースコアを付ける。
    - 他の変数タイプは常に変数タイプのインジケーターで始まり、その後にアンダースコアを付ける。
2. 数式は「form」で始まり、その後にアンダースコアを付ける、その後ろに返されるデータ型とアンダースコアを付ける。
3.  選択肢は「ch」で始まり、その後にアンダースコアを付ける。選択肢の名前は、選択肢の結果を反映したものになる。

Text要素を含む画面の例：

| 種類  | 名前 | 説明 |
| ------------- | ------------- | ------------- |
| 販売された商品の総数を取得する式 | formula_ProductDiscountWeighted | 商品の種類によって割引を重み付ける、実際の最終的な割引を計算。割引または価格のNULL値をキャッチし、0を返す。 |
| RecordIdを格納する変数 | recordId | フローを開始するレコード ID を格納。 *従来の Salesforce の動作のため、通常の規則から除外されます。注: この変数名は大文字と小文字が区別されます。*  |
| ループ内のフローで計算された値から作成したレコードを、コレクション変数に格納する前にすべて作成する | sObj_This_OpportunityProduct | 計算された商談商品の値 |

変数と画面要素の例を含むスクリーンショット：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/d8cf08d9-903d-cb8e-cc0c-15f4159235c0.png)



##### ロジック
1. すべての「決定」は、その決定がオープンな選択肢であれば「DEC」で、ロジックの最終確認（logical terminator）であれば「CHECK」で開始し、その後にアンダースコアを付ける。アクション名(Action Name)にはさらに、Is、Can、または決定の性質を示す他の副詞と、 チェックされる内容の短い説明を先頭に付ける。
    - いかなる決定結果も、接頭辞のない決定名(Decision Name)で始まり、アンダースコア(Enderscore)、 結果(Outcome)の順番で付ける。
    - デフォルトの結果は、エラー処理に使用されるべき、該当する場合はERRORとリラ ベルされるべき。
2. 割り当ては常に SET、ASSIGN、STORE、REMOVE、または CALC（実行される割り当てのタイプによる）で始まり、その後にアンダースコアを付ける。
    - 「SET」は変数の更新に使用される、主にオブジェクトの変数。
    - 「ASSIGN」は変数の初期化や非オブジェクト変数の更新に使用。
    - 「STORE」はコレクションに要素を追加するときに使用。
    - 「REMOVE」はコレクションから要素を削除するときに使用。
    - 「CALC」は数学的な代入や複雑なコレクション操作に使用。
3. ループは「LOOP」で始まり、アンダースコアが続き、繰り返し処理される内容の説明が続く。これはコレクション名とは異なる場合があります。

| 種類  | 名前 | 説明 |
| ------------- | ------------- | ------------- |
| sObj_This_OpportunityProduct レコード値を設定 | SET_OppProdValues | 計算された割引と数量に基づいて商談商品を設定 |
| コレクション変数に商談商品を格納 | 名前： STORE_ThisOppProd  <br>格納： {sObj_coll_OppProdtoCreate} add {sObj_This_OpportunityProduct}  | コレクションにに計算されたOpp Prod行を追加 |
| コレクション sObj 変数に格納する複数のレコードを作成する| CREATE_OppProds | OppProdを作成 |
| 処理のために選択された要素を決定 | 決定： CHECK_PBESelected  <br>結果1：CHECK_PBESelected_Yes  <br>結果2：CHECK_PBESelected_No  <br>デフォルトの結果： 致命的な失敗 | 少なくとも1行が選択される、そうでない場合エラー画面で終了 |
| 基準に基づいて要素を並べ替える決定 | 決定： DEC_SortOverrides  <br>結果：SortOverrides_Fields  <br>結果2：SortOverrides_Values  <br>結果3：SortOverrides_Full  <br>デフォルトの結果：致命的な失敗 | ユーザーの選択に基づいて、レコード内の情報を上書きする必要かどうか、どの情報を上書きする必要があるかを確認 |
| フローから請求書受領を通知するアラートメールを送信 | EA01_EI10_InvoiceReceived | 支払請求書の詳細を含むテンプレートEI10を送信 |



### フィールド規則
#### 一般規則
*本ページの内容は[SFXD Wiki-General Conventions](https://wiki.sfxd.org/books/best-practices/page/general-conventions)の翻訳*

すべての命名規則はRFC 2119およびRFC 6919に準拠する。
1. すべてのフィールドAPI名は、ラベルが他の言語で書かれている場合でも、英語で書かれなければならない。
2. 全てのフィールドAPI名はPascalCaseで書かれなければならない。
3. この規約で明示的に定義されている場合を除き、フィールド名にアンダースコアを含んではならない。
4. フィールドは通常、説明を含まなければなりません。
5. フィールド名を読んだだけではフィールドの目的全体が明らかでない場合、フィールドは説明を含まなければならない。
6. フィールドの目的が曖昧な場合、フィールドはヘルプテキストを含まなければならない。目的が明確な場合、分かりやすくするためにヘルプテキストを定義することも可能である。
7. フィールドAPI名は以下の接頭辞と接尾辞を尊重すべきである *[追加説明２]* 。接頭辞と接尾辞の前にアンダースコアを付けてはならない。

| フィルド種類  | 接頭辞 | 接尾辞 |
| ------------- | ------------- | ------------- |
| マスター詳細(MasterDetail) |  | Ref |
| ルックアップ(Lookup) |  | Ref |
| 計算式(Formula) |  | Auto |
| ロールアップサマリ(Rollup Summary) |  | Auto |
| 自動操作(APEX)(Filled by automation) *[追加説明１]*|  | Trig |
|  ピックリスト or マルチピックリスト(Picklist or Multipicklist) |  | Pick |
| ブール値(Boolean) | Is or IsCan *[追加説明３]*  |  |

追加説明：
1. *ワークフロー、プロセスビルダー、およびフローはこのロジックに含まれない。理由として、これらの自動操作はフィールド名の変更をエラーなしで許可する、また管理者が変更することができる。もしフィールドが自動操作によって埋められることを唯一の目的として作成される場合（例えば、ロールアップサマリーで使用されるフィールド）、コンサルタントは、ユーザが自分でデータを設定できないことを示すため、Trig接尾辞を使用する。* 
2. *数値、通貨、パーセンテージのフィールドが容易に認識できるようにするなど、他のフィールドタイプの規範も検討されたが、管理者にとって制約が多すぎるので破棄された。この場合の型の不一致の修正は、TEXT()またはVALUE()関数を使用して値を正しい型にキャストすることで簡単に解決できます。*
3. *”IsCan”は "Can "を置き換えます。例えばCanActivateContractはIsCanActivateContractになります。これは、1つのクエリでページ上のすべてのチェックボックスを検索できるようにするためです。* 


#### フィールドのグループ化
*本ページの内容は[SFXD Wiki-Grouping fields](https://wiki.sfxd.org/books/best-practices/page/grouping-fields)の翻訳*

1. 組織が複数のサービス持つ場合、フィールドAPI名の先頭に、そのフィールドが使われるサービス名を付け、その後にアンダースコアを付ける。
    -  オブジェクトを使用するサービスが1つだけの場合、上記ルール当てはまらない。
2. 複数のサービスがフィールドを使用する場合、またはフィールドが他のサービスによって使用される前に、既に他のサービスに使用される場合、フィールドAPI名の前には、ユーザ視点の機能説明とアンダースコアを付ける。フィールドの説明(Description)は、どのサービスがそのフィールドを使用するかを示さなければならない[追加説明１]。
3. フィールドが異なるサービスによって異なる用途で使用される場合、フィールドの説明には各用途の概要説明を含めなければならない。
4. フィールドが技術的な理由で値をホストするために作成されるが、ユーザーに表示されないか、表示されるべきでない場合、API名の先頭に「TECH」とアンダースコアを付けなければならない。
5. 1つのオブジェクトに50以上のフィールドが作成される場合、コンサルタントは、技術的なフィールドと同じように、「$Groupname」の後にアンダースコアが続く形式で、フィールドをグループ化するために接頭辞を使用することを検討するべきである。

| オブジェクト | フィールド種類 | コメント | フィールドラベル | フィールドAPI名 | フィールド説明 |
| ------------- | ------------- | ------------- | ------------- | ------------- | ------------- |
| ケース（Case）  | 参照 | 取引先を参照 | Service Provider | ServiceProviderRef__c | 顧客と連絡を取るサービス提供者にケースを紐つく。 |
| 取引先（Account） | 数式 | 経理部門専用 | Solvability |  	Accounting_SolvabilityAuto__c | 収益と費用に基づいて解決可能性を計算します。センシティブなデータは共有されるべきではありません。 |
| 取引先責任者（Contact） | Checkbox |  | Sponsored ? |  IsSponsored__c| 連絡先が他のクライアントによってプログラムにスポンサーされた場合、チェックされます。 |

追加説明：
 *1. デプロイ後にAPI名を修正することは、複雑であることで知られているが、フィールドが適切に認識できるようにすることは、プロジェクト中にメンテナンスを避けるよりも長期的には良いことである。このような修正は、見積もりの際に考慮すべきである。* 



### 検証ルールの規則
#### 検証ルールのメタデータ規約
*本ページの内容は[SFXD Wiki-Validation Rule Metadata Conventions](https://wiki.sfxd.org/books/best-practices/page/validation-rule-metadata-conventions)の翻訳*

1.  検証ルール名(Validation Rule Name)は、その 検証ルールが何を防いでいるかを簡潔に説明する。このフィールドでは簡潔さがわかりやすさに優先することに注意してください。
2. すべての検証ルールのAPI名はPascalCaseで記述する。
3. この規約で明確に定義されている場合を除き、検証ルールはフィールド名にアンダースコアを含まない。
4. 検証ルールは常にオブジェクト名の省略形（例： ACC、VR）、その後にトリガーとなるオブジェクトの検証ルールの番号、その後にアンダースコアが続く。
5. 検証ルールのエラーメッセージには、[VRXX]（XXは検証ルール番号）の形式、検証ルールの番号を示すエラーコードを含まなければならない *[追加説明１]* 。
6. 検証ルールには説明（Description）を設けなければならない。説明には、VR のトリガとなる技術的な説明を含んではならない。

追加説明：
*1. ユーザが表示するメッセージにエラーコードを含めることは奇妙に思われるかもしれませんが、これによって管理者やコンサルタントは、ユーザがデバッグの目的でエンドコードを伝えるだけでよいとき、どの検証ルールが問題を引き起こしているかを正確に見つけることができます。*


#### 検証ルールの記述規約
*本ページの内容は[SFXD Wiki-Validation rules writing conventions](https://wiki.sfxd.org/books/best-practices/page/validation-rules-writing-conventions)の翻訳*

1. すべての検証ルールにはバイパスルール（Bypass Rule）のチェックを含めなければならない。
2. 可能な限り、コンサルタントは関数上の演算子を使用すべきである。
3. IF() はすべて CASE() に置き換えるべきである。
4. 他の式フィールドを参照することは絶対に避けるべきである。
5. すべての場合、ISNULL の代わりにISBLANK() を使用すべきである。
6. 検証ルールは、カスケード方式でトリガーしてはならない*[追加説明１]* 。

| 名前 | 計算式  | エラーメッセージ | 説明 |
| ------------- | ------------- | ------------- | ------------- |
| OPP_VR01_CancelReason |` !$User.IsCanBypassVR__c && TEXT(Cancellationreason__c)="Other" && ISBLANK(OtherCancellationReason__c)` | キャンセル理由で「その他」を選択された場合は、その理由を詳しくご記入ください。「OPP_VR01」 | コメントを入れずに「その他」を選択することを防ぐ。「OPP_VR01」 |
|OPP_VR02_NoApprovalCantReserve | `!$User.IsCanBypassVR__c && !IsApproved__c && ( ISPICKVAL(Status__c,"Approved - CC ") || ISPICKVAL(Status__c,"Approved - Client") || ISPICKVAL(Status__c,"Paid") ) `  | 承認されない場合、ステータスをそれ以上進めることはできない。「OPP_VR02」 | 承認されない場合、ステータスをそれ以上進めることはできない。「OPP_VR02」 |

追加説明：
*1. カスケード検証ルール（Cascading Validation Rules）とは、別の検証ルールがトリガされたときにトリガされる検証ルールです。例 ステータスが "Lost "の場合、あるフィールドは必須である、そのフィールドは5文字未満にはならない。この場合、2つ目のエラーは1つ目の条件が満たされた時点で表示されるべき。* 



### フロー構造規則
*本ページの内容は[SFXD Wiki-Flow Structural Conventions](https://wiki.sfxd.org/books/best-practices/page/flow-structural-conventions)の翻訳*

#### フローごとの設計
1. フローは、簡単に識別できるトリガー要素を1つ持つべきである。    
    これは[命名規則](https://flt.backlog.jp/alias/wiki/1075651340)に関連する。
    1. レコードトリガー型のフローの場合、識別要素は、DML(Data Manipulation Language)のトリガーとなるレコード。
    2. イベントベースのフローでは、識別要素は単一のイベント。
    3. スクリーンフローでは、識別要素は、単一のrecordId、単一のsObject変数、または単一のsObjectリスト変数のいずれかになります。そして、呼び出されるフローは、その入力と出力内容を確認。
    4. サブフローの場合、ルールはさまざまである。同じオブジェクトに対するクエリの繰り返しを避けるために、複数のコレクションをサブフローに渡すと便利な場合がある。しかし、複数の単一レコード変数や単一テキスト変数をサブフローに渡すことは、一般的にメインフローと過度に結合した設計を示し、より抽象化されるべきです。
    
    トリガー要素のネーミングの良い例：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/f5502890-51f7-fd1f-7fd7-66739f8384c4.png)

2. 説明を追加。
    説明は技術的なものではなく、機能的なものである。コンサルタントは、あなたのフローを読んで、それが何をするものかを知ることができるはずです。そのため、説明文は、そのフローが所定のドメイン（該当する場合）構成の中でどのような機能を提供するかを説明するものでなければならない。

    説明は技術的なものではない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/71105220-5b32-fd8c-3cf8-617aef5ff252.png)

3. すべてのDMLまたはQuery要素はエラー処理を持つべきである。
    画面フロー、画面を表示、どのような状況がこれにつながるかを表示する。
    レコードトリガーフロー、APEXの例外メール受信者にメールを送信する。そのロジックをサブフローに組み込んで、どこからでも呼び出せるようにする。
    あるいは通知を送る。 (sandbox内でメール配信の設定を「System Only」にしている場合、通常のフローメールやメールアラートは送信されません。)

    DMLが失敗すると、画面にエラーメッセージが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/4ff15302-cfbd-d082-022c-06846c153365.png)

4. ループの中でDMLやクエリーを行わない。（ズバリ：ループの中にピンクの四角マークを入れない。）
    Salesforce では、このような操作を行うと警告が表示されるようになりましたが、それでも言う必要があります。
    これを避けるには、処理したい1レコードをループ内のコレクション変数に代入し、フローの最後にループの外でDMLを実行します。[追加説明１]

    こんなことはするな。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/abbcb2cd-233d-f222-2712-92890cb156fc.png)

5. 様々な場所で同じロジックが発生している場合、そのロジックをサブフローにまとめ直すべきである。
    こうすることで、同じことを6カ所で修正する必要がなくなる。また、フローが読みやすくなる。[追加説明２]

6. 判定チェックに基づいてループを終了させないでください。
    Flowエンジンはそれをうまくサポートしておらず、メインループに戻ると奇妙で混乱した問題が発生する。

    ループは必ず終了させましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/e3d0ebdc-0db8-76a5-ac6b-b21e3eafc222.png)

7. 長いWait要素を持ち、何千ものレコードから呼び出されるようなFlowを設計しないでください。
    Paused Interviewの制限を超えてしまいます。このようなユースケースは、いずれにせよScheduledフローにすべきです。

8. 暗黙の参照に依存しないこと。
    これは、レコードにクエリを発行し、{MyRecord.ParentRecord__c.SomeField__c}で親レコードの情報を取得する場合です。これは便利ですが、エラーが発生しやすくなります（特にRecordTypeのようなフィールドで）。


#### クロスフロー設計
1. 1つのサブフローには、1つのRecord変数または1つのRecordコレクションのみを渡すようにしてください。
    [フローごとの設計](https://flt.backlog.jp/alias/wiki/1075654694#loom-header-1)項目 1 を参照。
    実行時に多くのレコード変数を初期化する場合、そのサブフローを異なる関数に分割できる。レコードをトリガー要素として渡し、設定情報を変数として渡す。

    例 - Pricebook2Id 変数は Order 変数から取得する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/cfa60ef4-6e4c-8b9c-e005-74e79727e7a6.png)

2. サブフローはできるだけ再利用する。
    多くの異なるアクションを実行するサブフローは、おそらく1回きりの使用となり、別のロジックでサブフローの一部が必要になった場合、再度Subflowを構築することになり、技術的負債が大きくなる可能性があります。
    可能な限り、各サブフローは単一のドメイン内で単一の関数を実行する。

3. 各フローは単一のドメインに関連付けられ、ドメイン間の通信はイベントによって処理されるべきである。
    [ドメイン駆動設計](https://flt.backlog.jp/alias/wiki/1075654694#loom-header-3)を参照。
    つまり、あるフローが営業（たとえば商談が成立したときに実行されるアクション）から始まり、請求書作成（請求書を作成し、その請求書の担当者に通知する）で終わる場合、これは2つの別々のフローであり、それぞれが単一のドメインに紐づいているべきである。

    この例では、Technician On SiteフローがInterventionが開始されたことを通知し、それがWork Order関連フローをトリガーしている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/c4befa13-9690-f028-38a9-7c54f6fd2979.png)

4. フロー間の通信は、重い結合を避けるために、イベントを介して処理されるのが理想的である。
    上の例では、営業で開始するフローが「商談が終了した」イベントを発生させ、それを「請求書発行を開始する」フローがlistenし、請求書発行に関連するアクションをトリガーする。
    上記の例を参照

5. サブフローが別のサブフローを呼び出し、そのサブフローがまた別のサブフローを呼び出すような接続は避けましょう。
    二次的サブフローが基本的に、あらゆるフローからの入力を処理する完全に抽象化されたメソッドでない限り（複数選択リストからコレクションを返すようなもの）、メンテナンスが複雑になり、コストがかかる。


#### [ドメイン駆動設計](https://martinfowler.com/tags/domain%20driven%20design.html)
1. フローを作成するときに、フローのドメインを特定する。1つのフローは、1つの帰属ドメインのみを持つべきである。

2. フロー内の別のドメインの要素を変更する必要がある場合は、代わりに現在のステータスに一致するイベントを発行し、そのイベントを使用して、帰属するドメインを持つ別のフローを開始する。

3. ドメインは、明確な担当[ペルソナ](https://trailhead.salesforce.com/ja/content/learn/modules/ux-personas-for-salesforce/get_started_with_personas)を持つ、独立した機能のグループとして定義。

    ドメイン間の高レベル通信
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/85d087a5-cdea-2374-eb4c-7dca7b7cd7d9.png)


#### レコードトリガーフローの設計
1. 何オブジェクトの何の操作（作成前、更新前、作成後）。
    BEFOREフロー以外のすべてのケースでは、サブフローを活用することで、実行順序とメンテナンス性を確保できる。
    BEFORE フローの場合、当面は 1 つのフローを作成し、決定ノードで関数を分割するのがベスト。
    1. BeforeUpdateの場合、"決定 "はプロセスビルダー様なを垂直ツリーで行い、実際のアクションとロジックは右側に配置する。これは、管理者がFlowを開いた場合に、Flowに慣れてもらうためと、サブフローへの移行を容易にするためである。
    2. AfterUpdateの場合、"決定 "はプロセスビルダー様なを垂直ツリーで行い、ロジックは可能な限りサブフローに格納し、決定の右側で呼び出す。

2. 可能な限り、BEFORE-SAVE操作を優先する。
    これはデータベースにとってあらゆる面で効率的であり、SAVE操作が繰り返し行われるのを避けることができます。

3. 上記の理由から、レコードトリガーフローを含むすべての設計でサブフローを活用するようにしてください。

4. Eメールハンドラのみを使用するフローは、独自のレコードトリガーフローが必要。
    これは、フローを評価する条件が、メール送信の処理方法に影響を与える可能性があるためです。また、他のフローを変更したりテストしている間は、「Eメールハンドラ」のフローをオフにすることができるという利点もあります。

5. オートレイアウトモードは、初心者の方にも使いやすく、すっきりとした状態を保つことができます。オートレイアウトモードは必要に応じてオン・オフすることができるので、その決断にコミットする必要はない。


#### 遅延アクションについて
Flowsでは、スケジュールだけでなく、複雑なクエリーやループも実行できる。そのため、待機要素や遅延アクションを使用する理由は、プラットフォームイベントのための待機や、遅延アクションが比較的短い場合を除き、ほぼありません。
例えば、1ヶ月先に予定されているアクションは、その代わりにレコードにフラグを設定し、スケジュールされたフローが毎日レコードを評価し、処理の基準に合うかどうかを確認する必要があります。もし条件に合っていれば、アクションを実行する。
この素晴らしい例は、誕生日メールです。1年間待つアクションをトリガーする代わりに、誕生日のコンタクトに対して毎日実行されるスケジュールされたフローを実行します。これにより、デバッグや何が起こっているかの確認が非常に簡単になります。

#### 追加説明
1. DML(Data Manipulation Language)の場合は簡単ですが、レコードの取得の場合はそうもいきません。この問題を回避するためにインストールできるapexアクションがあります。画面フローを構築している場合は、この問題はあまりありません。
2. （Spring21の時点では、レコード編集フローはまだサブフローの呼び出しをサポートしていません。対応するまでは利用を控えた方がよいでしょう)。


### apex命名規則
*本ページの内容は[Salesforce-Naming-Conventions.md APEX関連部分](https://github.com/cfpb/salesforce-docs/blob/master/_pages/Salesforce-Naming-Conventions.md)の翻訳*

#### Apexクラス
##### 命名のルール
クラス名は大文字で始まるユニークなものでなければならない。アンダースコアやスペースを含んではならない。単語は、頭文字を大文字で連結し、それに続く内部の単語は大文字にする。全単語を使用し、頭字語や略語の使用は制限する。カスタムコントローラクラスであるApexクラスのサフィックスは「Controller」にします。コントローラ拡張であるApexクラスのサフィックスは「XController」にします。これにより、Visualforceページに関連するコントローラを簡単に検索できます。

##### 例外
広く使われ、一般に理解されている頭字語や略語は、長い形式の代わりに使うことができる。例えばHTTPやURL、ACMAなど。

##### 例
以下は、使用すべきでないApexクラスの命名の例です：

| クラス名  | 理由 |
| ------------- | ------------- |
|  FHACustomer |  略語の使用はニーモニックでないため避けるべきである。 |
| GrtBgClass  | 全単語を短縮形の代わりに使用する GreatBigClass  |
| addresshandler  | クラスは大文字で始まらない  |
| Address_Handler  | アンダースコアは避けるべき  |
|   |   |

以下は、使用すべき命名規則の例である：

| クラス名  | 理由 |
| ------------- | ------------- |
| Customer  | クラスを表す完全な単語で、大文字で始まります  |
|  AddressHandler | 複数の単語を連結したもので、後続の単語は大文字で始まる。  |
| MailFaxController  |  Mail_Fax__c オブジェクトのコントローラ拡張。 |
|  CustomerController |  Customer オブジェクト用のコントローラ |


#### Apexバッチクラス-スケジューラブルクラス-キューアブルクラス
##### 命名のルール
クラス名は一意でなければならず、大文字で始まります。アンダースコアやスペースを含んではなりません。単語は、最初の大文字とそれに続く内部の単語を大文字にして連結します。全単語を使用し、頭字語や略語の使用は制限されるべきである。バッチ・クラスの接尾辞は「 _Batch」、スケジュール可能クラスの接尾辞は「_Schedule」、 [Queuableクラス](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_class_System_Queueable.htm)の接尾辞は「_Queueable」です。

##### 例外
広く使用され、一般的に理解されている頭字語や略語は、長い形式の代わりに使用できます。例えば、HTTPやURL、ACMAなどです。

##### 例
以下は、使用すべきでないApexのバッチ、スケジューラブル、およびキューアブル・クラスの命名の例です：

| クラス名  | 理由 |
| ------------- | ------------- |
| GrtBgClass  | 全単語を短縮形の代わりに使用する GreatBigClass、適切な接尾辞を使用すべき。  |
| contactbatch  | クラスは大文字で始まらず、接尾辞の前には必ずアンダースコアを付ける。  |
| Address_Update_Batch  | サフィックス以外のアンダースコアは避けること。  |
|   |   |

以下は、使用すべき命名規則の例である：

| クラス名  | 理由 |
| ------------- | ------------- |
| RoleExpiry_Batch  | 複数の単語を連結し、後続の単語を大文字にしたもの。バッチクラスであることを示す_Batchが接尾辞として付く。|
|  RoleExpiry_Queueable | 複数の単語を大文字で連結したもの。Queueableで接尾辞を付け、これがキュー可能なクラスであることを示します。  |
|   |   |
|   |   |


#### Apexトリガー
##### 命名のルール
トリガーは常に[オブジェクト名][操作]トリガー、またはそのオブジェクトのすべての操作を含むトリガーの場合は[オブジェクト名]トリガーという形式で命名する必要があります。例えば、[AccountInsertTrigger]、[AccountUpdateTrigger]、[OrderInsertTrigger]など。1つのオブジェクトの1つの操作にはトリガー1つだけ。1つのオブジェクトにつき、1つのトリガー内で全ての操作を含めることを強く推奨します。

##### 例
以下は、使用してはならないトリガの命名例です：

| クラス名  | 理由 |
| ------------- | ------------- |
| UpdateAccountAddresses  |  オブジェクト名は常に操作名の前になければならない。 |
|  AccountUpdateContacts |  ビジネス関数に特有であり、同じオブジェクトに対して他の更新トリガーを作成することができます。 |

以下は、使用される命名規則の例である：

| クラス名  | 理由 |
| ------------- | ------------- |
|  AccountUpdateTrigger | 更新操作のみを実行する汎用トリガー。 |
|   |   |


#### Apexテストクラス
##### 命名のルール
テストクラス名は一意でなければなりません。スペースを含んではいけません。単語は、最初の大文字とそれに続く内部の単語を大文字にして連結する。全単語を使用し、頭字語や略語の使用は制限する。テスト・クラスでは、Test という規約を使用する。これにより、クラスのアルファベット順が維持される。

##### 例外
広く使用され、一般的に理解されている略語や略称は、長い形式の代わりに使用することができます。例えばHTTPやURL、ACMAなど。

##### 例
以下は、使用すべきでない Apex クラス名の例です。 クラス名 理由 TESTCustomerManagement テスト・クラスは、接頭辞に "TEST" を付けず、接尾辞に "Test" を付けます。以下は、使用する命名規約の例です。

| クラス名  | 理由 |
| ------------- | ------------- |
|  CustomerManagementTest | CustomerManagement Apex クラスのテストクラスです。テスト対象のクラスの下にアルファベット順に表示されます。 |
|   |   |


#### Apexメソッド
#### 命名規則
メソッドは動詞、最初の単語は小文字、そのあと単語最初の文字は大文字。全単語を使用し、頭字語や略語の使用は制限する。

##### 例外
広く使用され、一般的に理解されている略語や略称は、長い形式の代わりに使用することができる。例えばHTTPやURL、ACMAなど。

##### 例
以下は、使用すべきでないApexメソッドの命名の例です：

| メソッド名  | 理由 |
| ------------- | ------------- |
|  handleCalculation() |  何を処理するか？ |
| performServices()  |  どんなサービスを実行するのか? |
|  dealWithInput() | 入力は具体的にどのように処理されるのか?  |
| NTInQ1()  | 関数名から何をするのか判断できない  |

以下は、使用される命名規則の例です：

| メソッド名  | 理由 |
| ------------- | ------------- |
| ammortizationCalculation()  |  どのような計算が実行されるかを記述する  |
|  numberOfTransactionsInQ1() |  わかりやすくするために必要なら、長い名前のほうがよい |
|   |   |


#### Apex変数
##### 命名規則
最初の単語は小文字、そのあと単語最初の文字は大文字。内部の単語は大文字で始めます。変数名は短いが意味のあるものにする。変数名はニモニックであるべきで、つまり、何気なく見ている人にその使用の意図を示すように設計されるべきである。1文字の変数名は、一時的な "使い捨て変数 "を除いて避けるべきである。一時変数の一般的な名前は、整数の場合はi、j、k、m、n、文字の場合はc、d、eです。

##### 例
使用すべきでないApex変数の命名例を以下に示します：

| 変数名  | 理由 |
| ------------- | ------------- |
| x = x – y  | 変数名は曖昧である  |

以下は、使用する命名規則の例です：

| 変数名  | 理由 |
| ------------- | ------------- |
| currentBalance = lastBalance - lastPayment  |  明確な意味を持つ曖昧な名前。 |


#### Apex定数
##### 命名規則
クラス定数として宣言された変数の名前は、すべて大文字で、アンダースコア（"_"）で単語を区切ります。アプリケーション全体で使用される共通の定数は、GlobalConstantsクラスで宣言する必要があります。 定数のスコープは必要最小限に抑える必要があります。privateなクラス属性は、一般に定義された定数よりも優先されます。

##### 例
以下は、使用すべきでないApex定数の命名例です：

| 定数名  | 理由 |
| ------------- | ------------- |
| maxCharacters  | 変数名と区別できない  |

以下は、使用される命名規則の例です：

| 定数名  | 理由 |
| ------------- | ------------- |
|  MAX_CHARACTERS |  大文字を使用すると、レビューアが定数であると判断しやすくなります |


#### Apexタイプ名
##### 命名のルール
型名には大文字の頭文字を使用する。これはJavaの命名規則に従っています。これは、型名がその直後に続く変数名と類似しないようにするためです。

##### 例
以下は、使用すべきでないApex型名の例です。

| タイプ名  | 理由 |
| ------------- | ------------- |
|  map Contacts |  "map"、"id"、および "string" は大文字で始まるべき |
|  String Contact |  "string" は大文字で始まるべき |
|   |   |

以下は、使用される命名規則の例です。

| タイプ名  | 理由 |
| ------------- | ------------- |
| Map Contacts  |  大文字で始まる |
|   |   |