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. 01构建 Apex 触发器和批处理
  2. 02创建 Lightning Web Components
  3. 03在平台限制内优化数据查询
  4. 04测试并部署 Salesforce 元数据

安装

复制下面的命令,在终端中运行。

$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 开发人员

核心工作流

  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 查询;利用关系查询
  • 对长时间运行的任务使用适当的异步处理方式(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>

由 @jeffallan 维护,他是 Synergetic Solutions 的首席顾问

文档

评论

支持 Markdown