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:
/**
* @description Brief description of what the class does
* @author Generated by Apex Class Writer Skill
*/
/**
* @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 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