Salesforceで実現するDomain Driven Design（DDD）

#参照関係
SalesforceでDDDを実現した場合の参照関係は以下のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239535/87b01ccf-694b-51b2-f143-a2c0238a84ea.png)

######インフラ層（オレンジ）
DBや外部APIに接続する部分になります。
DAOもこちらに該当します。

######ドメイン層（グリーン）
システムにおける知識を持ったクラスが該当します。
ドメイン層は二つに分けられます。
　・ドメインモデル
　　　⇒ふるまい・ルールを持ったオブジェクト
　・ドメインサービス
　　　⇒ドメインモデルで表し切れない処理をここに書く
SalesforceにおいてはsObjectが最もドメインモデルに近いかと思います。
なので、ドメインモデルクラスは作りません。
ドメインサービスはsObjectを補助するようなクラスにします。（バリデーションチェックなどが該当）

######アプリケーション層（ブルー）
ここではシステムにおけるユースケースに対応するクラスが該当します。

######UI/Batch/Trigger/GlobalAPI層（グレー）
ユースケース処理を呼ぶクライアント層になります。
Salesforceでは、UI（Visualforce・LightningComponent等）、Batch、Trigger、GlobalAPI（Apexの外部公開カスタムAPI）が該当します。

######高レベルから低レベルへ依存させる
依存は高レベル（より人間に近い動き）から低レベル（より機械に近い動き）に参照させます。
それぞれのパターンから入ってきたユースケースを低次元の処理を使って解決させていきます。

#サンプルアプリ
######要件
■Contact Create Page
　・Contactレコードが作成できる
　・「Account Phone」が同じAccountレコードが既に存在している場合は、そのレコードをContactレコードに紐づける
　・「Account Phone」が同じAccountレコードがない場合は、作成してそのレコードをContactレコードに紐づける
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239535/03ca63cc-d2b2-16f7-a587-f398ed8e3117.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239535/0a624656-4e9e-50cd-738b-836abbaf5e0a.png)

■Contact Table
　・Contact Create Pageで作成したレコードが表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239535/ecc7ae9a-ba8a-1a37-5a13-4b1237638f6d.png)

#クラス構成
以下がサンプルアプリのソースコードです。
https://github.com/MASA-JAPAN/Salesforce-DDD-Template

#処理概要
■Contact Create Page
LWCフレームワークで開発しております。
コントローラ（dddContactCreateController.cls）は一番上のグレー層に該当します。
こちらからContactApplicationService（アプリケーション層）のユースケース処理（createNewDddContact）を呼びます。

```Java
public with sharing class dddContactCreateController {
    public dddContactCreateController() {

    }

    @AuraEnabled
    public static String clickAction( String AccountName, String AccountPhone, String LastName, String FirstName ){
        ContactApplicationService contactAppService = new ContactApplicationService();
        return contactAppService.createNewDddContact(AccountName, AccountPhone, LastName, FirstName);
    }
}

```
createNewDddContactでは、ドメイン層（sObjectとObjectService層）とインフラ層（DAO）を駆使してユースケースを実現してます。

```Java
    public Id createNewDddContact( String AccountName, String AccountPhone, String LastName, String FirstName ){

        //If there is not an Account record, create it.
        AccountService accountService = new AccountService();
        Account targetAccount = new Account( Name = AccountName, Phone = AccountPhone );
        List<Account> sameAccounts = new List<Account>( accountService.getSameAccount(targetAccount) );
        if( sameAccounts.size() == 1){
            targetAccount = sameAccounts[0];
        } else if( sameAccounts.size() == 0 ){
            insert targetAccount;
        } else {
            throw new ContactApplicationServiceException('Phone ' + AccountPhone + ' is duplicated' );
        }

        Contact contact = new Contact(AccountId = targetAccount.Id, LastName = LastName, FirstName = FirstName, LeadSource = 'DDD' );
        insert contact;
        return contact.Id;
    }

```
さらに詳しくはGithubのソースコードを見て頂ければと思います。

#まとめ
ざーっと書いてみました、まだまだブラッシュアップすべき点は満載です！
是非コメント頂けると嬉しいです。