Trace の 4 つのライフサイクルメソッド
•Apex Stem ドキュメント
Apex StemApexTraceLoggingSalesforceApex
Usecase に Trace を仕込む基本形。instance field で 1 回だけ生成する理由、start / log / skip / abort / finish の使い分け、3 つの終了パスを解説します。
Trace の 4 つのライフサイクルメソッド
Trace クラスは、Usecase の処理の流れを表現する 4 つのライフサイクルメソッドを持ちます。
instance field に持つ
Trace は Usecase クラスの instance field として 一度だけ 生成します。
APEX
public with sharing class CopyAccountIndustryToOpportunityUsecase {
private Trace t = Trace.of('商談に親取引先の業種をコピー');
// ...
}
「なぜ instance field で 1 回だけなのか」は、§「その他の注意点」で詳しく扱います。ここではまず、Usecase 1 つにつき 1 つの Trace を持つ、と覚えれば十分です。
4 つのメソッドと 3 つの終了パス
| メソッド | 用途 | 呼ぶタイミング |
|---|---|---|
t.start() | 処理開始 | invoke() の冒頭 |
t.log(msg) | 中間ログ | 任意箇所、複数回 OK |
t.skip(msg) | スキップ終了 | 早期 return の直前 (処理対象なしなど) |
t.abort(msg) | 異常終了 | 例外で抜ける時、業務エラーで中止する時 |
t.finish(msg) | 正常終了 | invoke() の末尾 |
log / skip / abort / finish には 引数なしのオーバーロード もあります。メッセージを残す必要がない場面 (とにかく終了させたいだけ、など) では t.finish() のように呼べます。経路 (skip / finish / abort) の区別だけ残せばよく、追加のログは不要、というケースに向きます。
ポイントは 3 つの終了パス です。
finish: 処理が正常に完了したことを表すskip: 「対象がない」「条件不一致」などで、何もせず正常に抜けることを表すabort: 例外発生や業務エラーで、正常完了しなかったことを表す
この 3 つを使い分けると、後段の TraceFlow で「どの経路で終わったか」をテストで検証できます。
コード例
CopyAccountIndustryToOpportunityUsecase を、Trace の使い方に焦点を当てて見てみます。
APEX
public with sharing class CopyAccountIndustryToOpportunityUsecase {
@TestVisible static final String LBL_FETCH = 'oppFetch';
@TestVisible static final String LBL_UPDATE = 'oppUpdate';
private final Set<Id> opportunityIds;
private final IEloquent eloquent;
private Trace t = Trace.of('商談に親取引先の業種をコピー');
// (コンストラクタは省略。詳細は導入ガイドのステップ 3 を参照)
public void invoke() {
this.t.start();
if(this.opportunityIds == null || this.opportunityIds.isEmpty()) {
this.t.skip('対象の商談がないため終了。');
return;
}
Scribe oppScribe = Scribe.of(Opportunity.class)
.field('Id')
.parentField(Scribe.asParent('AccountId').field('Industry'))
.whereIn('Id', this.opportunityIds);
List<IEntry> oppEntries = this.eloquent.label(LBL_FETCH).get(oppScribe);
for(IEntry oppEntry : oppEntries) {
IEntry accountEntry = oppEntry.getParent('AccountId');
oppEntry.put('Industry__c', accountEntry.get('Industry'));
}
this.eloquent.label(LBL_UPDATE).doUpdate(oppEntries);
this.t.finish(oppEntries.size() + ' 件の商談に業種をコピー。');
}
}
この Usecase は 2 つの経路で終わります。対象が空なら skip、処理を完了したら finish。次の章では、この 2 つの経路をテストで区別する方法を見ます。
関連ドキュメント
- TraceFlow で経路を検証する: 記録した経路をテストで縛る
- ネストと 2 つのモード: Usecase が Usecase を呼ぶときの順序ルール
- ApexTrace ガイド: ガイド目次に戻る