ApexクラスとApexトリガー

## **ApexクラスとApexトリガーの違い**

| **項目** | **Apexクラス** | **Apexトリガー** |
|----------|--------------|--------------|
| **目的** | 再利用可能なビジネスロジックを定義 | レコードの作成・更新・削除時に自動実行される処理 |
| **実行タイミング** | 明示的に呼び出さないと実行されない | DML操作（INSERT, UPDATE, DELETE, UNDELETE）により自動実行 |
| **書き方** | メソッドや変数を定義する一般的なクラス構造 | `trigger` キーワードを使用し、特定のオブジェクトのイベントに対して実行 |
| **呼び出し方法** | 他のクラス、トリガー、Visualforce、LWC/Lightning Component、スケジュール処理などから呼び出し可能 | DML操作をトリガーにするため、明示的に呼び出せない |
| **テスト・再利用** | 再利用が容易で、単体テストもしやすい | 単体ではテストしづらく、カスタムロジックをApexクラスに移すのが一般的 |

---

## **具体例**

### **1. Apexトリガーの例（商談成立時にフォローアップタスクを作成）**
商談（Opportunity）の`StageName`が`Closed Won`（成立）になった際、90日後のフォローアップタスクを作成するApexトリガーの例。

```apex
trigger CreateFollowUpTask on Opportunity (after update) {
    List<Task> tasksToCreate = new List<Task>();

    for (Opportunity opp : Trigger.new) {
        Opportunity oldOpp = Trigger.oldMap.get(opp.Id);
        if (oldOpp.StageName != 'Closed Won' && opp.StageName == 'Closed Won') {
            Task newTask = new Task(
                Subject = 'フォローアップ',
                WhatId = opp.Id,
                OwnerId = opp.OwnerId,
                ActivityDate = Date.today().addDays(90),
                Status = 'Not Started',
                Priority = 'High'
            );
            tasksToCreate.add(newTask);
        }
    }

    if (!tasksToCreate.isEmpty()) {
        insert tasksToCreate;
    }
}
```
このように、Apexトリガーは **DML操作（更新）を契機に自動で実行** される。

---

### **2. Apexクラスの例（商談のフォローアップタスクを作成するメソッド）**
上記のApexトリガーのロジックを **Apexクラス** に分離すると、他のクラスからも再利用しやすくなる。

```apex
public class OpportunityHelper {
    public static void createFollowUpTask(List<Opportunity> oppList) {
        List<Task> tasksToCreate = new List<Task>();

        for (Opportunity opp : oppList) {
            if (opp.StageName == 'Closed Won') {
                Task newTask = new Task(
                    Subject = 'フォローアップ',
                    WhatId = opp.Id,
                    OwnerId = opp.OwnerId,
                    ActivityDate = Date.today().addDays(90),
                    Status = 'Not Started',
                    Priority = 'High'
                );
                tasksToCreate.add(newTask);
            }
        }

        if (!tasksToCreate.isEmpty()) {
            insert tasksToCreate;
        }
    }
}
```

Apexトリガー側では、このクラスのメソッドを呼び出すだけにすることで、コードの管理がしやすくなる。

```apex
trigger CreateFollowUpTask on Opportunity (after update) {
    OpportunityHelper.createFollowUpTask(Trigger.new);
}
```

**メリット**
✅ Apexクラスを分けることで **再利用可能**  
✅ **ユニットテストがしやすくなる**  
✅ トリガーのロジックがシンプルになるため **可読性が向上**  

---

## **Visualforceとの関連**
Visualforce（VF）は、Salesforceの **カスタムUIを作成** するためのフレームワーク。  
Apexクラスは **Visualforceページのコントローラー** として利用できる。

### **3. VisualforceページでApexクラスを活用**
**(1) Apexクラス**
```apex
public class OpportunityController {
    public List<Opportunity> getOpportunities() {
        return [SELECT Id, Name, Amount, StageName FROM Opportunity LIMIT 10];
    }
}
```

**(2) Visualforceページ**
```html
<apex:page controller="OpportunityController">
    <apex:pageBlock title="最近の商談">
        <apex:pageBlockTable value="{!Opportunities}" var="opp">
            <apex:column value="{!opp.Name}"/>
            <apex:column value="{!opp.Amount}"/>
            <apex:column value="{!opp.StageName}"/>
        </apex:pageBlockTable>
    </apex:pageBlock>
</apex:page>
```

このように、Apexクラスを **Visualforceのデータ取得や処理のロジック** に活用できる。

---

## **まとめ**
| **項目** | **Apexクラス** | **Apexトリガー** | **Visualforceとの関連** |
|----------|--------------|--------------|------------------|
| **役割** | ビジネスロジックを定義し、他のクラスやコンポーネントで利用 | DML操作（INSERT, UPDATE, DELETE）に応じて自動実行 | カスタムUIを作成し、Apexクラスをコントローラーとして利用 |
| **再利用性** | 高い（メソッドを他のクラスでも利用可） | 低い（DML操作に依存） | Apexクラスを利用してデータを表示・処理 |
| **実行方法** | 明示的に呼び出し（LWC、VF、バッチ、スケジュール処理など） | DML操作時にSalesforceが自動実行 | ユーザー操作で実行（ボタンやページロード時） |

### **使い分けのポイント**
✅ **Apexクラス:** 業務ロジックを共通化して管理・再利用しやすくする  
✅ **Apexトリガー:** データ変更に応じたリアルタイム処理を実装する  
✅ **Visualforce:** SalesforceのUIをカスタマイズし、データの表示・操作を行う  

LWCやAuraコンポーネントが普及している現在でも、**Visualforce + Apexクラス** の組み合わせは、特に **レガシーシステムの改修** や **特定用途のUIカスタマイズ** で使われることが多い。

---

Salesforceで開発する際は、**できるだけApexクラスにロジックを分けて管理** し、トリガーはシンプルに保つのがベストプラクティス！