Salesforce
force.com

ApexTriggerを構造化する

More than 3 years have passed since last update.

ApexTriggerのベストプラクティスとして、Handlerクラスを作成して、呼び出しと処理を分離するというものがあります。とはいえ、ちょっとしたTriggerなのにHandlerクラスを作ったりするのは面倒だけど、メソッド化したいということはないでしょうか?あるいはシステム管理者権限で実行したいとか…。

実は、ApexTriggerも構造化することができます!


ApexTriggerにメソッドを書く

こんな感じで書けます。


method

trigger AccountTestTrigger on Account (before insert, before update) {

if(Trigger.isBefore && Trigger.isInsert) {
doBeforeInsert();
}

public void doBeforeInsert() {
System.debug('TestTriggerHandler.doBeforeInsert()');
}
}


あんまり意味無いですが、staticメソッドも書けます。


static_method

trigger AccountTestTrigger on Account (before insert) {

if(Trigger.isBefore && Trigger.isInsert) {
doBeforeInsert();
}

public static void doBeforeInsert() {
System.debug('TestTriggerHandler.doBeforeInsert()');
}
}



ApexTriggerに内部クラスを書く

内部クラスも書けたりします。


class

trigger AccountTestTrigger on Account (before insert) {

TestTriggerHandler h = new TestTriggerHandler();

if(Trigger.isBefore && Trigger.isInsert) {
h.doBeforeInsert();
}

public class TestTriggerHandler {
public void doBeforeInsert() {
System.debug('TestTriggerHandler.doBeforeInsert()');
}
}

}



ApexTriggerにテストは書けるのか?

残念ながらテストメソッドは書けません。

まずは外部のテストクラスから呼び出せるか試してみましたが、呼び出せませんでした。


テストクラス

AccountTestTrigger.TestHandler h = new AccountTestTrigger.TestHandler();


大胆にApexTriggerにテストメソッドを書いてみましたが、こちらもNGでした。


testMethod

trigger AccountTestTrigger on Account (before insert) {

static testMethod void testDoBeforeInsert() {
System.debug('TestTriggerHandler.doBeforeInsert()');

}



ApexTrigger構造化が拓く世界

ApexTriggerを構造化することで、AppExchangeアプリケーション開発者がハッピーになることがあります。

アクセス権限がないレコードを更新したいとき without sharing を利用すれば問題ないところですが、AppExchangeアプリケーションを開発する場合、セキュリティレビューでApexClassに with sharing を設定することが求められます。

そのため、Handlerクラスを利用するとアクセス権限のないレコードは更新できなくなってしまいます。

しかし、ApexTrigger内に記述された処理についてはシステム管理者権限で動作しますので、アクセス権限に縛られずレコードなどを操作できます。とはいえ、構造化できない状態では見通しが悪くなり保守性が落ちるので書く気が起きませんが、ApexTriggerを構造化できればある程度のロジックをトリガー内に書いてもいいかな、と思えてきます。


まとめ

最後にメリット・デメリットをまとめておきます。

実際問題としてAppExchangeに公開するパッケージを開発している人でなければ、あまり利用しないかもしれません。

実装方法
メリット
デメリット

Handlerクラスにロジックを分離
他のクラスやトリガーで再利用・単体テストしやすい
AppExchangeに掲載するアプリの場合はアクセス権限が制限される

ApexTrigger内で構造化
AppExchangeに掲載するアプリでもアクセス権限が制限されない
再利用できるのはトリガー内のみで、単体テストが書きにくい

この投稿はSalesforce1 Advent Calendar 2014の12月19日の記事です。

Happy Hacking!