10 Essential Principles for Writing Clean, Scalable, and Maintainable Apex Code

Apex is the core language for custom development in Salesforce. While powerful, it comes with strict governor limits and architectural considerations. Writing Apex is not just about making things work, It’s about making them scalable, testable, and ready for change. This decalogue presents 10 original and practical guidelines to help you build reliable solutions using Apex.

ARTICLES

Julio M.

7/31/20251 min read

1. Bulkify all your logic

Handle multiple records in a single execution. Never place SOQL or DML inside loops.

2. Implement proper error handling

Wrap critical operations, especially DML and callouts in try/catch and avoid generic exceptions where possible. Log useful context and, if appropriate, relay a user‑friendly error. Avoid catching generic Exception unless necessary. Catch the specific exception class you’re expecting (like CalloutException, DmlException, etc.).

3. Enforce security with CRUD & FLS

Enforce security with CRUD & FLS Always check field-level (FLS) and object-level permissions before accessing or modifying data. Use WITH SECURITY_ENFORCED in SOQL queries or Security.stripInaccessible() for DML operations.

4. Structure your code with layers and trigger frameworks

Avoid embedding logic directly inside triggers. Use a layered architecture: Trigger → Handler → Service → Utility. Employ frameworks like Kevin O’Hara’s to manage context (beforeInsert, afterUpdate, etc.) and keep triggers lightweight and testable.

5. Document every class and method

Use ApexDoc to annotate purpose, parameters, and return values. Include headers with author, version, and change log to support long-term maintenance.

6. Use asynchronous processing when necessary

When your logic performs heavy operations, long loops, or integrations, offload it using Queueable, Batchable, or @future. This keeps your code efficient and reliable.

7. Write robust, isolated tests

Cover positive, negative, edge, and bulk scenarios. Use @testSetup, Test.startTest(), Test.stopTest(), and advanced assertions. Avoid seeAllData=true.

8. Decide declarative vs programmatic wisely

Before writing Apex, consider: can this be done with a validation rule, flow, or formula? Apex is for complex logic, large data volumes, or cases where declarative tools fall short. Choose code only when necessary.

9. Optimize data access and logic reuse

Leverage Maps, Sets, and reusable utility classes (e.g. Utils.getMapById()) instead of re-querying inside loops. Avoid unnecessary heap usage and duplicate logic.

10. Follow consistent naming conventions

Names reflect your system’s clarity. Use PascalCase for classes, camelCase for variables and methods. Avoid abbreviations unless obvious. Write field names that are self-explanatory before the platform adds suffixes like __c.

Examples:

  • Class: InvoiceProcessor

  • Method: calculateTaxAmount

  • Custom field: SyncEnabled

  • Custom metadata: DeployConfiguration

Content

Related Stories

Related Stories