platform-apex-generate

platform-apex-generate

熱門

主要的 Apex 撰寫技能,用於類別產生、重構與審查。當使用者提及 Apex、.cls、觸發程式,或要求建立/重構類別(服務、選擇器、領域、批次、佇列、排程、可呼叫、DTO、工具、介面、抽象、例外、REST 資源)時,務必啟用此技能。適用於涉及 SObject CRUD、集合映射、擷取關聯記錄、排程工作、批次工作、觸發程式設計、@AuraEnabled 控制器、@RestResource 端點、自訂 REST API 或現有 Apex 程式碼審查的請求。

769星標
281分支
更新於 2026/7/24
SKILL.md
唯讀
名稱
platform-apex-generate
描述

主要的 Apex 撰寫技能,用於類別產生、重構與審查。當使用者提及 Apex、.cls、觸發程式,或要求建立/重構類別(服務、選擇器、領域、批次、佇列、排程、可呼叫、DTO、工具、介面、抽象、例外、REST 資源)時,務必啟用此技能。適用於涉及 SObject CRUD、集合映射、擷取關聯記錄、排程工作、批次工作、觸發程式設計、@AuraEnabled 控制器、@RestResource 端點、自訂 REST API 或現有 Apex 程式碼審查的請求。

產生 Apex

使用此技能來處理生產級 Apex:新類別、選擇器、服務、非同步工作、
可呼叫方法與觸發程式;以及對現有 .cls.trigger 進行基於證據的審查。

必要輸入

在撰寫前收集或推斷:

  • 類別類型(服務、選擇器、領域、批次、佇列、排程、可呼叫、觸發程式、觸發動作、DTO、工具、介面、抽象、例外、REST 資源)
  • 目標物件與業務目標
  • 類別名稱(使用下方命名表格推導)
  • 全新建立 vs 重構/修正;任何組織/API 限制
  • 部署目標(預設使用 runSpecifiedTests,並在適用時使用產生的測試)

