Naming Conventions

Project code prefix

First-party Apex classes, exceptions, and related global types use a project-specific prefix in ALL_CAPS, an underscore, and a descriptive PascalCase name (for example ACME_AccountService). How your team chooses and records that prefix—and how it lines up with LWC bundle naming—is covered in Project code prefix.

Classes

  • Format: <APEX_PREFIX>_ClassNameInPascalCase (placeholder: ACME_…)

  • Naming: ALL_CAPS project prefix, underscore, then descriptive PascalCase name

  • Pattern: <APEX_PREFIX>_<DescriptiveClassName>

  • Examples:

    public class ACME_AccountSelector { }
    public class ACME_AccountTriggerHandler { }
    public class ACME_PermissionUtils { }
    public class ACME_ProjectService { }

Methods

  • Format: camelCase

  • Naming: Verb-based names that describe the action performed

  • Examples:

    public static List<Account> getAccounts() { }
    public void processRecords(List<SObject> records) { }
    private Boolean validateInput(String input) { }

Variables

  • Format: camelCase

  • Naming: Be specific and self-documenting - prefer full words over unclear abbreviations (unless the abbreviation is widely understood). Name for what the value is (e.g. accountName not name, accountList not list), including temporaries.

  • Length: Single- and double-letter names are not allowed except for loop index variables (i, j, k, etc.).

  • Examples:

    // Good: Meaningful variable names
    String accountName = 'Test Account';
    Integer recordCount = 10;
    Boolean isLoading = true;
    List<Account> accountList = new List<Account>();
    Account currentAccount;
    String errorMessage = error.getMessage();
    
    // Good: Loop index variables (exception to the rule)
    for (Integer i = 0; i < items.size(); i++) {
        processItem(items[i]);
    }
    
    for (Integer j = 0; j < rows.size(); j++) {
        for (Integer k = 0; k < columns.size(); k++) {
            processCell(rows[j], columns[k]);
        }
    }
    
    // Bad: Single/double character variables (except loop indices)
    String a = 'Test Account'; // Bad - use accountName
    Integer x = 10; // Bad - use recordCount
    Account acc = [SELECT Id FROM Account LIMIT 1]; // Bad - use currentAccount or accountRecord
    String msg = error.getMessage(); // Bad - use errorMessage
    
    // Bad: Unclear abbreviations
    String accNm = 'Test Account'; // Bad - use accountName
    List<Account> accs = new List<Account>(); // Bad - use accountList or accounts
    Integer cnt = 0; // Bad - use recordCount or count

Constants

  • Format: UPPER_SNAKE_CASE

  • Naming: Descriptive names in all caps with underscores

  • Examples:

    static final String DEFAULT_STATUS = 'Active';
    static final Set<String> DATE_LITERALS = new Set<String>{
        'YESTERDAY', 'TODAY', 'TOMORROW'
    };
    static final Integer MAX_RETRY_ATTEMPTS = 3;

Exceptions

  • Format: PascalCase with "Exception" suffix

  • Naming: Descriptive name indicating the exception type

  • Examples:

    public class ACME_ValidationException extends Exception { }
    public class ACME_SecurityException extends Exception { }
    public class ACME_DataAccessException extends Exception { }

Inner Classes

  • Format: PascalCase (same as top-level classes)

  • Usage: Discretionary - wrappers and response classes are acceptable as inner classes, but don't overuse

  • Examples:

    public class ACME_AccountSelector {
        public class QueryResult {
            // Inner class for query results
        }
    }

Constants vs Enums

Note: Normative guidelines are deferred until the team agrees when to prefer Apex enum types versus static final constants (and how that interacts with picklists, packages, and integrations). Until then, use constants by default unless an existing module has already standardized on enums.

Code Organization

Class Structure Order

Classes should follow this order:

  1. Constants - Static final fields
  2. Properties - Instance and class variables
  3. Constructors - Class constructors
  4. Methods - Public methods first, then private/protected methods

Example:

public with sharing class ACME_AccountService {
    // 1. Constants
    private static final String DEFAULT_STATUS = 'Active';

    // 2. Properties
    private String accountName;
    private List<Contact> contacts;

    // 3. Constructors
    public ACME_AccountService() {
        contacts = new List<Contact>();
    }

    // 4. Public Methods
    public static Account createAccount(String name) {
        // Implementation
    }

    // 4b. Private Methods
    private Boolean validateAccount(Account acc) {
        // Implementation
    }
}

Package Organization

Code should be organized by feature/domain in your Salesforce DX package structure so related classes are easy to find and maintain:

force-app/
└── main/
    └── default/
        └── classes/
            ├── account/
            │   ├── ACME_AccountService.cls
            │   ├── ACME_AccountSelector.cls
            │   └── ACME_AccountTriggerHandler.cls
            ├── billing/
            │   ├── ACME_InvoiceService.cls
            │   └── ACME_PaymentGateway.cls
            └── shared/
                └── ACME_PermissionUtils.cls

Change History

Version 1.0 - 2026-03-26

  • Added initial version history tracking for this document.

Last Updated: 2026-03-26 Version: 1.0