关于 salesforce-developer
salesforce-developer 是用于构建和部署 Salesforce 解决方案的开发技能,涵盖 Apex、Lightning Web Components、SOQL、集成、平台限制、测试及 Salesforce DX 工作流。
主要功能
- 01Apex 类、触发器与异步模式
- 02Lightning Web Components 开发
- 03SOQL 与 SOSL 查询实践
- 04批量化与平台限制检查
- 05测试类与批量场景测试
- 06Salesforce DX 与元数据部署
适用场景
- 01构建 Apex 触发器和批处理
- 02创建 Lightning Web Components
- 03在平台限制内优化数据查询
- 04测试并部署 Salesforce 元数据
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ jeffallan/ claude-skills --skill salesforce-developer安装后在 Claude Code 中输入/salesforce-developer确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/apex-development.mddeployment-devops.mdintegration-patterns.mdlightning-web-components.mdsoql-sosl.md详细介绍
Salesforce 开发人员
核心工作流
- 分析需求 - 理解业务需求、数据模型、治理限制和可扩展性
- 设计解决方案 - 选择声明式或编程式方案,规划批量化处理,设计集成
- 实施 - 遵循最佳实践编写 Apex 类、LWC 组件和 SOQL 查询
- 验证治理限制 - 确认 SOQL/DML 次数、堆大小和 CPU 时间均未超出平台限制,再继续操作
- 全面测试 - 编写测试类,覆盖率达到 90% 以上;测试批量场景(每批 200 条记录)
- 部署 - 使用 Salesforce DX、临时组织和 CI/CD 部署元数据
参考指南
根据上下文加载详细指南:
| 主题 | 参考资料 | 加载时机 |
|---|---|---|
| Apex 开发 | references/apex-development.md | 类、触发器、异步模式、批处理 |
| Lightning Web Components | references/lightning-web-components.md | LWC 框架、组件设计、事件、wire 服务 |
| SOQL/SOSL | references/soql-sosl.md | 查询优化、关系、治理限制 |
| 集成模式 | references/integration-patterns.md | REST/SOAP API、平台事件、外部服务 |
| 部署与 DevOps | references/deployment-devops.md | Salesforce 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