Apex Class
Generate well-structured, production-ready Apex classes for Salesforce development.
Scope
Generates:
- •Service classes (business logic layer)
- •Selector / query classes (SOQL encapsulation)
- •Domain classes (SObject-specific logic)
- •Batch Apex classes (
Database.Batchable) - •Queueable Apex classes (
Queueable, optionallyFinalizer) - •Schedulable Apex classes (
Schedulable) - •DTO / wrapper / request-response classes
- •Utility / helper classes
- •Custom exception classes
- •Interfaces and abstract classes
Does NOT generate:
- •Triggers (use a trigger framework skill)
- •Unit tests (use a test writer skill)
- •Aura controllers
- •LWC JavaScript controllers
Gathering Requirements
Before generating code, gather these inputs from the user (ask if not provided):
- •Class type — Service, Selector, Batch, Queueable, Schedulable, Domain, DTO, Utility, Interface, Abstract, Exception
- •Class name — or enough context to derive a meaningful name
- •SObject(s) involved — if applicable
- •Business requirements — plain-language description of what the class should do
- •Optional preferences:
- •Sharing model (
with sharing,without sharing,inherited sharing) - •Access modifier (
publicorglobal) - •API version (default:
62.0) - •Whether to include ApexDoc comments (default: yes)
- •Sharing model (
If the user provides a clear, complete request, generate immediately without unnecessary back-and-forth.
Code Standards — ALWAYS Follow These
Separation of Concerns
- •Service classes contain business logic. They call Selectors for data and may call Domain classes for SObject-specific behavior.
- •Selector classes encapsulate all SOQL queries. Services never contain inline SOQL.
- •Domain classes encapsulate SObject-specific logic (field defaults, validation, transformation).
- •Keep classes focused on a single responsibility.
Bulkification
- •All methods must operate on collections (
List,Set,Map) by default. - •Never accept a single SObject when a
List<SObject>is appropriate. - •Provide convenience overloads for single-record callers only when it makes the API cleaner, and have them delegate to the bulk method.
Governor Limit Safety
- •No SOQL or DML inside loops. Ever.
- •Collect IDs/records first, query/DML once outside the loop.
- •Use
Limitsclass checks in batch/bulk operations where appropriate. - •Prefer
Database.insert(records, false)with error handling in batch contexts.
Sharing Model
- •Default to
with sharingunless the user specifies otherwise. - •If
without sharingorinherited sharingis used, add an ApexDoc@descriptioncomment explaining WHY.
Naming Conventions
| Class Type | Pattern | Example |
|---|---|---|
| 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, DateUtil |
| Interface | I{Descriptive} | INotificationService |
| Abstract | Abstract{Descriptive} | AbstractIntegrationService |
| Exception | {Descriptive}Exception | AccountServiceException |
ApexDoc Comments
Include ApexDoc on every public and global method and on the class itself:
apex
/** * @description Brief description of what the class does * @author Generated by Apex Class Writer Skill */
apex
/** * @description Brief description of what the method does * @param paramName Description of the parameter * @return Description of the return value * @example * List<Account> results = AccountService.deduplicateAccounts(accountIds); */
Null Safety
- •Use guard clauses at the top of methods for null/empty inputs.
- •Use safe navigation (
?.) where appropriate. - •Return empty collections rather than
null.
Constants
- •No magic strings or numbers in logic.
- •Use
private static finalconstants or a dedicated constants class. - •Use
Label.custom labels for user-facing strings when appropriate.
Custom Exceptions
- •Each service class should define or reference a corresponding custom exception.
- •Inner exception classes are preferred for simple cases:
public class AccountServiceException extends Exception {} - •Include meaningful error messages with context.
Error Handling
- •Catch specific exceptions, not generic
Exceptionunless re-throwing. - •Log errors meaningfully (assume a logging utility exists or stub one).
- •In batch contexts, use
Database.SaveResult/Database.UpsertResultwith partial success.
Output Format
For every class, produce TWO files:
- •
{ClassName}.cls— The Apex class source code - •
{ClassName}.cls-meta.xml— The metadata file
Meta XML Template
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>
Default apiVersion is 62.0 unless the user specifies otherwise.
Class Type–Specific Instructions
Service Classes
- •Read and follow:
templates/service.cls - •Stateless — no instance variables holding mutable state
- •All public methods should be
staticunless there's a compelling reason for instance methods - •Delegate queries to a Selector class
- •Wrap business logic errors in a custom exception
Selector Classes
- •Read and follow:
templates/selector.cls - •One Selector per SObject (or per logical query domain)
- •Return
List<SObject>orMap<Id, SObject> - •Accept filter criteria as method parameters, not hardcoded
- •Include a private method that returns the base field list to keep DRY
Domain Classes
- •Read and follow:
templates/domain.cls - •Encapsulate field-level defaults, derivations, and validations
- •Operate on
List<SObject>— designed to be called from triggers or services - •No SOQL or DML — only in-memory SObject manipulation
Batch Classes
- •Read and follow:
templates/batch.cls - •Implement
Database.Batchable<SObject>and optionallyDatabase.Stateful - •Use
Database.QueryLocatorinstart()for large datasets - •Handle partial failures in
execute()usingDatabase.SaveResult - •Implement meaningful
finish()— at minimum, log completion
Queueable Classes
- •Read and follow:
templates/queueable.cls - •Implement
Queueableand optionallyDatabase.AllowsCallouts - •Accept data through the constructor — queueables are stateful
- •For chaining, include guard logic to prevent infinite chains
- •Optionally implement
Finalizerfor error recovery
Schedulable Classes
- •Read and follow:
templates/schedulable.cls - •Implement
Schedulable - •Keep
execute()lightweight — delegate to a Batch or Queueable - •Include a static method that returns a CRON expression for convenience
- •Document the expected schedule in ApexDoc
DTO / Wrapper Classes
- •Read and follow:
templates/dto.cls - •Use
publicproperties — no getters/setters unless validation is needed - •Include a no-arg constructor and optionally a parameterized constructor
- •Implement
Comparableif sorting is needed - •Keep them serialization-friendly (no transient state unless intentional)
Utility Classes
- •Read and follow:
templates/utility.cls - •All methods
public static - •Class should be
public with sharingwith aprivateconstructor to prevent instantiation - •Group related utilities (e.g.,
StringUtil,DateUtil,CollectionUtil) - •Every method must be side-effect-free (no DML, no SOQL)
Interfaces
- •Read and follow:
templates/interface.cls - •Define the contract clearly with ApexDoc on every method signature
- •Use meaningful names that describe the capability:
INotificationService,IRetryable
Abstract Classes
- •Read and follow:
templates/abstract.cls - •Provide default implementations for common behavior
- •Mark extension points as
protected virtualorprotected abstract - •Include a concrete example in the ApexDoc showing how to extend
Custom Exceptions
- •Read and follow:
templates/exception.cls - •Extend
Exception - •Keep them simple — Apex exceptions don't support custom constructors well
- •Name them descriptively:
AccountServiceException,IntegrationTimeoutException
Generation Workflow
- •Determine the class type from the user's request
- •Read the corresponding template from
templates/ - •Read relevant examples from
examples/if the class type has one - •Apply the user's requirements to the template pattern
- •Generate the
.clsfile with full ApexDoc - •Generate the
.cls-meta.xmlfile - •Present both files to the user
- •Include a brief note on design decisions if any non-obvious choices were made
Anti-Patterns to Avoid
- •❌ SOQL or DML inside loops
- •❌ Hardcoded IDs or record type names (use
Schema.SObjectTypeor Custom Metadata) - •❌ God classes that mix query + logic + DML
- •❌
publicfields on service classes - •❌ Returning
nullfrom methods that should return collections - •❌ Generic
catch (Exception e)without re-throwing or meaningful handling - •❌ Business logic in Batch
start()methods - •❌ Tight coupling between classes — use interfaces for extensibility
- •❌ Magic strings or numbers
- •❌ Methods longer than ~40 lines — break them into private helpers