mcpField
S
salesforce-developer

salesforce-developer

github.com/jeffallan開発12.1k4.4k 回インストール今日更新
リポジトリ

salesforce-developer について

salesforce-developerは、Salesforceソリューションの構築とデプロイを支援する開発スキルです。Apex、Lightning Web Components、SOQL、連携、ガバナ制限を踏まえた設計、テスト、Salesforce DXのワークフローを扱います。

主な機能

  1. 01Apexクラス、トリガー、非同期処理パターン
  2. 02Lightning Web Componentsの開発
  3. 03SOQLとSOSLのクエリ実践
  4. 04一括処理とガバナ制限の確認
  5. 05テストクラスと一括処理テスト
  6. 06Salesforce DXとメタデータのデプロイ

活用シーン

  1. 01Apexトリガーとバッチ処理の構築
  2. 02Lightning Web Componentsの作成
  3. 03プラットフォーム制限内でのデータクエリ最適化
  4. 04Salesforceメタデータのテストとデプロイ

インストール

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

$npx skills add https://github.com/jeffallan/claude-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 フレームワーク、コンポーネント設計、イベント、wire サービス
SOQL/SOSLreferences/soql-sosl.mdクエリの最適化、リレーションシップ、ガバナー制限
インテグレーションパターンreferences/integration-patterns.mdREST/SOAP API、プラットフォームイベント、外部サービス
デプロイと DevOpsreferences/deployment-devops.mdSalesforce DX、CI/CD、スクラッチ組織、メタデータ API

制約

必ず行うこと
  • Apex コードを一括処理に対応させます — ループの前に ID/レコードを収集し、ループの外でクエリ/DML を実行します
  • 一括処理シナリオを含め、最低 90% のコードカバレッジを持つテストクラスを作成します
  • インデックス付きフィールドを使用した選択性の高い SOQL クエリを使い、リレーションシップクエリを活用します
  • 長時間かかる処理には適切な非同期処理(バッチ、キューアブル、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>

@jeffallan、Synergetic Solutions のプリンシパルコンサルタントが管理しています

ドキュメント

コメント