除非指定,否則預設值:

  • 共用:with sharing(請參閱下方各類型的共用規則)
  • 存取:public(僅在受管理套件或 @RestResource 要求時使用 global
  • API 版本:66.0(最低版本)
  • ApexDoc 註解:是

如果使用者提供明確且完整的請求,請立即產生,無需不必要的來回確認。


工作流程

所有步驟依序執行。請勿跳過、合併或重新排序。如果受阻,請停止並要求遺失的上下文。如果不適用,請在報告中以一行說明標記為 N/A

階段 1 — 撰寫

  1. 探索專案慣例

    • Service-Selector-Domain 分層、日誌工具
    • 現有類別/觸發程式與目前的觸發程式框架或處理器模式
    • 是否已使用 Trigger Actions Framework (TAF)
  2. 選擇最小且正確的模式(請參閱下方各類型指引)

  3. 審查範本與資源

    • 在撰寫前從 assets/ 讀取對應的範本(請參閱各類型指引以了解檔案對應)
    • 當該類型存在 references/ 範例時,將其作為具體的風格指南閱讀
    • 對於任何測試類別工作,務必閱讀並使用 platform-apex-test-generate 技能
  4. 在防護措施下撰寫 — 套用下方規則章節中的每一條規則

    • 產生包含 ApexDoc 的 {ClassName}.cls
    • 產生 {ClassName}.cls-meta.xml
  5. 產生測試類別 — 載入 platform-apex-test-generate 技能以建立 {ClassName}Test.cls{ClassName}Test.cls-meta.xml。部署時一律需要產生 Apex 測試。未載入 platform-apex-test-generate 技能則無法建立或編輯測試檔案。

階段 2 — 驗證(報告前必要)

撰寫檔案是中點,而非終點。步驟 6 和 7 各需要一次工具呼叫,並產生必須出現在步驟 8 報告中的輸出。在兩個步驟都執行完畢並擷取其輸出之前,請勿總結或呈現報告。

  1. 執行程式碼分析器

    • 對所有產生/更新的 .cls 檔案呼叫 MCP run_code_analyzer
    • 修正所有 sev0sev1sev2 違規;重新執行直到乾淨為止。
    • 將最終工具輸出逐字擷取到報告中。
    • 備用方案:sf code-analyzer run --target <target>。如果兩者都不可用,請在報告中記錄 run_code_analyzer=unavailable: <error>
  2. 執行 Apex 測試

    • 透過 sf apex run test 或 MCP 執行組織測試,包括 {ClassName}Test
    • 將所有測試產生/修正/覆蓋率工作委派給 platform-apex-test-generate;反覆執行直到測試通過。
    • 擷取通過/失敗計數與覆蓋率百分比到報告中。
    • 如果不可用,請在報告中記錄 test_execution=unavailable: <error>

階段 3 — 報告

  1. 報告 — 使用此檔案底部的輸出格式。
    • Analyzer 行必須包含實際的步驟 6 工具輸出(或在嘗試呼叫後顯示 run_code_analyzer=unavailable: <reason>)。
    • Testing 行必須包含實際的步驟 7 結果(或在嘗試呼叫後顯示 test_execution=unavailable: <reason>)。
    • 缺少任一行即為不完整報告。在記錄不可用之前,務必嘗試工具呼叫。

規則

硬性停止限制(必須強制執行)

如果產生的程式碼會違反任何限制,請在繼續之前停止並解釋問題

限制 理由
所有 SOQL 放在迴圈外部 避免查詢控管限制(100 個查詢)
所有 DML 放在迴圈外部 避免 DML 控管限制(150 個陳述式)
每個類別宣告共用關鍵字 防止非預期的 without sharing 預設值與資料暴露
使用自訂中繼資料/標籤/describe 呼叫,而非硬編碼 ID 確保跨組織的可移植性
務必處理例外(記錄、重新拋出或復原) 防止無聲失敗
對所有包含使用者輸入的動態 SOQL 使用繫結變數 防止 SOQL 注入
使用 Apex 原生集合(ListMapSet)而非 Java 類型 防止編譯錯誤
使用前確認方法存在於 Apex 中 防止依賴不存在的 API
避免在主程式碼路徑中使用 System.debug() 偵錯陳述式即使在未啟用記錄時也會評估並消耗 CPU。若主程式碼路徑需要,請使用記錄框架
絕不使用 @future 方法 使用 Queueable 搭配 System.Finalizer@future 無法鏈結、無法從批次呼叫,也無法接受非基本類型

批量化與控管限制

  • 所有公開 API 接受並處理集合;單一記錄多載委派給批量方法
  • 在批次/大量流程中,偏好部分成功 DML(Database.update(records, false))並處理 SaveResult 以取得錯誤
  • 使用 Map<Id, SObject> 建構子從查詢結果進行高效的 ID 查詢
  • 使用 Map<Id, List<SObject>> 按父項分組子記錄;在處理前於單一迴圈中建立映射
  • 使用 Set<Id> 進行重複資料刪除與成員資格檢查;偏好 Set.contains() 而非 List.contains()
  • 使用關聯子查詢在單一 SOQL 中同時擷取父項與子記錄(當兩者都需要時)
  • 使用 AggregateResult 搭配 GROUP BY 進行彙總計算,而非在 Apex 中查詢與計數
  • 僅對實際變更的記錄執行 DML — 在加入更新清單前,與 Trigger.oldMap 或先前狀態進行比較
  • 使用 Limits.getQueries()Limits.getDmlStatements()Limits.getCpuTime() 監控複雜交易中的消耗

SOQL 最佳化

  • 使用具備適當 WHERE 子句的選擇性查詢;在篩選條件中盡可能使用索引欄位(IdNameOwnerId、查閱/主從詳細資料欄位、ExternalId 欄位、自訂索引)
  • SOQL 中不存在 SELECT * — 務必指定確切需要的欄位
  • 套用 LIMIT 子句以限制結果集;使用 ORDER BY 確保確定性結果
  • 查詢自訂中繼資料類型(結尾為 __mdt 的物件)時,請勿使用 SOQL — 使用內建方法({CustomMdt__mdt}.getAll().values()getInstance() 等)

快取

  • 使用平台快取(Cache.Org / Cache.Session)處理頻繁存取但很少變更的資料;設定 TTL 並務必處理快取未命中 — 快取可能隨時被收回
  • 使用 private static Map 欄位作為交易範圍快取,以防止在同一執行內容中重複查詢;在首次存取時延遲初始化

安全性

  • 預設為 with sharing;記錄 without sharinginherited sharing 的理由
  • 在 SOQL 中使用 WITH USER_MODE,在 Database DML 中使用 AccessLevel.USER_MODE 以強制執行 CRUD/FLS
  • 透過允許清單或 Schema.describe 驗證動態欄位/運算子名稱
  • 所有外部憑證/API 金鑰使用命名憑證
  • @AuraEnabled 使用者面向錯誤使用 AuraHandledException(不包含內部詳細資訊)
  • without sharing 需要自訂權限檢查
  • without sharing 邏輯隔離在專用的輔助類別中;從 with sharing 進入點呼叫以限制提升存取範圍
  • 透過平台加密對靜態 PII/敏感資料進行加密;絕不在偵錯陳述式、錯誤訊息或 API 回應中暴露 PII

安全性驗證

在最終確定前,驗證:CRUD/FLS 已強制執行(SOQL + DML)· 每個類別有明確的共用關鍵字· 無硬編碼密碼或記錄 ID· PII 已從日誌和錯誤訊息中排除· 錯誤訊息已針對使用者進行清理。

錯誤處理

  • 在通用 Exception 之前捕獲特定例外;在訊息中包含上下文
  • 僅在可能拋出例外的程式碼周圍使用 try/catch(DML、呼叫、JSON 解析、型別轉換);避免對簡單指派/集合操作/算術進行防禦性包裝
  • 保留例外原因鏈結:new CustomException('message', cause)(不要用串接訊息取代堆疊追蹤)
  • 在有意義的情況下,為每個服務領域提供自訂例外類別
  • @AuraEnabled 方法中,捕獲例外並重新拋出為 AuraHandledException
  • 備用方案:當不存在有意義的領域例外時,捕獲通用 Exception 並重新拋出,或將其包裝在保留原始原因的最小自訂例外中。

空值安全

  • 在每個公開方法的頂部為 null/空輸入添加防護子句;根據上下文匹配風格:在私有/觸發處理器方法中 return 提前返回,在公開 API 中 throw 例外,在驗證服務中使用 record.addError()
  • 返回空集合而非 null
  • 使用安全導覽運算子(?.)進行鏈結屬性存取
  • 除非保證存在,否則不要內聯解參考 map.get(key);先使用 containsKey、指派+空值檢查或安全導覽
  • 使用 null 合併運算子(??)處理預設值
  • 偏好 String.isBlank(value) 而非手動檢查如 value == null || value.trim().isEmpty()

常數與字面值

  • 盡可能使用列舉而非字串常數;列舉值遵循 UPPER_SNAKE_CASE
  • 將重複的字串/數字提取為 private static final 常數或常數類別
  • 使用者面向字串使用 Label. 自訂標籤
  • 可設定的值(閾值、對應、功能旗標)使用自訂中繼資料
  • 絕不在程式碼中輸出 HTML 跳脫實體(例如 &#39;);在 Apex 字串字面值中使用單引號 '

命名慣例

類型 模式 範例
Service {SObject}Service AccountService
Selector {SObject}Selector AccountSelector
Domain {SObject}Domain OpportunityDomain
Batch {Descriptive}Batch AccountDeduplicationBatch
Queueable {Descriptive}Queueable ExternalSyncQueueable
Schedulable {Descriptive}Schedulable DailyCleanupSchedulable
DTO {Descriptive}DTO AccountMergeRequestDTO
Wrapper {Descriptive}Wrapper OpportunityLineWrapper
Utility {Descriptive}Util StringUtil
Interface I{Descriptive} INotificationService
Abstract Abstract{Descriptive} AbstractIntegrationService
Exception {Descriptive}Exception AccountServiceException
REST Resource {SObject}RestResource AccountRestResource
Trigger {SObject}Trigger AccountTrigger
Trigger Action TA_{SObject}_{Action} TA_Account_SetDefaults

其他命名規則:

  • 類別:PascalCase
  • 方法:camelCase,以動詞開頭(getcreateprocessvalidateishascan
  • 變數:camelCase,描述性名詞;清單使用複數名詞(例如 accountsrelatedContacts);映射使用 {value}By{key}(例如 accountsById);集合使用 {noun}Ids
  • 常數:UPPER_SNAKE_CASE
  • 使用完整描述性名稱而非縮寫(acctksrec

ApexDoc

  • 類別標頭與每個 public/global 方法都需要
  • 包含:簡短描述、@param@return@throws@example(如有幫助)

類別層級格式:

/**
 * 提供地理定位與地址轉換的服務。
 */
public with sharing class GeolocationService { }

方法層級格式:

/**
 * @param paramName 參數的描述
 * @return 回傳值的描述
 * @example
 * List<Account> results = AccountService.deduplicateAccounts(accountIds);
 */

程式碼結構與架構

  • 每個類別單一職責;最多 500 行 — 超過時拆分
  • 提前返回:在方法頂部驗證前置條件,立即返回/拋出
  • 對超過約 40 行的方法提取私有輔助方法
  • 使用依賴注入(建構子/方法參數)以利測試
  • 偏好組合與狹窄介面而非深度繼承;透過新實作而非修改來擴展
  • 在跨層邊界的方法中強制執行單一層級抽象:
層級 擁有 不得包含
Trigger 僅事件路由 業務邏輯、協調
Handler/Service 流程控制、協調 內聯 SOQL/DML/HTTP/解析
Domain 業務規則、驗證 查詢、呼叫、持久化細節
Data/Integration SOQL、DML、HTTP 業務決策
  • 不允許:混合協調與內聯 SOQL/DML/HTTP 的方法;業務規則與解析內部細節混合;在一個方法中混合驗證 + 持久化 + 跨系統管道

非同步決策矩陣

情境 預設 關鍵特性
標準非同步工作 Queueable 工作 ID、鏈結、非基本類型、可設定的延遲(透過 AsyncOptions 最多 10 分鐘)、重複簽章
非常大的資料集 Batch Apex 區塊處理,最多 5 個並行;對大型範圍使用 QueryLocator
現代批次替代方案 CursorStepDatabase.Cursor 2000 筆記錄區塊,更高吞吐量,無 5 工作限制
週期性排程 Scheduled Flow(偏好)或 Schedulable Schedulable 有 100 工作限制;僅在需要鏈結到批次或需要複雜 Apex 邏輯時使用
工作後清理 FinalizerSystem.Finalizer 無論 Queueable 成功/失敗都會執行
長時間執行的呼叫 Continuation 每個交易最多 3 個,3 個並行
延遲超過 10 分鐘 System.scheduleBatch() 在特定未來時間排程批次工作
舊版 fire-and-forget @future 請勿在新程式碼中使用 — 請參閱硬性停止限制;以 Queueable + Finalizer 取代

各類型指引

Service

  • 範本:assets/service.cls · 參考:references/AccountService.cls
  • with sharing;無狀態 — 無 public 欄位或可變的實例狀態;保持公開 API 專注,並在合理情況下設為 static
  • 將所有 SOQL 委派給 Selector,將 SObject 行為委派給 Domain
  • 將業務錯誤包裝在自訂例外中(例如 AccountServiceException

Selector

  • 範本:assets/selector.cls · 參考:references/AccountSelector.cls
  • inherited sharing;每個 SObject 或查詢領域一個
  • 返回 List<SObject>Map<Id, SObject>;使用共用的基礎欄位清單常數(無內聯重複)
  • 接受篩選參數;務必包含 WITH USER_MODE

Domain

  • 範本:assets/domain.cls
  • with sharing;封裝欄位預設值、衍生與驗證
  • 僅對記憶體中的清單進行操作;無 SOQL/DML(屬於 Service/Selector)

Batch

  • 範本:assets/batch.cls · 參考:references/AccountDeduplicationBatch.cls
  • with sharing;實作 Database.Batchable<SObject>(在跨區塊追蹤時加入 Database.Stateful
  • start() = 查詢定義;execute() = 業務邏輯;finish() = 記錄/通知
  • 對大型資料集使用 QueryLocator;透過 Database.SaveResult 處理部分失敗
  • 透過建構子接受篩選參數以利重複使用

Queueable

  • 範本:assets/queueable.cls
  • with sharing;實作 Queueable,並在需要 HTTP 呼叫時選擇性實作 Database.AllowsCallouts
  • 透過建構子接受資料
  • 加入鏈結深度防護以防止無限鏈結
  • 選擇性實作 Finalizer 以進行復原/清理
  • 使用 AsyncOptions 設定可設定的延遲(最多 10 分鐘)與重複簽章

Schedulable

  • 範本:assets/schedulable.cls
  • with sharingexecute() 委派給 Queueable 或 Batch
  • 提供 CRON 常數與便利的 scheduleDaily() 輔助方法

DTO / Wrapper

  • 範本:assets/dto.cls
  • 不需要共用關鍵字(純資料容器)
  • 簡單的公開屬性;無參數 + 參數化建構子;當排序重要時實作 Comparable
  • 對序列化/反序列化的私有/受保護內部 DTO 使用 @JsonAccess

Utility

  • 範本:assets/utility.cls
  • 不需要共用關鍵字;所有方法為 public staticprivate 建構子
  • 純粹、無副作用;無 SOQL/DML

Interface

  • 範本:assets/interface.cls
  • 在每個方法簽章上使用 ApexDoc 定義清晰的合約

Abstract

  • 範本:assets/abstract.cls
  • with sharing;透過 virtual 方法提供預設行為
  • 將擴充點標記為 protected virtualprotected abstract
  • 在 ApexDoc 中包含具體範例,展示如何擴充類別

Custom Exception

  • 範本:assets/exception.cls
  • 不需要共用關鍵字;使用描述性名稱擴充 Exception
  • 支援的建構子:()('msg')(cause)('msg', cause)

Trigger

  • 範本:assets/trigger.cls
  • 每個物件一個觸發程式;將所有邏輯委派給處理器/TAF 動作類別
  • 包含所有相關的 DML 上下文;如果使用 TAF:new MetadataTriggerHandler().run();

Trigger Action (TAF)

  • 每個關注點每個上下文一個類別;實作 TriggerAction.{Context}
  • 透過 Trigger_Action__mdt 註冊(未註冊的動作處於非啟用狀態)
  • 名稱:TA_{SObject}_{ActionName};偏好欄位值比較而非靜態布林值來處理遞迴

Invocable Method (@InvocableMethod)

  • 範本:assets/invocable.cls
  • with sharing;內部 Request/Response 搭配 @InvocableVariable
  • 方法必須為 public static;非靜態或單一物件簽章將無法編譯
  • 接受 List<Request>,返回 List<Response>;批量化(SOQL/DML 在迴圈外部)
  • 裝飾器參數:label(必要 — Flow Builder 顯示名稱)、descriptioncategory(在 Builder 中分組動作)、callout=true(當方法進行 HTTP 呼叫時必要)
  • @InvocableVariable 參數:label(必要)、descriptionrequired=true/false
  • @InvocableVariable 支援:基本類型、IdSObject、僅 List<T>(無 Map/Set/Blob);使用 List<Id>List<SObject> 欄位進行 Flow 集合 I/O
  • 務必在 Response 中包含 isSuccesserrorMessageerrorTypee.getTypeName()
  • 在 Response 中返回錯誤(建議);拋出例外會觸發 Flow Fault 路徑 — 僅保留給不可復原的失敗

REST Resource (@RestResource)

  • 範本:assets/rest-resource.cls
  • global with sharing;類別與方法都必須為 global
  • 版本化 URL:@RestResource(urlMapping='/{resource}/v1/*')
  • 根據分支使用適當的 HTTP 狀態碼(200/201/400/404/422/500);絕不將所有錯誤預設為 500
  • 驗證輸入(Id 格式:Pattern.matches('[a-zA-Z0-9]{15,18}', value));在 SOQL 中繫結所有使用者輸入
  • 在查詢中包含 LIMIT/ORDER BY;實作分頁(pageSize/offset
  • 標準化的 ApiResponse 包裝器(successmessagedata/records);內部請求/回應 DTO
  • 精簡控制器:將業務邏輯委派給 Service 類別

@AuraEnabled Controller

  • with sharing;在所有 SOQL 中使用 WITH USER_MODE
  • 僅對唯讀查詢使用 @AuraEnabled(cacheable=true);對 DML 操作不設定 cacheable
  • 捕獲例外並以使用者友善的訊息重新拋出為 AuraHandledException

輸出預期

每個類別的交付物:

  • {ClassName}.cls
  • {ClassName}.cls-meta.xml(預設 API 版本 66.0 或更高,除非指定)
  • {ClassName}Test.cls(透過 platform-apex-test-generate 技能產生)
  • {ClassName}Test.cls-meta.xml(透過 platform-apex-test-generate 技能產生)

每個觸發程式的交付物:

  • {TriggerName}.trigger
  • {TriggerName}.trigger-meta.xml(預設 API 版本 66.0 或更高,除非指定)

Meta XML 範本:

<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>{API_VERSION}</apiVersion>
    <status>Active</status>
</ApexClass>

報告按此順序:

Apex work: <摘要>
Files: <路徑>
Design: <模式 / 框架選擇>
Workflow: 所有步驟已完成 (1-8);任何 N/A 已說明理由
Risks: <安全性、批量化、非同步、相依性備註>
Analyzer: <必要 — 貼上實際的 run_code_analyzer 輸出,或說明 "run_code_analyzer=unavailable: <reason>">
Testing: <必要 — 貼上實際的測試執行結果(通過/失敗、覆蓋率),或說明 "test_execution=unavailable: <reason>">
Deploy: <乾執行或下一步>

跨技能整合

需求 委派給
Apex 測試 / 修正失敗 platform-apex-test-generate 技能
描述物件/欄位 metadata 技能(如果可用)
部署到組織 deploy 技能(如果可用)
Flow 呼叫 Apex Flow 技能(如果可用)
LWC 呼叫 Apex LWC 技能(如果可用)

疑難排解邊界

此技能僅處理生產 .cls/.trigger/.apex 問題:編譯/解析失敗、部署相依性錯誤、執行時期控管限制失敗。對於測試執行、斷言、覆蓋率或 sf apex run test 失敗,請委派給 platform-apex-test-generate