PR

【Salesforce】Apex 開発におけるアンチパターンと回避方法

salesforce-apex Salesforce
この記事は約4分で読めます。
記事内に広告が含まれています。

Salesforce はマルチテナント型の SaaS のため、特定の顧客がリソースを食い潰さないように、ガバナ制約 を設けています。

Apex によるカスタム開発を行う際は、常にこの ガバナ制約 を意識して記述する必要があります。

また、レコードの Id の扱いにも要注意です。

これらを前提とした開発を行うために、本記事ではいくつかのアンチパターンと、その回避方法を紹介します。

アンチパターン:ループ内のDML操作

Apex コードでループ(for文など)内に DML操作 (insert, update, delete, upsert)を配置することは、真っ先に覚えるべきアンチパターンです。

各繰り返しでデータベーストランザクションが発生し、ガバナ制限に達するリスクが高まるためです。

悪い例

for(Account acc : accountList) {
    // ループ内でDML操作
    update acc;
}

良い例

コレクション(ListやMapなど)を使用して、ループの外で一括DML操作を行います。

List<Account> accountsToUpdate = new List<Account>();
for(Account acc : accountList) {
    // 必要な変更を加える
    accountsToUpdate.add(acc);
}
update accountsToUpdate; // ループ外で一括DML操作
スポンサーリンク

アンチパターン:ループ内でのSOQLクエリ実行

これも前章の内容と同様です。

ループ内でSOQLクエリを実行すると、各繰り返しでクエリが実行され、ガバナ制限に達するリスクが高まります。

これは非効率的でリソースを浪費する行為です。

悪い例

for(Contact con : contactList) {
    Account acc = [SELECT Id, Name FROM Account WHERE Id = :con.AccountId];
    // 何らかの処理
}

良い例

事前に必要なデータをクエリし、ループの外でデータを処理します。

または、Mapなどのコレクションを使用して関連データを効率的にアクセスします。

Map<Id, Account> accountMap = new Map<Id, Account>([SELECT Id, Name FROM Account WHERE Id IN :accountIds]);
for(Contact con : contactList) {
    Account acc = accountMap.get(con.AccountId);
    // 何らかの処理
}
【Salesforce】Apex で SOQL の結果を Map に反映する簡潔な書き方
Apex で、 `Map<Id, SObject>` のような形式でSOQLのデータを保持したい場合に覚えておくと便利な書き方を備忘録として記載します。
スポンサーリンク

アンチパターン:ハードコーディングされたID

システムの各種ID(オブジェクトのレコードIDや各種設定のID等)は、環境が変わる(例えば、 Sandbox から本番環境への移行)ごとにIDが変わります。

これらをハードコーディングすると、意図しない不具合を生む原因となります。

代わりに、動的にIDを取得する方法を使用するべきです。

「本番環境ではこの ID だから大丈夫」 は、ただの言い訳です。絶対にやめましょう。

Salesforce 環境の引っ越しをするときに絶望しますよ。

悪い例

String recordTypeId = '012000000000123'; // ハードコーディングされたレコードタイプID
Account acc = new Account(Name='Sample', RecordTypeId=recordTypeId);
// 後続処理...

良い例

// レコードタイプIDを動的に取得
Schema.DescribeSObjectResult accDescribe = Account.SObjectType.getDescribe();
List<Schema.RecordTypeInfo> accRecordTypes = accDescribe.getRecordTypeInfos();
for (Schema.RecordTypeInfo rtInfo : accRecordTypes) {
    rtInfo.getRecordTypeId();
}
// 後続処理...

※例外的に、レコードタイプの ID は、本番環境からリフレッシュした Developer Sandbox でも値は同じです。が、それでもハードコードはやめましょう。

スポンサーリンク

おわりに

Salesforce の Apex 開発における一般的なアンチパターンと、それらを避けるための実践的な回避方法を紹介しました。

開発者として、これらのパターンを認識し、適切な設計とコーディングプラクティスを適用することで、より効率的で保守しやすいコードを書くことができます。

一時の気の迷いで、負債を残すのはやめましょうね。

コメント

タイトルとURLをコピーしました