-
Notifications
You must be signed in to change notification settings - Fork 0
Framework Architecture and Layers
The Apex Orbit Framework (AOF) is structured into distinct layers, each with a specific responsibility. This layered architecture promotes separation of concerns, making the framework modular, easier to understand, test, and maintain. The primary layers are: Trigger Handler, Service, Domain, Selector, Unit of Work, and Error Handling.
Component: AOF_TriggerHandler.cls
-
Purpose: This is the entry point for all SObject trigger logic. AOF employs a single trigger per SObject pattern. Instead of writing complex logic directly within individual SObject triggers (e.g.,
AccountTrigger.trigger), these triggers will be minimal, primarily responsible for instantiating and invoking theAOF_TriggerHandler. -
Functionality:
- Manages and provides access to trigger context variables (e.g.,
Trigger.new,Trigger.oldMap,Trigger.operationType). - Orchestrates the execution flow by delegating calls to the appropriate methods in the Domain Layer or, for more complex cross-object logic, the Service Layer. The dispatch is based on the SObject type and the specific trigger context (e.g.,
before insert,after update). - Includes a static bypass mechanism (e.g.,
AOF_TriggerHandler.bypassAllTriggers = true;or per-object bypass) to allow administrators or data migration processes to disable trigger logic temporarily. - Ensures that all calls to subsequent layers are inherently bulk-safe because it operates on the collections of records provided by the trigger context.
- The base
AOF_TriggerHandlercontains virtual methods for each trigger event (e.g.,beforeInsert(),afterUpdate()). These methods are intended to be called by therun()method. Concrete SObject-specific domain classes will implement the logic for these events.
- Manages and provides access to trigger context variables (e.g.,
-
SObject-Specific Triggers (e.g.,
AccountTrigger.trigger):- Each SObject that requires trigger logic will have a single trigger file.
- This trigger file will contain minimal code, typically just one line to instantiate
AOF_TriggerHandlerand call itsrun()method. -
Example (
AccountTrigger.trigger):trigger AccountTrigger on Account (before insert, after insert, before update, after update, before delete, after delete, after undelete) { new AOF_TriggerHandler(Account.SObjectType, Trigger.operationType).run(); }
Component: AOF_Application_Service.cls (Interface)
- Purpose: The Service Layer encapsulates business logic that is not tied to a single SObject or that orchestrates operations across multiple SObjects or layers. It handles more complex business processes, integrations with external systems, or operations that require a broader scope than a single SObject domain.
-
Functionality:
- The
AOF_Application_Serviceinterface defines a contract for service classes. Concrete service classes will implement this interface (or extend an abstract base service class if common service utilities are identified). -
SObject-Specific or Process-Specific Service Classes (e.g.,
AOF_AccountService.cls,AOF_OrderFulfillmentService.cls) contain the actual business logic. - Methods within service classes are designed to be bulkified, operating on lists or maps of SObjects or other relevant data structures.
- Services interact with the Selector Layer to query data and with the Unit of Work Layer to register DML operations.
- They can call methods in other service classes or in the Domain Layer for SObject-specific logic.
- Services can be responsible for managing transaction control for complex operations, although DML operations themselves are preferably delegated to the Unit of Work.
- The
Component: AOF_Application_Domain.cls (Abstract Class)
- Purpose: The Domain Layer represents the SObject itself and contains logic that is specific to individual records or collections of records of that SObject type. This layer is responsible for record-level business rules, validations, calculations, and manipulations that directly pertain to the state of an SObject.
-
Functionality:
- The
AOF_Application_Domainabstract class provides a base for SObject-specific domain classes. - Its constructor typically accepts
List<SObject>(fromTrigger.newor records to be processed) andMap<Id, SObject>(fromTrigger.oldMapfor update/delete contexts). -
SObject-Specific Domain Classes (e.g.,
AOF_AccountDomain.clsextendingAOF_Application_Domain) implement the concrete logic for a particular SObject. - These classes take the relevant SObject records in their constructor.
- They provide overrides for context-specific methods defined in
AOF_Application_Domain(e.g.,onBeforeInsert(),onAfterUpdate(),validate(),calculateRollups()). - All methods within domain classes are inherently bulkified as they operate on the collection of records passed into the domain class instance.
- The
AOF_TriggerHandlerdelegates the execution of trigger context-specific logic to these domain methods.
- The
Component: AOF_Application_Selector.cls (Abstract Class)
- Purpose: The Selector Layer is responsible for all SObject querying. It centralizes SOQL queries, making them reusable, optimized, and secure.
-
Functionality:
- The
AOF_Application_Selectorabstract class provides a base for SObject-specific selector classes. - It includes base methods for common query needs, dynamic field selection, ordering, and pagination (if needed).
- A core responsibility of this layer is to enforce security: Field-Level Security (FLS) and CRUD (Create, Read, Update, Delete) permissions. Queries should use
WITH SECURITY_ENFORCEDor results should be processed withSecurity.stripInaccessible()to ensure users only see data they are permitted to access. - The base class can provide utility methods to get the SObjectType, describe field information, and build dynamic queries safely.
-
SObject-Specific Selector Classes (e.g.,
AOF_AccountSelector.clsextendingAOF_Application_Selector) encapsulate all SOQL queries for a specific SObject. - Methods in these classes return
List<SObject>orMap<Id, SObject>and are named descriptively based on their query criteria (e.g.,selectByIds(Set<Id> ids),selectActiveAccountsByType(String type)). - Selectors are optimized for performance by querying only necessary fields and using efficient
WHEREclauses. They are inherently bulk-safe.
- The
Component: AOF_Application_UnitOfWork.cls (Class)
- Purpose: The Unit of Work (UoW) Layer manages DML (Data Manipulation Language) operations. It centralizes DML calls, ensuring they are performed efficiently, in the correct order, and within Salesforce governor limits by reducing the number of DML statements.
-
Functionality:
- The
AOF_Application_UnitOfWorkclass provides methods to register records for DML operations without immediately executing them (e.g.,registerNew(SObject record),registerDirty(SObject record),registerDeleted(SObject record)). It supports registering single records or lists of records. - A
commitWork()method is called (typically once, at the end of a logical transaction phase, often by theAOF_TriggerHandleror a controlling service method) to execute all registered DML operations in a bulkified manner (e.g., oneinsertcall for all registered new records). - The UoW can help manage transaction boundaries and can be configured to process DML operations grouped by SObject type if a specific order of operations is critical (e.g., insert Parent__c records before Child__c records).
- It helps in maintaining transaction integrity. By default, DML operations are performed with
allOrNone=true, meaning if one record fails, the entire batch for that DML statement rolls back. More granular error handling for partial success can be built in if required, but often a full rollback on error simplifies logic.
- The
- Purpose: To provide a robust, decoupled, and customizable mechanism for logging errors and exceptions that occur within the framework or application logic.
-
Components:
-
ErrorLogEvent__e(Platform Event): A custom Platform Event defined to carry error details. Using a Platform Event decouples the error logging from the main transaction, meaning the error log can be saved even if the original transaction that caused the error is rolled back.-
Recommended Fields:
Timestamp__c(DateTime),TransactionId__c(Text),OriginatingClassName__c(Text),OriginatingMethodName__c(Text),LineNumber__c(Number),ErrorMessage__c(Long Text Area),StackTrace__c(Long Text Area),SObjectType__c(Text, optional),RecordIds__c(Text, optional, comma-separated list of Ids involved in the error),Severity__c(Picklist: e.g., Critical, High, Medium, Low, Info).
-
Recommended Fields:
-
Error_Log__c(Custom SObject): A custom SObject used to persistently store error details captured by the Platform Event.-
Fields: Mirroring the Platform Event fields, plus additional fields for tracking and management, such as
ErrorLogName(Auto Number),Status__c(Picklist: New, Investigating, Resolved, Ignored),AssignedTo__c(User Lookup),ResolutionNotes__c(Long Text Area).
-
Fields: Mirroring the Platform Event fields, plus additional fields for tracking and management, such as
-
AOF_ErrorHandlerService.cls(Utility Class):- Provides static utility methods (e.g.,
logError(Exception ex, String className, String methodName, List<Id> recordIds, String sObjectTypeApiName, String severity)) to easily publishErrorLogEvent__eevents from anywhere in the code. - This service handles the instantiation and publishing of the Platform Event, ensuring it's done correctly and efficiently.
- It should include its own try-catch blocks to prevent the error logging mechanism itself from throwing unhandled exceptions.
- Provides static utility methods (e.g.,
-
Platform Event Subscriber (e.g.,
ErrorLogEventTriggeronErrorLogEvent__e):- An Apex trigger that subscribes to the
ErrorLogEvent__eevents. - When an event is received, this trigger creates and inserts
Error_Log__crecords in a bulkified manner. - This asynchronous processing ensures that the creation of the persistent error log record does not impact the performance or governor limits of the original transaction.
- An Apex trigger that subscribes to the
-
This layered architecture ensures that the Apex Orbit Framework is organized, scalable, and promotes best practices in Salesforce development.

Home
Quick Start
Usage Guide and Examples
Metadata‐Driven Trigger
Best Practices
Core Principles
Framework Architecture and Layers
Trigger Handler Layer
Service Layer
Domain Layer
Selector Layer
Unit of Work Layer
Error Handling Framework
Trigger Execution Flow
Scalability and Performance
Security Considerations
Core Components In-Depth
Error Handling In-Depth
Customization and Extension