-
Notifications
You must be signed in to change notification settings - Fork 0
Recommended Conventions for Salesforce Development
David B edited this page Feb 1, 2025
·
17 revisions
- Regularly refer to the Salesforce Metadata Coverage Report and:
- Avoid leveraging metadata types which are unsupported by
Unlocked Packaging - Avoid modifying Standard or Managed Metadata Types
- Avoid leveraging metadata types which are unsupported by
- Use PascalCase for custom objects and fields
- Avoid using underscores
- Use singular nouns for object names
- Avoid modifying the following Standard Metadata Types:
- Standard Page Layouts
- Standard Flexipages
- Standard Search Layouts
- Standard Compact Layouts
- Standard Value Sets (e.g.
Opportunity StagePicklist)
- When creating fields, always add them to the relevant Permission Set(s)
- Avoid changing field Data Types (generally better to introduce a new field and deprecate the old one as opposed to changing its type)
- Junction object names should reflect their primary relationships (eg a junction object joining
Survey__candPage__cshould be calledSurveyPage__c)
Tip
Most field types don't need type indicators - the name should describe its purpose clearly. Only use suffixes when they add clarity or help distinguish between similar fields.
Below are specific conventions for various field types:
| Field Type | Example Field Label | Example API Name | Notes |
|---|---|---|---|
| Most Fields | Annual Revenue | AnnualRevenue__c | No suffix needed |
| Lookup/Master-Detail | Account Manager | AccountManagerId__c | Use Id suffix |
| Date | Start Date | StartDate__c | Use Date when needed to distinguish from DateTime |
| DateTime | Start Time | StartDateTime__c | Use DateTime when needed to distinguish from Date |
| Percent | Discount | DiscountPct__c | Use Pct only when "Percent" isn't clear in name |
| Number | Sequence | SequenceNum__c | Use Num only when disambiguation needed |
| Legacy System IDs | Legacy LCS ID | LegacyLcsId__c | Use Id suffix |
- Use PascalCase for all class names
- Classes should be nouns (e.g.,
UserService) - Avoid abbreviations unless universally understood (e.g.,
Id,Http)
-
Test Classes: Suffix with
Test -
Trigger Handlers: Suffix with
TriggerHandler -
Triggers: Suffix with
BeforeorAfterto indicate execution order- Example:
AccountTriggerBefore
- Example:
-
Utility Classes: Suffix with
Util -
Scheduled Jobs: Suffix with
Schedule -
Invocable Classes: Suffix with
Action- Example:
AccountMergeAction - Always include human-friendly Labels and Descriptions
- Label example:
Merge Accounts - Description example:
This action attempts to automatically merge two account records
- Label example:
- Example:
-
Exception Classes: Suffix with
Exception- Example:
InvalidAccountException
- Example:
- Avoid "I" prefix for interfaces
- ✅ Use:
PayableInterface - ❌ Avoid:
IPayable
- ✅ Use:
classes/
├── account/
│ ├── AccountApi.cls
│ ├── AccountController.cls
│ ├── AccountService.cls
│ ├── AccountRepository.cls
│ └── client/
│ ├── AccountRequest.cls # Apex-Defined Type for incoming account creation requests
│ ├── AccountResponse.cls # Apex-Defined Type for API responses
│ └── AccountSearchCriteria.cls # Apex-Defined Type for complex search parameters
- Use camelCase
- Methods should be verbs
- Example:
getUserById
-
Accessors: Use
get/set -
Complex Operations: Use
compute/calculate -
General Actions: Start with verbs
- Examples:
getData,processRecord,validateInput
- Examples:
- Prefix with
test - Use descriptive names explaining the scenario
- ✅ Good Examples:
testUpdateAccountWithValidDatatestThrowsExceptionWhenEmailInvalid
- ❌ Avoid arbitrary suffixes
- Use camelCase
- Use meaningful plural/singular forms
✅ Correct Examples:
List<Account> accountsAccount primaryAccountList<Contact> activeContacts
❌ Incorrect Examples:
List<Account> accountAccount accountsList<Contact> contact
Use these prefixes:
-
is: For state
- Examples:
isValid,isActive
- Examples:
-
has: For possession
- Examples:
hasPermission,hasChildren
- Examples:
-
should: For conditions
- Examples:
shouldProcess,shouldUpdate
- Examples:
- Use UPPER_SNAKE_CASE
- Example:
MAX_ATTEMPTS
- Use PascalCase for flow names
- Avoid including redundant information in the Flow Name and Label. All of the following details are natively tracked by Salesforce and are therefore considered redundant:
- Active
- Api Version
- Environments
- Flow Namespace
- Created By
- Package Name
- Package State
- Process Type
- Source Template
- Template
- Trigger
- A single flow should be roughly analogous - in terms of its "Cognitive Complexity" - to a single Apex Method:
- Name follows typical verb-noun conventions: (e.g.,
CreateNewAccount,UpdateOpportunityStage,GetOpportunityProducts) - Single-Responsibility
- Reusable
- Self-contained
- Name follows typical verb-noun conventions: (e.g.,
- Avoid using the default screen header in Screen Flows
- Instead, disable the header and insert a "display text" element with a user-friendly title
- Tip: For screen flows with many screens, consider creating a Text Template variable to avoid creating the title in every screen
- Variable naming conventions:
- Input variables: prefix with
in_ - Output variables: prefix with
out_ - Collection variables: suffix with
_Collection - Loop variables: suffix with
_Current
- Input variables: prefix with
- Use all-caps snake-case for Validation Rule names (e.g.,
REQUIRE_CONTACT_METHOD) - Start with a verb describing the restriction:
PREVENT_DUPLICATE_NAMEPREVENT_NULL_LASTNAMEREQUIRE_ROLE_ADMIN
- Error messages should:
- Use clear, user-friendly language
- Include specific resolution steps
- Example: "Please provide at least one contact method (Email or Phone)"
- Use underscore (_) instead of spaces in report and dashboard names
- Start with the primary object name (e.g., "Opportunity_Pipeline_Summary")
- Use consistent folder structure:
- Format:
Department/Team/Category/Report_Name - Example:
Sales/Pipeline/Opportunity/Opportunity_Pipeline_Summary
- Format:
- For time-based reports, include date:
- Format:
Report_Name_YYYY_MM
- Format:
- Use verb phrases for button and link names
- For custom labels, use all-caps snake-case
OBJECT_ACTION_PURPOSE(e.g.,ACCOUNT_CREATE_ERROR,ACCOUNT_CREATE_SUCCESS,USER_SIGNIN_WELCOME)
- Use kebab-case for component names (e.g., "my-component")
- Use camelCase for properties and methods
- Suffix service components with "Service" (e.g., "dataService")
- Follow DRY & SOLID principles
- File naming conventions:
- HTML template:
myComponent.html - JavaScript:
myComponent.js - CSS:
myComponent.css - Test:
myComponent.test.js
- HTML template:
- Private methods/properties should start with underscore
- Event handler methods should end with
Handler(e.g.,clickHandler)
- Use PascalCase for page layout names
- Avoid modifying Standard Page Layouts
- Include the object name and any specific use case (e.g.,
AccountSalesLayout,ContactSupportLayout)
- Use PascalCase for Flexipage names
- Avoid modifying Standard Flexipages
- Include the purpose or app name (e.g.,
AccountDetailPage,SalesConsoleHomePage)
- Avoid using these altogether. They are not CICD-friendly.
- Instead, rely on Custom Metadata Types and/or Custom Permissions where applicable
- Use PascalCase for custom metadata type names
- Suffix with
SettingorConfig(e.g.,EmailServiceSetting,IntegrationConfig)
- Use PascalCase for custom permission names
- Create one
Custom Permissionper Persona-based custom permissions (e.g.isCallCenterUser,isFieldServiceManager)- Add these^ custom permissions to a permissionSet & permissionSetGroup of the same name (e.g.
CallCenterUser,FieldServiceManager) - In addition to sanitizing your permission schema, this also gives you some pretty incredible super powers...
- Add these^ custom permissions to a permissionSet & permissionSetGroup of the same name (e.g.
public void updateServiceCase(Case record) {
// Check if user has field service permissions
if (!FeatureManagement.checkPermission('isFieldServiceManager')) {
throw new CustomException('You do not have permission to update service cases');
}
// Proceed with update
update record;
}AND(
ISCHANGED(Status),
NOT($Permission.isCallCenterUser)
)