Apex Trigger Lightweight Framework

#1.一般的な実装例
```java

trigger EmployeeTrigger on Employee__c (before insert, before update, before delete, after insert, after update, after delete, after undelete) {
    if (Trigger.isInsert) {
        if (Trigger.isBefore) {
            // Before Insert 処理
        } else if (Trigger.isAfter) {
            // After Insert 処理
    }
    ．．．（略）
}
```
#2.問題分析
*●トリガはシステム権限で実行するため、レコード共有権限は無視される*
*●メソッド単位でテストできないため、テストクラスの作成には不便利*
*●ロジックは共有できない*

#3.Trigger構成図（Lightweight Framework）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/332907/bd54e131-001f-54ee-fa91-431308aeaa32.png)

#4.TriggerHandler
```java

public abstract class TriggerHandler {
    public void execute() {
        switch on Trigger.operationType {
            when BEFORE_INSERT  { this.beforeInsert(Trigger.new); }
            when BEFORE_UPDATE  { this.beforeUpdate(Trigger.oldMap, Trigger.newMap); }
            when BEFORE_DELETE  { this.beforeDelete(Trigger.oldMap); }
            when AFTER_INSERT   { this.afterInsert(Trigger.newMap); }
            when AFTER_UPDATE   { this.afterUpdate(Trigger.oldMap, Trigger.newMap); }
            when AFTER_DELETE   { this.afterDelete(Trigger.oldMap); }
            when AFTER_UNDELETE { this.afterUndelete(Trigger.newMap); }
        }
    }

    protected virtual void beforeInsert(List<Sobject> newList) {}
    protected virtual void beforeUpdate(Map<Id, Sobject> oldMap, Map<Id, Sobject> newMap) {}
    protected virtual void beforeDelete(Map<Id, Sobject> oldMap) {}
    protected virtual void afterInsert(Map<Id, Sobject> newMap) {}
    protected virtual void afterUpdate(Map<Id, Sobject> oldMap, Map<Id, Sobject> newMap) {}
    protected virtual void afterDelete(Map<Id, Sobject> oldMap) {}
    protected virtual void afterUndelete(Map<Id, Sobject> newMap) {}

    @TestVisible protected Boolean isFieldValueChanged(SObject oldObject, SObject newObject, SObjectField field) {
        Object oldValue = getFieldValue(oldObject, field);
        Object newValue = getFieldValue(newObject, field);
        return oldValue != newValue;
    }
    
    @TestVisible protected Object getFieldValue(SObject obj, SObjectField field) {
        Object fieldValue = (obj != null) && (field != null) ? obj.get(field) : null;
        return fieldValue;
    }
}
```
#5.実装例
```java

trigger EmployeeTrigger on Employee__c (before insert, before update, before delete, after insert, after update, after delete, after undelete) {
    new EmployeeTriggerHandler().execute();
}
```

```java

public with sharing class EmployeeTriggerHandler extends TriggerHandler {
    public override void afterInsert(Map<Id, SObject> newMap) {
        // 業務処理
    }
    public override void afterUpdate(Map<Id, SObject> oldMap, Map<Id, SObject> newMap){
        // 業務処理
    }
}
```

#6.Triggerの実行制御について
![image.png](https://qiita-image-store.s3.amazonaws.com/0/332907/8cd77443-71e6-354e-c836-775437288c54.png)

#7.テストクラス
```java

/*******************************************************************************
* XXXXXXシステム
* @Auther Terrasky 徐
* 概要：トリガーハンドラーの基底クラス（テストクラス）
******************************************************************************/
@isTest
private class TriggerHandlerTest {
	@isTest
	static void testAll() {
		TriggerHandlerDummy dummy = new TriggerHandlerDummy();
		dummy.execute();
		dummy.beforeInsert(null);
		dummy.beforeUpdate(null, null);
		dummy.beforeDelete(null);
		dummy.afterInsert(null);
		dummy.afterUpdate(null, null);
		dummy.afterDelete(null);
		dummy.afterUndelete(null);
		dummy.isFieldValueChanged(new Account(name='123'), new Account(name='456'), Account.name);
	}

	private Class TriggerHandlerDummy extends TriggerHandler{}
}
```