Enterprise Design Patterns have been around for a while to represent best practices for large scale development projects. First promoted by Martin Fowler in 2003 – “Patterns of Enterprise Application Architecture”. First Adapted to Salesforce by Andy Fawcett in 2014 – now known as “Salesforce Lightning Platform Enterprise Architecture, 3rd edition”
- Review basic Object-Oriented Analysis and Development themes
- Salesforce Lightning Enterprise Architecture patterns
- Selector Pattern
- Domain Pattern
- Service Pattern
- Unit of Work Pattern
- Application Factory Pattern
- Review of Apex Enterprise Patterns Open Source group and frameworks
Apex Enterprise Design Patterns
- Open Source Frameworks originally created by FinancialForce
- FFLIB Apex Mocks
- An Apex mocking framework for true unit testing in Salesforce, with Stub API support
- Based on the Java mocking framework Mockito
- FFLIB Apex Commons
- FFLIB Apex Mocks
- Framework which supports implementation of various Martin Fowler design patterns
- FFLIB frameworks are now maintained by the Apex Enterprise Patterns GitHub group
Basic OOAD Themes
Various principles and themes used in enterprise application development:
- Separation of Concerns
- DRY Principle
- SOLID Principle
- Dependency Injection
Separation of Concerns
- Enterprise software needs to change over time. It evolves.
- It’s one thing to write code to satisfy the immediate need. It’s another thing to write code that will be easy to maintain and be able to be changed over time.
- Complex code will become unmaintainable if proper boundaries are not established
Typical layers include:
- Declarative: Lightning UI/LEX, Page layouts, Reports, Dashboards, Screen Flow Types
- Programmatic: Lightning Web Components, Aura, Single Page Apps, Visualforce
- Business Logic Layer
- Declarative: Certain elements of Flows and Process Builders, Approval Processes
- Programmatic: Apex
- Data Access Layer
- Declarative: Flow Data Elements – Create Records, Update Records, Get Records, etc
- Programmatic: SOQL, SOSL, Salesforce REST and SOAP APIs
- Database Layer
- Declarative: Custom Objects, Fields, Relationships, Autolaunched Flow Types
- Programmatic: Apex Triggers
- “Don’t repeat yourself”
- “Every piece of knowledge must have a single, unambiguous, authoritative representation within a system”
- Single-responsibility principle
- A piece of logic should only have a single responsibility….and that responsibility should be entirely encapsulated by the class, module or function.
- Open-closed principle
- “Software entities … should be open for extension but closed for modification.”
- Liskov substitution principle
- “Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program”
- “Design by Contract”
- Interface segregation principle
- “Many client-specific interfaces are better than one general-purpose interface.” Don’t force a class to depend on methods that it does not use.
- Dependency inversion principle
- “Depend on abstractions and not concretions”
- Technique in which an object receives things that it depends on at runtime.
- Separates the creation of a dependency from the usage of a dependency
- Promotes the concept of “loosely coupled” system
A class responsible for all aspects of queries for a single SObject. It manages the fields to query and manages the specific queries. All classes use this class to make queries against this SObject. The pattern encourages bulkification. All method parameters are usually Sets of IDs and return Lists of the SObject. Returns List of SObjects or Database.QueryLocator.
A class responsible for the business logic specific to a single SObject. Sometimes viewed as “fine grain services”. It is a wrapper around the records you are working with. Initialize the domain class with all of the records of that type that you are working with in the current context. This can be one to many records. It does not manage the persistence of records (see UnitOfWork). Handles defaulting and validations. Once you have the domain class, you work with a single object, executing logic on the records.
- A class responsible for aggregating the logic across multiple SObjects
- Sometimes viewed as a “course-grained service”
- This is the traditional “Service Tier Contract” boundary
- All Presentation or “client-tier” logic calls the Service Tier logic
- Typically, the “client-tier” logic only calls a single Service method per transaction
- Becomes the DML Transaction boundary by utilizing a UnitOfWork (see UnitOfWork pattern)
Unit Of Work Pattern
- A “utility” class focused on
- Optimizing DML interactions with the Database layer
- Providing transactional control for the Service Layer
- Simplifying the complex code usually constructed to manage bulkified DML operations
- Managing the “plumbing” needed to save parent-child data relationships
- Used within a service method but passed to domain methods as needed.
- The UOW manages all DML transactions and rollbacks for all Service Layer logic
- Using an instance of UOW, you can register new records, modified/dirty records, and register records that need to be deleted.
- Once all records and changes are collected, the “commitWork()” method is called to begin DML transactions.
UOW manages relationships between parent and child records
- Since the UOW only holds records until the end of the Service method and the call to the “commitWork()” method, it needs to maintain the “connection” between parent and child records.
- The “registerRelationship” series of methods accomplish this.
- Reference line 54 of the InvoicingServiceTest class.
- The parent Opportunity record is registered at line 39 …but not saved to database yet
- Each of the child OpportunityLineItem records are
- Registered as new records to be saved at line 55
- Related to the parent Opportunity record at line 54 using the “registerRelationship” method
- During the “commitWork()” method execution, the UOW saves the parent Opportunity records, maintains a link to the new opportunity record id, and then adds that parent record id to the child OpportunityLineItem records before saving those new records.
|Date : Sat, AUG 22, 2020 10:00 AM EST (7:30 PM IST)|
Where : Apex Hours Youtube Live
Speaker : John M. Daniel
- Apex Enterprise Patterns — Separation of Concerns
- Apex Enterprise Patterns — Selector Layer
- Apex Enterprise Patterns — Domain Layer
- Apex Enterprise Patterns — Service Layer
- Apex Enterprise Patterns — Unit Of Work
- Apex Enterprise Patterns — FinancialForce Apex Common Updates
Amit Chaudhary is Salesforce Application & System Architect and working on Salesforce Platform since 2010. He is Salesforce MVP since 2017 and have 17 Salesforce Certificates.
He is a active blogger and founder of Apex Hours.