Salesforce Apex Design Patterns
Salesforce Apex Design Patterns

Salesforce Apex Design Patterns

In this article, you'll:

  • Learn the basics and advanced aspects of apex design patterns, and get to know different categories and types of these patterns.
  • Explore each design pattern thoroughly, delving into usage scenarios and discovering the advantages presented by each pattern.
  • Go through the code examples without design patterns to understand their limitations, followed by a demonstration of how to apply relevant pattern.


What Are Apex Design Patterns?

Design patterns are best practices and proven solutions to to recurring design problems encountered during software development. These design patterns serve as guiding principles, aiding in structuring and organizing code to enhance efficiency, maintainability, and scalability of applications. The patterns not only streamline the development process but also contribute to building a robust foundation for future modifications and expansions.

Design patterns can be grouped into three main categories based on their purpose and usage.

  • Creational Patterns - Creational Patterns focus on object creation mechanisms, providing flexible ways to create instances of classes or objects enhancing reusability and control during instance creation.?
  • Structural Patterns - Structural patterns focus on organizing classes and objects into larger, clear structures, promoting better code organization and flexibility.
  • Behavioral Patterns - Behavioral patterns concentrate on the communication between classes and objects, optimizing delegation of responsibilities and enhancing system collaboration and flexibility.


Type Of Apex Design Patterns

Here are some common patterns we will be discussing in this article:

  1. Singleton Pattern - It's a creational design pattern which restricts the instantiation of a?class?to one “single” instance only within a single transaction context.
  2. Strategy Pattern - It’s behavioral design pattern that is used when there are multiples solutions to the same problem and solution or strategy to be selected at runtime.
  3. Decorator Pattern - It's structural design pattern that allows the introduction of new temporary fields for processing without altering the object structure.
  4. Facade Pattern - It's structural design pattern that provide the simpler interface and hides the complexity of complex classes.
  5. Bulk State Transition Pattern - It's behavioral design pattern that is used to perform bulk actions based on the change of state of one or more records.


Let's now go into the details of each design pattern.


1. Singleton Pattern

A fundamental creational design pattern, which ensures that a class has only one instance within a specific transaction context. This restriction is pivotal for scenarios where a singular instance of a class is sufficient to manage a particular resource or configuration throughout the application.

Problem Scenario

Let's see a code snippet below where we want to access application settings using a utility class. Without singleton pattern, one might unintentionally end up making many class instances. This could lead to unnecessary database queries impacting governor limits and potentially performance issues.

The Solution: Implementing Singleton Pattern

Let's modify the code snippet using the Singleton pattern. By applying the Singleton pattern, we ensure a single instance of ConfigurationManager is created. Subsequent requests for an instance will return the existing one, reducing redundant queries and enhancing efficiency.

Advantage of Singleton Pattern

  • Provides a single, global point of access to a class instance throughout the application.
  • Ensures only one instance is created, minimizing memory usage and avoiding unnecessary duplications.
  • Reduces object instantiation, enhancing performance and mitigating the impact of governor limits.
  • Supports lazy initialization, creating the instance only when first accessed, improving performance.


2. Strategy Pattern

It’s design behavioral pattern that comes into play when multiple solutions are available for a single problem, and the choice of solution or strategy needs to be made dynamically at runtime. It offers a structure to select the most right strategy based on the specific context.

Problem Scenario

Let's see a code snippet below where we want to handle different SMS gateways based on for distinct countries, such as UAE and Pakistan. Not using the Strategy Pattern can lead to complex, hard-to-maintain code and hinder extensibility. Additionally, it can pose challenges when multiple developers collaborate on the same class.

The Solution: Implementing Strategy Pattern

Advantages of Strategy Pattern

  • Strategies encapsulate algorithms or behaviors, promoting a clear separation of concerns and modularity within the codebase.
  • Strategies can be swapped or extended without modifying the context, allowing for flexibility and reusability of the code.
  • Each strategy is typically in its own class, making it easier to understand, maintain, and modify without affecting other parts of the system.
  • Strategies can be tested independently, facilitating unit testing and ensuring that each strategy functions correctly in isolation.
  • The Strategy Pattern adheres to the Open/Closed Principle, allowing for the addition of new strategies without modifying existing code.


3. Decorator Pattern

It’s is a structural design pattern that allows behavior to be added to individual objects, either statically or dynamically, without affecting the object structure.

