Development Principles

These are fundamental principles that guide our development practices in Salesforce projects. Following these principles ensures maintainable, secure, and efficient solutions.

Metadata Management

Do not keep unused metadata

Do not keep unused metadata (fields, Flows, classes, etc.) unless there's a very specific reason.

Why this matters:

  • Reduces technical debt and confusion for future developers

  • Improves org performance and reduces complexity

  • Makes deployments cleaner and more predictable

  • Reduces security surface area

Examples of unused metadata to remove:

  • Unused custom fields on objects

  • Inactive or obsolete Flows

  • Deprecated Apex classes and triggers

  • Unused custom objects

  • Outdated validation rules

  • Unused Lightning components

Exceptions:

  • Metadata required for data migration processes

  • Fields/objects needed for audit trails or compliance

  • Components that are temporarily disabled but will be reactivated

Security and Configuration

Do not hardcode IDs

Do not hardcode IDs (like Record Types, Users, Profiles, etc.)

Why this matters:

  • IDs are environment-specific and will break during deployments

  • Makes code fragile and difficult to maintain

  • Prevents proper testing across different environments

What not to do:

// Bad - hardcoded Record Type ID
if (account.RecordTypeId == '0120000000001ABC') {
    // logic here
}

// Bad - hardcoded User ID
if (UserInfo.getUserId() == '0050000000001XYZ') {
    // logic here
}

What to do instead:

// Good - use Record Type developer name
Id recordTypeId = Schema.SObjectType.Account.getRecordTypeInfosByDeveloperName()
    .get('Business_Account').getRecordTypeId();

// Good - use Custom Permissions or Custom Settings
if (FeatureManagement.checkPermission('Special_Access_Permission')) {
    // logic here
}

// Good - use Custom Metadata Types for configuration
Configuration__mdt config = Configuration__mdt.getInstance('Default');

Alternatives to hardcoding:

  • Use Record Type developer names with Schema methods

  • Use Custom Permissions for user-based logic

  • Use Custom Metadata Types for configuration data

  • Use Custom Settings for environment-specific values

Do not hardcode credentials

Do not hardcode credentials (e.g. passwords, API keys, etc.)

Why this matters:

  • Exposes sensitive information in version control

  • Creates serious security vulnerabilities

  • Makes credential rotation difficult

  • Violates security best practices and compliance requirements

Secure alternatives:

Use Named Credentials for external system authentication.

Automation Strategy

Avoid using record-triggered flows

Avoid using record-triggered flows (especially after-save record triggered flows, which have significant overhead). Instead, use a trigger framework.

Why this matters:

  • Record-triggered flows have substantial performance overhead compared to Apex triggers

  • Flows are harder to debug and maintain for complex business logic

  • Trigger frameworks provide better control over execution order and bulkification

  • Better testability and code reusability with Apex-based solutions

Reference:

Recommended trigger frameworks:

Migration strategy:

  • Identify existing record-triggered flows in your org

  • Prioritize migration based on performance impact and complexity

  • Implement trigger framework gradually

  • Test thoroughly before deactivating flows

Use Generic Users for Automated Jobs

When scheduling automated jobs, generally use a generic user account as the executor rather than personal user accounts.

Why:

  • Operational Continuity: If done with a person-tied user, if their user is deactivated, the process will stop working.

  • Clear Audit Trail: It's easier to track changes (like record updates) made by automations vs real humans.

Examples:

  • Bot accounts: "Integration Bot", "Report Bot"

  • Service accounts: "Data Sync Service", "Backup Service"

Last updated

Was this helpful?