mcpField
S
salesforce-developer

salesforce-developer

github.com/farmage開発224271 回インストール5 週間前に更新
リポジトリ

salesforce-developer について

Salesforce ソリューションを実装・デプロイする開発者向けのスキルです。Apex、Lightning Web Components、SOQL/SOSL、テスト、ガバナ制限、Salesforce DX の手法を扱います。

主な機能

  1. 01Apex とトリガーのパターン
  2. 02Lightning Web Components のガイド
  3. 03SOQL/SOSL クエリの実践
  4. 04ガバナ制限の確認
  5. 05テストと Salesforce DX によるデプロイ

活用シーン

  1. 01一括処理に対応する Apex 機能の設計
  2. 02Lightning Web Components の構築
  3. 03デプロイ用メタデータの準備

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/farmage/opencode-skills --skill salesforce-developer

インストール後、Claude Code で/salesforce-developerを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
apex-development.md
deployment-devops.md
integration-patterns.md
lightning-web-components.md
soql-sosl.md

詳細

Salesforce Developer

コアワークフロー

  1. 要件を分析する - ビジネスニーズ、データモデル、ガバナ制限、スケーラビリティを把握します
  2. ソリューションを設計する - 宣言型とプログラム型のどちらを使うかを選択し、一括処理を計画して、連携を設計します
  3. 実装する - ベストプラクティスに従って、Apex クラス、LWC コンポーネント、SOQL クエリを作成します
  4. ガバナ制限を検証する - 先に進む前に、SOQL/DML の実行回数、ヒープサイズ、CPU 時間がプラットフォームの制限内に収まっていることを確認します
  5. 十分にテストする - カバレッジ 90% 以上のテストクラスを作成し、一括処理のシナリオ(200 レコードのバッチ)をテストします
  6. デプロイする - Salesforce DX、スクラッチ組織、CI/CD を使用してメタデータをデプロイします

リファレンスガイド

状況に応じて詳細なガイダンスを読み込みます。

トピックリファレンス読み込むタイミング
Apex 開発references/apex-development.mdクラス、トリガー、非同期パターン、バッチ処理
Lightning Web Componentsreferences/lightning-web-components.mdLWC フレームワーク、コンポーネント設計、イベント、ワイヤーサービス
SOQL/SOSLreferences/soql-sosl.mdクエリの最適化、リレーションシップ、ガバナ制限
連携パターンreferences/integration-patterns.mdREST/SOAP API、プラットフォームイベント、外部サービス
デプロイと DevOpsreferences/deployment-devops.mdSalesforce DX、CI/CD、スクラッチ組織、メタデータ API

制約

必ず行うこと
  • Apex コードを一括処理に対応させます — ループの前に ID/レコードを収集し、クエリ/DML はループの外で実行します
  • 一括処理のシナリオを含む、最低 90% のコードカバレッジを持つテストクラスを作成します
  • インデックス付きフィールドを使った選択性の高い SOQL クエリを使用し、リレーションシップクエリを活用します
  • 長時間かかる処理には、適切な非同期処理(batch、queueable、future)を使用します
  • 適切なエラー処理とログ記録を実装し、部分的な成功には Database.update(scope, false) を使用します
  • ソース駆動型の開発とメタデータのデプロイに Salesforce DX を使用します
必ず避けること
  • ループ内で SOQL/DML を実行します(ガバナ制限違反 — 以下の一括処理対応トリガーパターンを参照)
  • コードに ID や認証情報をハードコードします
  • 保護策なしで再帰的なトリガーを作成します
  • 項目レベルセキュリティと共有ルールのチェックを省略します
  • 非推奨の Salesforce API やコンポーネントを使用します

コードパターン

一括処理に対応したトリガー(正しいパターン)
// CORRECT: collect IDs, query once outside the loop
trigger AccountTrigger on Account (before insert, before update) {
    AccountTriggerHandler.handleBeforeInsert(Trigger.new);
}

public class AccountTriggerHandler {
    public static void handleBeforeInsert(List<Account> newAccounts) {
        Set<Id> parentIds = new Set<Id>();
        for (Account acc : newAccounts) {
            if (acc.ParentId != null) parentIds.add(acc.ParentId);
        }
        Map<Id, Account> parentMap = new Map<Id, Account>(
            [SELECT Id, Name FROM Account WHERE Id IN :parentIds]
        );
        for (Account acc : newAccounts) {
            if (acc.ParentId != null && parentMap.containsKey(acc.ParentId)) {
                acc.Description = 'Child of: ' + parentMap.get(acc.ParentId).Name;
            }
        }
    }
}
// INCORRECT: SOQL inside loop — governor limit violation
trigger AccountTrigger on Account (before insert) {
    for (Account acc : Trigger.new) {
        Account parent = [SELECT Id, Name FROM Account WHERE Id = :acc.ParentId]; // BAD
        acc.Description = 'Child of: ' + parent.Name;
    }
}
Batch Apex
public class ContactBatchUpdate implements Database.Batchable<SObject> {
    public Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator([SELECT Id, Email FROM Contact WHERE Email = null]);
    }
    public void execute(Database.BatchableContext bc, List<Contact> scope) {
        for (Contact c : scope) {
            c.Email = '[email protected]';
        }
        Database.update(scope, false); // partial success allowed
    }
    public void finish(Database.BatchableContext bc) {
        // Send notification or chain next batch
    }
}
// Execute: Database.executeBatch(new ContactBatchUpdate(), 200);
テストクラス
@IsTest
private class AccountTriggerHandlerTest {
    @TestSetup
    static void makeData() {
        Account parent = new Account(Name = 'Parent Co');
        insert parent;
        Account child = new Account(Name = 'Child Co', ParentId = parent.Id);
        insert child;
    }

    @IsTest
    static void testBulkInsert() {
        Account parent = [SELECT Id FROM Account WHERE Name = 'Parent Co' LIMIT 1];
        List<Account> children = new List<Account>();
        for (Integer i = 0; i < 200; i++) {
            children.add(new Account(Name = 'Child ' + i, ParentId = parent.Id));
        }
        Test.startTest();
        insert children;
        Test.stopTest();

        List<Account> updated = [SELECT Description FROM Account WHERE ParentId = :parent.Id];
        System.assert(!updated.isEmpty(), 'Children should have descriptions set');
        System.assert(updated[0].Description.startsWith('Child of:'), 'Description format mismatch');
    }
}
SOQL のベストプラクティス
// Selective query — use indexed fields in WHERE clause
List<Opportunity> opps = [
    SELECT Id, Name, Amount, StageName
    FROM Opportunity
    WHERE AccountId IN :accountIds      // indexed field
      AND CloseDate >= :Date.today()    // indexed field
    ORDER BY CloseDate ASC
    LIMIT 200
];

// Relationship query to avoid extra round-trips
List<Account> accounts = [
    SELECT Id, Name,
           (SELECT Id, LastName, Email FROM Contacts WHERE Email != null)
    FROM Account
    WHERE Id IN :accountIds
];
Lightning Web Component(カウンターの例)

<template>
    <lightning-card title="Counter">
        <div class="slds-p-around_medium">
            <p>Count: {count}</p>
            <lightning-button label="Increment" onclick={handleIncrement}></lightning-button>
        </div>
    </lightning-card>
</template>
// counterComponent.js
import { LightningElement, track } from 'lwc';
export default class CounterComponent extends LightningElement {
    @track count = 0;
    handleIncrement() {
        this.count += 1;
    }
}

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>59.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
    </targets>
</LightningComponentBundle>

ドキュメント

コメント