Sometimes during code processing, we encounter scenarios where temporary additional fields are needed for intermediate calculations. Using the Decorator pattern, we can dynamically extend the behavior of objects by adding these transient fields at runtime, avoiding the need to create permanent custom fields in the database.

We can use decorator pattern in below example use cases.

  • You may need a selection checkbox without the necessity to persist its value in the database.
  • At times, there's a requirement to display a complex calculated field on a page, a scenario not achievable using a formula.

Problem Scenario

Imagine a scenario where a developer needed to calculate a complex amount that's meant for temporary use within a single class.

Without using the Decorator Pattern, developers might opt for common solutions like creating a formula field or a currency field and later updating or calculating the value.

The Solution: Implementing Decorator Pattern

Advantages of Decorator Pattern

  • Allows adding new functionalities or features dynamically without altering object structure.
  • Enables removal of added functionalities without affecting the original object.
  • Decorators can be reused across different objects promoting code reusability.
  • Functionality can be modified or extended dynamically at runtime by adding or removing decorators.


4. Facade Pattern

It's is a structural design pattern that provides a simplified interface to a complex system. It essentially offers a high-level view and hides the complex workings of the subsystems.

Problem Scenario

Let's see a code snippet below where a developer needed to handle email and SMS sending, account updating, and logging. In absence of Facade pattern, code code can become cluttered and hard to manage, making it prone to errors and difficult to extend or modify in the future.

The Solution: Implementing Facade Pattern

Advantages of Facade Pattern

  • Facade simplifies a complex system, providing an easy-to-use interface.
  • It hides intricate internal details, allowing users to interact at a higher level.
  • Users only need to work with a single, clear interface rather than multiple subsystems.
  • Developers can focus on their tasks without being overwhelmed by system complexity.
  • Changes to the internal subsystems can be managed within the facade, minimizing impact on users.


5. Bulk State Transition Pattern

It’s a behavioral design pattern to efficiently handle the transition of multiple records from one state to another. This pattern is particularly valuable when dealing with a significant number of records and needing to update or modify them collectively based on certain conditions or triggers. Instead of processing records one by one, process them in bulk minimizing the use of database operations and enhancing performance.

Problem Scenario

Let's see a code snippet below where order object being created once opportunity is closed won. In absence of bulk state transition pattern, hitting governor limits is likely due to excessive database operations in a loop, affecting performance and potentially causing the trigger to fail for a significant number of records.

The Solution: Implementing Bulk State Transition

Advantages of Bulk State Transition Pattern

  • Reduces database operations by processing records in bulk, improving performance.
  • Helps avoid hitting Salesforce's governor limits by minimizing DML and query operations.
  • Optimizes resource usage, reducing platform costs associated with excessive database actions.
  • Allows the system to handle a large volume of data and transactions efficiently.
  • Enhances code organization and readability, making it easier to manage and maintain.


Conclusion

Apex design patterns serve as essential principles that enable developers to build software solutions that are both efficient and easy to maintain. The discussed patterns, such as Singleton, Strategy, Decorator, Facade, and Bulk State Transition, significantly enhance code quality. Integrating these patterns into development practices elevate modularity, flexibility, and overall performance, laying the foundation for resilient and flexible applications.


Dear @Waqas, Very nice article.? I do agree with @Gaurav as regards Strategy Pattern. It would be nice to show Strategy implemented with Dependency Injection. Great article. All the best.

回复
Gaurav Jain

Sr IT Architect at IQVIA | Salesforce Certified Application Architect | Salesforce Certified Integration Architect | Salesforce Certified Data Architect | 9X Salesforce Certified | 4X Trailhead Ranger | Copado Certified

1 年

Nice article! However few comments - Singleton pattern :If you can add that how to make it thread safe, that would be great? E.g. getInstance() is being called from two different places and for both of them instance is null. Then will both thread not enter in the if statement and initialized it twice? How to prevent that ? Strategy Pattern: One of the main advantage of strategy pattern is , how to get rid of If and else statement. so e.g, if tomorrow you want to implement SMSSender for India , you need to write another if statement for India. I would rather change the design of SMSSender class and pass the interface variable in the SMSSender and use that to call. That way you can get rid of if and else as well. But overall you have summarized it very well!

Manish Yadav

Building Digital Experiences

1 年

Thank you for Sharing Waqas Ali - Vincent Oliver, Kevin Snell

回复

要查看或添加评论,请登录

社区洞察

其他会员也浏览了