DEV Community

Niranjani Mishra
Niranjani Mishra

Posted on

FFLIB – The Old but Gold Framework Every Salesforce Developer Should Know

Introduction

Salesforce development has evolved over the years, but one framework has stood the test of time: FFLIB (Apex Common). Despite being around for a while, it remains a powerful tool, especially for large-scale enterprises dealing with complex business logic.
As Salesforce apps grow, managing scalability, testability, and modularity becomes tough. FFLIB (Apex Common) simplifies this by enforcing Apex Enterprise Patterns, making code structured and maintainable. This blog explores FFLIB, its relevance, and how it benefits large-scale industries handling complex structure.

What is FFLIB?

FFLIB (FinancialForce Library) is an Apex framework designed to enforce separation of concerns in Salesforce applications. It is built around Domain-Driven Design (DDD) and Enterprise Patterns to ensure clean, maintainable, and reusable code. It is particularly beneficial in scenarios where organizations deal with complex schemas, business calculations, and high-volume transactions using features like Flows, Triggers, Batches, Queueables, and Callouts.

Domain-Driven Layered Architecture in Apex

Key Components of FFLIB

  1. Domain Layer – Encapsulates business logic related to SObjects.
  2. Service Layer – Acts as an interface between the domain layer and external systems.
  3. Selector Layer – Optimizes SOQL queries and enforces bulk processing.
  4. Unit of Work (UOW) – Ensures efficient DML operations by batching inserts, updates, and deletes, reducing governor limits impact and improving transaction control.
  5. Recognition Service - Business rule evaluator.

Why Use FFLIB in Large-Scale Industries?

1. Separation of Concerns for Maintainability

  • Large enterprises often have multiple teams working on the same system. FFLIB enforces clear separation between layers, reducing conflicts and making debugging easier.
  • For example, Triggers should not contain business logic. Instead, logic should be placed in Domain and Service layers, making code modifications easier without breaking existing automation.

2. Bulkification & Performance Optimization

  • Enterprise applications handle millions of records. FFLIB ensures that queries and DML operations comply with governor limits.
  • Example: Instead of making multiple SOQL calls in a loop, FFLIB’s Selector Layer optimizes queries to fetch only the required fields.

3. Unified Handling of Asynchronous Processing

  • Complex systems involve Batches, Queueables, and Future Methods for high-volume processing.
  • FFLIB allows consistent handling of these by centralizing logic within the Service Layer, ensuring reliable retry mechanisms and error handling.

4. Callouts and External System Integrations

  • When making external API callouts, developers often struggle with managing responses and errors.
  • FFLIB provides structured handling through Service Layers, making it easier to mock callouts in test classes and ensure proper API response processing.

5. Unit of Work for Efficient DML Management

  • The Unit of Work (UOW) pattern in FFLIB helps batch multiple DML operations into a single commit, improving efficiency and reducing governor limit risks.
  • Instead of performing individual DML operations, FFLIB's fflib_UnitOfWork collects all inserts, updates, and deletes and executes them in a controlled manner.

Example: Using Unit of Work in Order Processing

public class OrderService {
    public void createOrderWithItems(Order__c order, List<Order_Item__c> items) {
        fflib_UnitOfWork uow = new fflib_UnitOfWork(new Schema.SObjectType[]{Order__c.SObjectType, Order_Item__c.SObjectType});
        uow.registerNew(order);
        for (Order_Item__c item : items) {
            uow.registerNew(item);
        }
        uow.commitWork();
    }
}
Enter fullscreen mode Exit fullscreen mode
  • This ensures all records are committed together, avoiding partial inserts or unnecessary rollbacks.

6. Enhanced Testability & Dependency Injection

  • In large-scale applications, testing is critical. FFLIB uses Dependency Injection, allowing developers to mock dependencies and run unit tests without hitting the database.

Complex Use Case: Multi-Step Order Processing with FFLIB

