0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Apex入門 - Salesforceのプログラミングを始めよう

Posted at

はじめに

この記事では、Salesforceの開発言語であるApexの基本を学びます。JavaやC#の経験がある方にとって、比較的親しみやすい言語です。

目次

  1. Apexの基本文法
  2. トリガーの基礎
  3. テストクラスの書き方

1. Apexの基本文法

image.png

変数とデータ型

Apexで利用できる主要なデータ型を見ていきましょう。

// プリミティブ型
Integer count = 1;
String name = 'John';
Boolean isActive = true;
Decimal price = 1000.50;
Date today = Date.today();
DateTime now = DateTime.now();

// コレクション型
List<String> nameList = new List<String>();
Set<String> uniqueNames = new Set<String>();
Map<Id, Account> accountMap = new Map<Id, Account>();

// sObject型(Salesforceの標準オブジェクト)
Account acc = new Account(
    Name = 'テスト取引先',
    Industry = 'Technology'
);

クラスの定義

Apexでのクラス定義の基本を見ていきましょう。

public class AccountService {
    // 定数
    private static final String DEFAULT_INDUSTRY = 'Technology';
    
    // インスタンス変数
    private String accountName;
    
    // コンストラクタ
    public AccountService(String name) {
        this.accountName = name;
    }
    
    // メソッド
    public Account createNewAccount() {
        Account acc = new Account();
        acc.Name = this.accountName;
        acc.Industry = DEFAULT_INDUSTRY;
        return acc;
    }
    
    // 静的メソッド
    public static List<Account> getActiveAccounts() {
        return [SELECT Id, Name FROM Account WHERE Active__c = true];
    }
}

SOQLとDML

Salesforceのデータベース操作は、SOQLとDMLを使用します。

// SOQL(データの取得)
List<Account> accounts = [
    SELECT Id, Name, Industry
    FROM Account
    WHERE Industry = 'Technology'
    LIMIT 10
];

// DML(データの作成・更新・削除)
Account newAccount = new Account(Name = 'New Account');
insert newAccount;  // 挿入

newAccount.Industry = 'Finance';
update newAccount;  // 更新

delete newAccount;  // 削除

2. トリガーの基礎

image.png

image.png

image.png

トリガーの実行タイミング

トリガーには以下の実行タイミングがあります:

  • before insert
  • after insert
  • before update
  • after update
  • before delete
  • after delete
  • after undelete

基本的なトリガーの例

trigger AccountTrigger on Account (before insert, before update) {
    // トリガーコンテキスト変数の使用
    System.debug('Trigger.new: ' + Trigger.new);        // 新しいレコード
    System.debug('Trigger.old: ' + Trigger.old);        // 古いレコード
    System.debug('Trigger.newMap: ' + Trigger.newMap);  // 新しいレコードのマップ
    System.debug('Trigger.oldMap: ' + Trigger.oldMap);  // 古いレコードのマップ
    
    // insertの場合の処理
    if (Trigger.isBefore && Trigger.isInsert) {
        for (Account acc : Trigger.new) {
            if (String.isBlank(acc.Industry)) {
                acc.Industry = 'Technology';  // デフォルト値を設定
            }
        }
    }
    
    // updateの場合の処理
    if (Trigger.isBefore && Trigger.isUpdate) {
        for (Account acc : Trigger.new) {
            Account oldAcc = Trigger.oldMap.get(acc.Id);
            if (acc.Industry != oldAcc.Industry) {
                // 業種が変更された場合の処理
                acc.Industry_Changed__c = true;
            }
        }
    }
}

トリガーのベストプラクティス

  1. 一つのオブジェクトに対して1つのトリガーにまとめる
  2. ビジネスロジックは別クラスに分離する
  3. 再帰的な更新に注意する
  4. バルク処理に対応する
// トリガーハンドラークラス
public class AccountTriggerHandler {
    private boolean isExecuting = false;
    
    public void handleBeforeInsert(List<Account> newAccounts) {
        if (isExecuting) return;
        isExecuting = true;
        
        try {
            // ビジネスロジックの実行
            for (Account acc : newAccounts) {
                // 処理
            }
        } finally {
            isExecuting = false;
        }
    }
}

// トリガー
trigger AccountTrigger on Account (before insert) {
    AccountTriggerHandler handler = new AccountTriggerHandler();
    if (Trigger.isBefore && Trigger.isInsert) {
        handler.handleBeforeInsert(Trigger.new);
    }
}

3. テストクラスの書き方

image.png

テストクラスの基本構造

@isTest
private class AccountServiceTest {
    // テストデータの準備
    @testSetup
    static void setup() {
        Account testAcc = new Account(Name = 'Test Account');
        insert testAcc;
    }
    
    // 正常系のテスト
    @isTest
    static void testCreateNewAccount() {
        // 準備
        String accountName = 'New Test Account';
        AccountService service = new AccountService(accountName);
        
        // 実行
        Test.startTest();
        Account result = service.createNewAccount();
        Test.stopTest();
        
        // 検証
        System.assertEquals(accountName, result.Name);
        System.assertEquals('Technology', result.Industry);
    }
    
    // 例外のテスト
    @isTest
    static void testCreateNewAccountWithError() {
        // 準備
        AccountService service = new AccountService(null);
        
        // 実行
        Test.startTest();
        try {
            Account result = service.createNewAccount();
            System.assert(false, '例外が発生するはずです');
        } catch (Exception e) {
            // 検証
            System.assert(e.getMessage().contains('Account name cannot be null'));
        }
        Test.stopTest();
    }
}

テストの重要なポイント

  1. Test.startTest()とTest.stopTest()

    • ガバナー制限をリセット
    • 非同期処理の完了を待機
  2. アサーション

    • System.assertEquals(expected, actual)
    • System.assertNotEquals(expected, actual)
    • System.assert(condition)
    • System.assertNull(actual)
    • System.assertNotNull(actual)
  3. テストデータの作成

    • @testSetupを使用して共通のテストデータを準備
    • TestDataFactoryクラスを作成してテストデータ作成を一元管理
@isTest
public class TestDataFactory {
    public static Account createTestAccount(String name) {
        Account acc = new Account(
            Name = name,
            Industry = 'Technology'
        );
        insert acc;
        return acc;
    }
    
    public static List<Account> createTestAccounts(Integer count) {
        List<Account> accounts = new List<Account>();
        for (Integer i = 0; i < count; i++) {
            accounts.add(new Account(
                Name = 'Test Account ' + i,
                Industry = 'Technology'
            ));
        }
        insert accounts;
        return accounts;
    }
}

まとめ

image.png

この記事では、Apexの基本的な部分を学びました:

  1. 基本文法とデータ型
  2. トリガーの仕組みと実装方法
  3. テストクラスの作成方法

次のステップとしては:

  • より複雑なビジネスロジックの実装
  • バッチ処理やスケジュール処理の実装
  • API統合の実装

参考資料

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?