Loading...
Loading...
Compare original and translation side by side
Glob: **/*.clsGlob: **/*.triggerGlob: **/*TriggerAction*.clsGlob: **/*.clsGlob: **/*.triggerGlob: **/*TriggerAction*.cls| Class Type | Template |
|---|---|
| Trigger | |
| Trigger Action | |
| Service | |
| Selector | |
| Batch | |
| Queueable | |
| Test | |
| Test Data Factory | |
| Standard Class | |
~/.claude/plugins/marketplaces/sf-skills/sf-apex/templates/[template][project-root]/sf-apex/templates/[template]Read: ~/.claude/plugins/marketplaces/sf-skills/sf-apex/templates/apex-class.cls| 类类型 | 模板 |
|---|---|
| 触发器 | |
| 触发器动作 | |
| 服务类 | |
| 选择器类 | |
| 批处理类 | |
| 可队列类 | |
| 测试类 | |
| 测试数据工厂 | |
| 标准类 | |
~/.claude/plugins/marketplaces/sf-skills/sf-apex/templates/[template][project-root]/sf-apex/templates/[template]Read: ~/.claude/plugins/marketplaces/sf-skills/sf-apex/templates/apex-class.clsforce-app/main/default/classes/Score: XX/150 ⭐⭐⭐⭐ Rating
├─ Bulkification: XX/25
├─ Security: XX/25
├─ Testing: XX/25
├─ Architecture: XX/20
├─ Clean Code: XX/20
├─ Error Handling: XX/15
├─ Performance: XX/10
└─ Documentation: XX/10force-app/main/default/classes/Score: XX/150 ⭐⭐⭐⭐ Rating
├─ Bulkification: XX/25
├─ Security: XX/25
├─ Testing: XX/25
├─ Architecture: XX/20
├─ Clean Code: XX/20
├─ Error Handling: XX/15
├─ Performance: XX/10
└─ Documentation: XX/10"I noticed [pattern]. This will cause [problem]. Should I: A) Refactor to use [correct pattern] B) Proceed anyway (not recommended)"
| Anti-Pattern | Detection | Impact |
|---|---|---|
| SOQL inside loop | | Governor limit failure (100 SOQL) |
| DML inside loop | | Governor limit failure (150 DML) |
| Missing sharing | | Security violation |
| Hardcoded ID | 15/18-char ID literal | Deployment failure |
| Empty catch | | Silent failures |
| String concatenation in SOQL | | SOQL injection |
| Test without assertions | | False positive tests |
"我注意到[模式]。这会导致[问题]。我应该: A) 重构为使用[正确模式] B) 继续执行(不推荐)"
| 反模式 | 检测方式 | 影响 |
|---|---|---|
| 循环内包含SOQL | | 触发 governor 限制失败(100次SOQL上限) |
| 循环内包含DML | | 触发 governor 限制失败(150次DML上限) |
| 缺少共享关键字 | | 安全违规 |
| 硬编码ID | 15/18位ID字面量 | 部署失败 |
| 空catch块 | | 静默失败 |
| SOQL中使用字符串拼接 | | SOQL注入风险 |
| 测试类无断言 | | 测试假阳性 |
Skill(skill="sf-deploy", args="Deploy classes at force-app/main/default/classes/ to [target-org] with --dry-run")Skill(skill="sf-deploy", args="Proceed with actual deployment to [target-org]")Skill(skill="sf-deploy", args="Deploy classes at force-app/main/default/classes/ to [target-org] with --dry-run")Skill(skill="sf-deploy", args="Proceed with actual deployment to [target-org]")✓ Apex Code Complete: [ClassName]
Type: [type] | API: 65.0
Location: force-app/main/default/classes/[ClassName].cls
Test Class: [TestClassName].cls
Validation: PASSED (Score: XX/150)
Next Steps: Run tests, verify behavior, monitor logs✓ Apex代码完成: [ClassName]
类型: [type] | API版本: 65.0
位置: force-app/main/default/classes/[ClassName].cls
测试类: [TestClassName].cls
验证: 通过(评分: XX/150)
后续步骤: 运行测试、验证行为、监控日志| Category | Points | Key Rules |
|---|---|---|
| Bulkification | 25 | NO SOQL/DML in loops; collect first, operate after; test 251+ records |
| Security | 25 | |
| Testing | 25 | 90%+ coverage; Assert class; positive/negative/bulk tests; Test Data Factory |
| Architecture | 20 | TAF triggers; Service/Domain/Selector layers; SOLID; dependency injection |
| Clean Code | 20 | Meaningful names; self-documenting; no |
| Error Handling | 15 | Specific before generic catch; no empty catch; custom business exceptions |
| Performance | 10 | Monitor with |
| Documentation | 10 | ApexDoc on classes/methods; meaningful params |
| 类别 | 分值 | 核心规则 |
|---|---|---|
| 批量处理优化 | 25 | 禁止循环内执行SOQL/DML;先收集数据再操作;测试251+条记录 |
| 安全性 | 25 | 使用 |
| 测试 | 25 | 覆盖率90%+;使用Assert类;包含正向/负向/批量测试;使用测试数据工厂 |
| 架构 | 20 | TAF触发器;服务/领域/选择器分层;SOLID原则;依赖注入 |
| 整洁代码 | 20 | 有意义的命名;自文档化;避免 |
| 错误处理 | 15 | 具体异常优先于通用异常捕获;禁止空catch块;自定义业务异常 |
| 性能 | 10 | 使用 |
| 文档 | 10 | 类/方法包含ApexDoc注释;有意义的参数说明 |
sf package installed listtrigger AccountTrigger on Account (before insert, after insert, before update, after update, before delete, after delete, after undelete) {
new MetadataTriggerHandler().run();
}public class TA_Account_SetDefaults implements TriggerAction.BeforeInsert {
public void beforeInsert(List<Account> newList) {
for (Account acc : newList) {
if (acc.Industry == null) {
acc.Industry = 'Other';
}
}
}
}Trigger_Action__mdtsf package install --package 04tKZ000000gUEFYA2 --target-org [alias] --wait 10sf package installed listtrigger AccountTrigger on Account (before insert, after insert, before update, after update, before delete, after delete, after undelete) {
new MetadataTriggerHandler().run();
}public class TA_Account_SetDefaults implements TriggerAction.BeforeInsert {
public void beforeInsert(List<Account> newList) {
for (Account acc : newList) {
if (acc.Industry == null) {
acc.Industry = 'Other';
}
}
}
}Trigger_Action__mdtsf package install --package 04tKZ000000gUEFYA2 --target-org [alias] --wait 10| Scenario | Use |
|---|---|
| Simple callout, fire-and-forget | |
| Complex logic, needs chaining | |
| Process millions of records | |
| Scheduled/recurring job | |
| Post-queueable cleanup | |
| 场景 | 推荐方案 |
|---|---|
| 简单调用、触发即遗忘 | |
| 复杂逻辑、需要链式调用 | |
| 处理百万级记录 | |
| 定时/周期性任务 | |
| 队列后清理 | |
value ?? defaultValuerecord?.Field__cWITH USER_MODEAssert.areEqual()Assert.isTrue()System.FinalExceptionvalue ?? defaultValuerecord?.Field__cWITH USER_MODEAssert.areEqual()Assert.isTrue()System.FinalException@InvocableMethod@InvocableMethodpublic with sharing class RecordProcessor {
@InvocableMethod(label='Process Record' category='Custom')
public static List<Response> execute(List<Request> requests) {
List<Response> responses = new List<Response>();
for (Request req : requests) {
Response res = new Response();
res.isSuccess = true;
res.processedId = req.recordId;
responses.add(res);
}
return responses;
}
public class Request {
@InvocableVariable(label='Record ID' required=true)
public Id recordId;
}
public class Response {
@InvocableVariable(label='Is Success')
public Boolean isSuccess;
@InvocableVariable(label='Processed ID')
public Id processedId;
}
}templates/invocable-method.clspublic with sharing class RecordProcessor {
@InvocableMethod(label='Process Record' category='Custom')
public static List<Response> execute(List<Request> requests) {
List<Response> responses = new List<Response>();
for (Request req : requests) {
Response res = new Response();
res.isSuccess = true;
res.processedId = req.recordId;
responses.add(res);
}
return responses;
}
public class Request {
@InvocableVariable(label='Record ID' required=true)
public Id recordId;
}
public class Response {
@InvocableVariable(label='Is Success')
public Boolean isSuccess;
@InvocableVariable(label='Processed ID')
public Id processedId;
}
}templates/invocable-method.cls@IsTest
static void testPositive() {
Account acc = new Account(Name = 'Test', Industry = 'Tech');
insert acc;
Assert.areEqual('Tech', [SELECT Industry FROM Account WHERE Id = :acc.Id].Industry);
}
@IsTest
static void testNegative() {
try {
insert new Account(); // Missing Name
Assert.fail('Expected DmlException');
} catch (DmlException e) {
Assert.isTrue(e.getMessage().contains('REQUIRED_FIELD_MISSING'));
}
}
@IsTest
static void testBulk() {
List<Account> accounts = new List<Account>();
for (Integer i = 0; i < 251; i++) {
accounts.add(new Account(Name = 'Bulk ' + i));
}
insert accounts;
Assert.areEqual(251, [SELECT COUNT() FROM Account]);
}@IsTest
static void testPositive() {
Account acc = new Account(Name = 'Test', Industry = 'Tech');
insert acc;
Assert.areEqual('Tech', [SELECT Industry FROM Account WHERE Id = :acc.Id].Industry);
}
@IsTest
static void testNegative() {
try {
insert new Account(); // 缺少Name字段
Assert.fail('Expected DmlException');
} catch (DmlException e) {
Assert.isTrue(e.getMessage().contains('REQUIRED_FIELD_MISSING'));
}
}
@IsTest
static void testBulk() {
List<Account> accounts = new List<Account>();
for (Integer i = 0; i < 251; i++) {
accounts.add(new Account(Name = 'Bulk ' + i));
}
insert accounts;
Assert.areEqual(251, [SELECT COUNT() FROM Account]);
}| Exception Type | When to Use |
|---|---|
| Insert/update/delete failures |
| SOQL query failures |
| Null reference access |
| List operation failures |
| Governor limit exceeded |
| HTTP callout failures |
@IsTest
static void testExceptionHandling() {
try {
insert new Account(); // Missing required Name
Assert.fail('Expected DmlException was not thrown');
} catch (DmlException e) {
Assert.isTrue(e.getMessage().contains('REQUIRED_FIELD_MISSING'),
'Expected REQUIRED_FIELD_MISSING but got: ' + e.getMessage());
}
}| 异常类型 | 使用场景 |
|---|---|
| 插入/更新/删除失败 |
| SOQL查询失败 |
| 空引用访问 |
| 集合操作失败 |
| 超出Governor限制 |
| HTTP调用失败 |
@IsTest
static void testExceptionHandling() {
try {
insert new Account(); // 缺少必填Name字段
Assert.fail('Expected DmlException was not thrown');
} catch (DmlException e) {
Assert.isTrue(e.getMessage().contains('REQUIRED_FIELD_MISSING'),
'Expected REQUIRED_FIELD_MISSING but got: ' + e.getMessage());
}
}.cls.triggerapex-jorje-lsp.jar.cls.triggerapex-jorje-lsp.jar| Skill | When to Use | Example |
|---|---|---|
| sf-metadata | Discover object/fields before coding | |
| sf-data | Generate 251+ test records after deploy | |
| sf-deploy | Deploy to org - see Phase 4 | |
| sf-flow | Create Flow that calls your Apex | See @InvocableMethod section above |
| sf-lwc | Create LWC that calls your Apex | |
| 技能 | 使用场景 | 示例 |
|---|---|---|
| sf-metadata | 编码前发现对象/字段 | |
| sf-data | 部署后生成251+测试记录 | |
| sf-deploy | 部署到组织 - 参考阶段4 | |
| sf-flow | 创建调用Apex的Flow | 参考@InvocableMethod部分 |
| sf-lwc | 创建调用Apex的LWC | |
| Guide | Description |
|---|---|
| patterns-deep-dive.md | TAF, @InvocableMethod, async patterns, service layer |
| security-guide.md | CRUD/FLS, sharing, SOQL injection, guardrails |
| bulkification-guide.md | Governor limits, collections, monitoring |
| testing-patterns.md | Exception types, mocking, Test Data Factory, coverage |
| anti-patterns.md | Code smells, red flags, refactoring patterns |
| troubleshooting.md | LSP validation, deployment errors, debug logs |
| 指南 | 描述 |
|---|---|
| patterns-deep-dive.md | TAF、@InvocableMethod、异步模式、服务层 |
| security-guide.md | CRUD/FLS、共享机制、SOQL注入防护、防护规则 |
| bulkification-guide.md | Governor限制、集合、监控 |
| testing-patterns.md | 异常类型、模拟、测试数据工厂、覆盖率 |
| anti-patterns.md | 代码异味、危险信号、重构模式 |
| troubleshooting.md | LSP验证、部署错误、调试日志 |
| Document | Description |
|---|---|
| Bulkification, collections, null safety, guard clauses, DML performance |
| Code smells detection and refactoring patterns |
| 12 patterns including Domain Class, Abstraction Levels |
| TAF setup and advanced patterns |
| Complete CRUD/FLS and sharing reference |
| Complete test patterns and mocking |
| Variable, method, class naming rules |
| SOLID principles for Apex |
| 150-point scoring criteria |
| Complete @InvocableMethod guide |
| Flow-LWC-Apex integration |
| NEW: Common LLM code generation mistakes (Java types, non-existent methods, Map patterns) |
~/.claude/plugins/marketplaces/sf-skills/sf-apex/docs/| 文档 | 描述 |
|---|---|
| 批量处理优化、集合、空安全、防护子句、DML性能 |
| 代码异味检测与重构模式 |
| 12种模式,包括领域类、抽象层级 |
| TAF设置与高级模式 |
| 完整的CRUD/FLS和共享参考 |
| 完整测试模式与模拟 |
| 变量、方法、类命名规则 |
| Apex的SOLID原则 |
| 150分评分标准 |
| 完整的@InvocableMethod指南 |
| Flow-LWC-Apex集成 |
| 新增:LLM代码生成常见错误(Java类型、不存在的方法、Map模式) |
~/.claude/plugins/marketplaces/sf-skills/sf-apex/docs//plugin install github:Jaganpro/sf-skills/[skill-name]/plugin install github:Jaganpro/sf-skills/[skill-name]