Introduction to FinancialForce Design Patterns

FinancialForce Apex Common Library offers a robust framework for Salesforce developers to streamline complex development tasks, improve code quality, and facilitate better maintenance. The library incorporates several design patterns that align with object-oriented best practices, aiding developers in creating scalable and robust applications on the Salesforce platform.

1. Service Layer Pattern

Definition: This pattern organizes business logic into services, separating it from the UI and data access layers. This separation enhances modularity and simplifies maintenance.

Use Case: Consider a Salesforce implementation for a financial services firm where you need to calculate the interest for different types of accounts. The service layer would handle the logic for these calculations, separate from the data retrieval (DAO layer) and the presentation layer (Visualforce or Lightning components).

Example:

public class InterestCalculationService {
    public Decimal calculateInterest(Account account) {
        // Logic to calculate interest
        return calculatedInterest;
    }
}

2. Domain Layer Pattern

Definition: This pattern centers around the domain model that encapsulates business logic within data objects, ensuring that the business rules and data management are close to the data they relate to.

Use Case: In an insurance application, the domain layer could manage the lifecycle of a policy, including state transitions from “New” to “Active” to “Closed.”

Example:

public class PolicyDomain extends fflib_SObjectDomain {
    public PolicyDomain(List<Policy__c> policies) {
        super(policies);
    }
    
    public void activatePolicies() {
        for (Policy__c policy : (List<Policy__c>) Records) {
            // Business logic to activate policy
            policy.Status__c = 'Active';
        }
    }
}

3. Selector Layer Pattern

Definition: This pattern abstracts the logic used to retrieve objects from the database into separate selector classes, which helps to encapsulate SOQL queries and makes the code more reusable and testable.

Use Case: Retrieving specific sets of accounts based on complex criteria that may be used across multiple components or services within an application.

Example:

public class AccountSelector extends fflib_SObjectSelector {
    public List<Account> selectById(Set<Id> ids) {
        return Database.query(
            fflib_QueryFactory.newInstance(Account.class)
                .selectFields('Name', 'Revenue__c')
                .setCondition('Id IN :ids')
                .toSOQL());
    }
}

4. Unit of Work Pattern

Definition: This pattern manages transactional logic by treating transactions as a unit of work, ensuring that all operations either complete successfully or roll back entirely.

Use Case: When updating multiple related records, such as creating an order and updating the inventory, both actions should either complete or fail together to maintain data integrity.

Example:

public void processOrder(Order order, List<OrderItem> items) {
    fflib_ISObjectUnitOfWork uow = Application.UnitOfWork.newInstance();
    
    uow.registerNew(order);
    for (OrderItem item : items) {
        uow.registerNew(item);
        uow.registerFieldUpdate(item.Product__c, 'Quantity__c', newQuantity);
    }
    
    uow.commitWork();
}

5. Application Factory Pattern

Definition: This pattern provides a central place to create and manage objects, which simplifies configuration and dependency management.

Use Case: Managing dependencies in a complex Salesforce application where service classes depend on multiple selector and domain classes.

Example:

public class Application {
    private static final fflib_Application.IFactory instance = new fflib_ApplicationFactory();

    public static AccountService getAccountService() {
        return (AccountService) instance.newInstance(AccountService.class);
    }
}

Conclusion

The FinancialForce Apex Common library brings powerful design patterns to Salesforce development, each addressing specific challenges in application design and maintenance. By leveraging these patterns, developers can build more maintainable, scalable, and robust applications on the Salesforce platform. The examples provided here illustrate how these patterns can be practically applied to enhance code quality and system architecture.

Leave a Comment