Scenario: A large e-commerce enterprise needs to process customer orders that involve:

  • Order validation (Triggers & Domain Layer)
  • Inventory check & reservation (Service Layer & Queueable)
  • Payment processing via an external API (Callout & Future Method)
  • Batch processing for order fulfillment (Batch Apex)

Implementation

1. Order Trigger Calling Domain Logic

trigger OrderTrigger on Order__c (before insert, before update) {
    fflib_SObjectDomain.triggerHandler(OrderDomain.class);
}
Enter fullscreen mode Exit fullscreen mode

2. Domain Layer - Business Logic

public class OrderDomain extends fflib_SObjectDomain {
    public OrderDomain(List<Order__c> records) {
        super(records);
    }
    public override void onValidate() {
        for (Order__c order : Records) {
            if (order.Total_Amount__c <= 0) {
                throw new fflib_SObjectDomainException('Order total must be greater than zero');
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

3. Service Layer - Inventory Check & Payment Processing

public class OrderService {
    public void processOrder(Id orderId) {
        Order__c order = new OrderSelector().selectById(orderId);

        // Check Inventory (Queueable)
        System.enqueueJob(new InventoryCheckQueueable(order));

        // Process Payment (Callout)
        PaymentProcessor.processPayment(order);
    }
}
Enter fullscreen mode Exit fullscreen mode

4. Queueable - Inventory Check

public class InventoryCheckQueueable implements Queueable {
    private Id orderId;
    public InventoryCheckQueueable(Order__c order) {
        this.orderId = order.Id;
    }
    public void execute(QueueableContext context) {
        // Check and reserve inventory
        System.debug('Checking inventory for Order: ' + orderId);
    }
}
Enter fullscreen mode Exit fullscreen mode

5. Callout - Payment Processing

public class PaymentProcessor {
    @future(callout=true)
    public static void processPayment(Order__c order) {
        HttpRequest req = new HttpRequest();
        req.setEndpoint('https://payment-gateway.com/api/pay');
        req.setMethod('POST');
        req.setBody('{"orderId":"' + order.Id + '", "amount": ' + order.Total_Amount__c + '}');
        new Http().send(req);
    }
}
Enter fullscreen mode Exit fullscreen mode

6. Batch - Order Fulfillment Processing

public class OrderFulfillmentBatch implements Database.Batchable<SObject> {
    public Database.QueryLocator start(Database.BatchableContext context) {
        return Database.getQueryLocator('SELECT Id, Status__c FROM Order__c WHERE Status__c = 'Pending');
    }
    public void execute(Database.BatchableContext context, List<SObject> scope) {
        for (Order__c order : (List<Order__c>)scope) {
            order.Status__c = 'Shipped';
        }
        update scope;
    }
    public void finish(Database.BatchableContext context) {
        System.debug('Order fulfillment completed.');
    }
}
Enter fullscreen mode Exit fullscreen mode

Flow of Execution

  1. Trigger invokes the Domain Layer to validate order details.
  2. Service Layer processes the order, enqueuing inventory checks and initiating payment processing.
  3. Queueable Inventory Check ensures stock is available before processing payment.
  4. Future Callout processes the payment, ensuring Salesforce limits are respected.
  5. Batch Apex fulfills the order by updating the status after processing.

Additional Learning Resources

Conclusion

FFLIB provides a structured and scalable way to implement Apex Enterprise Patterns in Salesforce. By adopting this framework, developers can create applications that are modular, maintainable, and testable, ensuring long-term success.

Why Large Enterprises Should Use FFLIB

  • Handles Complex Business Logic (Flows, Batches, Queueables, Callouts)
  • Ensures Performance Optimization (SOQL Selectors, Bulk DML, UOW)
  • Enforces Scalable Architecture (Domain-Driven Design)
  • Improves Testability & CI/CD Readiness (Mocking & Dependency Injection)

Whether you're working on a small project or a large-scale enterprise application, FFLIB can help streamline your Apex development.

Happy Coding!

Top comments (0)