Eric Broadaway Director Of Design Apex Tool Group
By Dennis Thong, Manu Erwin and Eric Santiago
Apex allows you to build just about any custom solution on the Force.com platform. But what are the common design patterns and associated best practices for Apex development, and how can you leverage these patterns and best practices to avoid reinventing the wheel?
This article describes how to leverage common design patterns to optimize your code and ensure reusability, maintainability and performance. This is a wiki version of the Dreamforce 2012 presentation 'Apex Design Patterns'.
Contents
- 1 Common Design Patterns
- 2 Singleton
- 2.1 Problem
- 2.2 Unified Modeling Language
- 2.3 Implementation
- 2.4 Conclusion
- 3 Strategy
- 3.1 Problem
- 3.2 Unified Modeling Language
- 3.3 Implementation
- 3.4 Conclusion
- 4 Decorator
- 4.1 Problem
- 4.2 Unified Modeling Language
- 4.3 Implementation
- 4.4 Conclusion
- 5 Facade
- 5.1 Problem
- 5.2 Unified Modeling Language
- 5.3 Implementation
- 5.4 Conclusion
- 6 Composite
- 6.1 Problem
- 6.2 Unified Modeling Language
- 6.3 Implementation
- 6.3.1 Examples/Usage
- 6.4 Conclusion
- 7 Bulk State Transition
- 7.1 Problem
- 7.2 Unified Modeling Language
- 7.3 Implementation
- 7.4 Conclusion
- 8 About the Authors
Common Design Patterns
The following are a list of design patterns, some of which are standard object-oriented patterns in a Force.com context, and some of which are specific Force.com patterns.
- Singleton - minimizing object instantiation for improved performance and to mitigate impact of governor limits
- Strategy - defining a family of algorithms, enscapsulating each one and making them interchangeable and selectable at runtime
- Decorator - extending the functionality of an sObject in Apex
- Facade - simplifying the execution of classes with complex interfaces (e.g. web service callouts)
- Composite - treating a group of objects in a similar manner to a single instance of that object
- Bulk State Transition - efficiently tracking the change of a field value in a trigger and executing functionality based on this change
Singleton
The Singleton pattern attempts to solve the issue of repeatedly using an object instance, but only wishing to instantiate it once within a single transaction context. Common uses for this pattern include:
- Global variables - whilst Apex does not support global variables across execution contexts, this pattern allows you to create an object instance that will only ever be instantiated once within an execution context.
- Limiting Impact of Governor Limits - certain system objects and methods, such as Apex Describes, are subject to governor limits. The Singleton pattern allows repeated reference to these without breaching governor limits.
- As an implementation to other patterns - other design patterns, such as Facade, are often implemented as Singletons.
However, it's most common use is to create an object instance that's instantiated only once for the lifetime of that execution context.
Problem
Developers often write inefficient code that can cause repeated instantiation of objects. This can result in inefficient, poorly performing code, and potentially the breaching of governor limits. This most commonly occurs in triggers, as they can operate against a set of records.
The following code shows an example of repeated code invocation that can result in a breach of governor limits:
The Trigger
The Class
The trigger will cause a repeated execution of the sObject getDescribe() method, resulting in a breach of the total number of describes governor limit if the trigger operates against more than 100 records.
Unified Modeling Language
Implementation
In order to implement a Singleton pattern in Apex, the class must instantiate only a single instance and be globally accessible. It is implemented by:
- Creating a class with a method that creates a new instance of the class if it doesn't already exist
- If it already exists, then simply return a reference to that object
The following code sample demonstrates an implementation of the Singleton pattern for returning a record type describe within a trigger:
The Trigger
The Singleton Class
The above code demonstrates the following:
- The getInstance() static method will only instantiate an instance of the class if it doesn't already exist in a lazy-initialization manner
- The constructor and the instance variable for the class is private to make sure that it cannot be instantiated outside of the getInstance() method
- The class defines a private, static instance of itself that can only be referenced via the getInstance() static method
- The ID member stores the record ID of the record type and is initialized in the constructor
This allows the trigger to obtain a reference to the record type without breaching governor limits.
The following code sample shows how to use eager-initialization so that a new instance is always created when the class is instantiated.
The Singleton Class - Eager Initialization variant
The instance of the class is instantiated as a final, static variable, which means that only one instance ever exists. This method is typically used if the cost of creating the instance is small.
Conclusion
The Singleton design pattern allows Apex code to repeatedly reference an object instance in an optimal manner, whilst mitigating the impact of governor limits.
Strategy
The Strategy pattern (aka the policy pattern) attempts to solve the issue where you need to provide multiple solutions for the same problem so that one can be selected at runtime.
Problem
You need to provide a geographical-based search engine solution where the implementing code can choose the search provider at runtime.
Unified Modeling Language
Implementation
In order to implement a Strategy pattern in Apex, you need to define a family of algorithms, encapsulate each one, make them interchangeable, and selectable at runtime. It is implemented by:
- Creating an interface class (the Strategy) with methods that will be implemented by other classes
- Creating a class for each concrete Strategy that implements the methods defined in the Strategy interface
The following code demonstrates an implementation of the Strategy pattern for the underlying GeocodeService strategy and implementations.
So the specific Unified Modeling Language (UML) for this implementation is
where:
- Context => Geocoder
- operation() => getLatLong()
- Strategy => GeocodeService
- ConcreteStrategyA => GoogleMapsImpl
- ConcreteStrategyB => MapQuestImpl
Now that we have our core strategy interface and implementations, we need to make use of them. There are a couple of ways you might be tempted to do this, however, in order to decouple as much as possible, consider the following:
The Class
Calling googleMaps
Calling MapQuest
As you can see above, the calling code has a choice of implementations and the only change is the string passed to the Strategy interface.
Conclusion
The Strategy design pattern uses aggregation instead of inheritance, allowing better decoupling between the behavior and the class that uses the behavior. This allows the behavior to be changed without breaking the classes that use it, and the classes can switch between behaviors by changing the specific implementation used without requiring any significant code changes.
Decorator
The Decorator pattern attempts to solve the issue where you need temporary fields for processing (typically in Visualforce) but do not need to add these fields to the sObject.
Common uses for this pattern include:
- Selection Checkbox – a list of records that the user selects and applies behavior to; the selection checkbox is not saved
- Calculated fields – a complex read-only value that cannot be easily done in a formula field (e.g. calculation of a check digit)
- Proxy fields – a field, that when updated, converts to a different value on the record (e.g. temperature figures presented to the user in C, but stored as F)
This pattern is primarily for Visualforce use cases.
Problem
You need to obtain or display temporary information on a Visualforce page that is not needed beyond the context of the interaction.
Unified Modeling Language
Implementation
In order to implement the Decorator pattern in Apex, we need to be aware that this is not a true OO implementation, but the intent is to add behavior at runtime rather than via inheritance at compile time. It is implemented by:
- Understanding the existing sObject superclass – the actual sObject class.
- Understanding the existing concrete sObject – our underlying sObject (e.g. Account, Opportunity) – this class is not extensible in Apex
- Creating an "sObject Decorator" class that wraps the sObject with a pointer to the concrete sObject, with additional operations and properties extending the behavior of the concrete sObject at runtime
- Creating a Visualforce controller/class that acts as a client to the decorator
Note that this is not a "true" implementation of the OO Decorator pattern:
- The decorator class does not implement an interface to sObject (you can't do it)
- The sObject pointer in the class is public to simplify access to its behaviors (unless you want to recreate all the sObject methods in the class)
- It does have the intent of decorator, which is to add functionality at runtime
In our example scenario, we have a Weather sObject with City__c and TempInFahrenheit__c fields, and our Visualforce requirements are:
- the stored temperature in Fahrenheit should be displayed in Celsius
- when the user enters the temperature in Celsius it is stored as Fahrenheit
The Code - Decorated sObject Class
The above code demonstrates how the decorator class extends or wraps the Weather sObject with new functionality.
- Reference the weather sObject as a public property, but make it a private set. (This is different to the true decorator pattern, which makes this private and delegates behavior instead)
- Constructor – is passed in the weather object
- Property for tempInCelcius
- Getter – converts the temp from F to C and returns it (assuming we have another class to convert temperature)
- Setter – uses the value entered to convert from C to F and a side effect to store into the weather.tempInF. The last line makes sure that the value is stored back on the property.
The Code - Custom Controller
The above code demonstrates how the Weather Controller is the client
- Has a property that is a list of DecoratedWeather (our wrapper class)
- Has a getter that lazy initializes the list by selecting from the Weather__c table
- Private setter – only this class can set it
The Code - Visualforce Page
The above code demonstrates that the Visualforce page only needs to implement a little AJAX action support to rerender the page if the temperature changes. There is no real client side logic and no other fancy tricks, just a simple rerender. The getter and setter in the decorator class takes care of all the work.
Conclusion
So what we have is an example of how to extend sObject functionality in Apex with behavior at runtime, rather than through inheritance using a pseudo decorator pattern. Most of you will have seen this done with selection checkboxes, but it's something that can be applied with other use-cases as well.
Facade
The primary purpose of the Facade pattern is to provide a simpler interface to a complex class. This avoids repeated code and increases maintainability. Common uses include:
- Simplifying the execution of an Apex Web Service Proxy class
- Simplifying the execution of custom Apex classes with complex interfaces
- Providing a single interface to execute methods in multiple classes (e.g. multiple web service callouts)
This pattern effectively abstracts one or more complex classes, simplifying their execution for the rest of the application.
Problem
Often times, the execution of a particular class method requires multiple lines of code or is complex in nature. If the same code is repeated multiple times across different parts of the application, this degrades maintainability.
In Force.com, one of the biggest examples of this is the execution of Web Service callouts. The generated Apex code often times requires complex code, such as setting timeout values, setting the target host, as well as setup of the various inputs and parsing of the callout results.
The following demonstrates the issue of repeated code when executing Web Service callouts, especially if the business process requires the execution of multiple web services.
In the above example, multiple clients attempt to create an account and contact in a target system. This results in repeated code to setup two web service proxies, degrading maintainability.
Unified Modeling Language
Implementation
To implement a facade class, simply create another class that abstracts the implementation of the complex class(es). This facade class usually contains a simpler interface and in some cases, orchestrates the execution of multiple complex classes.
The purpose of the facade class is to simplify the execution of one or more complex classes with a simpler interface, increasing maintainability.
The following code sample shows a facade class that orchestrates the creation of an account and contact in an external system by calling multiple web services:
Facade Class
In the above facade class:
- The CreateCustomerExternal method wraps the execution of the two web service calls to create an account and contact in the external system. Repeated code, such as setting timeout values and endpoints, user IDs, timestamps, etc., is enscapsulated within this method rather than repeated elsewhere.
- The CreateCustomerResponse inner class contains the account and contact numbers generated by the external system.
The facade class is then called in other parts of the application as follows:
Conclusion
The Facade design pattern increases the maintainability of Apex code by simplifying the execution of one or complex classes with a facade class.
Composite
The Composite Design Pattern allows for representation of expressions, such as;
- 1 AND 2
- 1 OR (2 AND 3)
- (1 AND 2) OR ((3 OR 4) AND 5)
Problem
Our developer has a requirement to create a custom version of the Create/Edit List View screen. However, he is really struggling with how to represent an expression (outlined in red). The difficulty is due to the level of recursion involved.
Note: This discussion does not cover developing the actual screen or parsing the expression - it is limited to representing an expression in Apex.
Unified Modeling Language
Implementation
To implement the Composite Design Pattern, deploy the following interface and classes in your environment.
Expression Interface
Composite class
AndComposite Class
OrComposite class
Variable class
Examples/Usage
The examples below illustrate how to use the Expression interface.
Example: 1 AND 2
Example: 1 OR (2 AND 3)
Example: Method Chaining
Example: 1 OR (2 AND 3)
Conclusion
The Composite design pattern can be used to represent an expression in Apex regardless of expression complexity, whilst mitigating the impact of governor limits that can result from recursions.
Bulk State Transition
The Bulk State Transition design pattern is a general pattern used for performing bulk actions in Apex based on the change of state of one or more records.
Problem
Our developer has written a trigger to create an order upon the close of an opportunity, however, he has noted that:
- It always creates a new order every time the closed opportunity is updated
- When loading via Data Loader, not all closed opportunities result in an order
The Offending Code
The above code has more than a few issues. Namely;
- Occurs regardless of prior state - What if a closed opportunity was updated?
- No bulk handling - What if more than one opportunity was closed?
- Poor reusability - What if there are other places that we needed to create orders from an opportunity?
Our developer has rewritten the offending code, this time using a trigger and class.
Attempt 2: Trigger
Attempt 2: Class
While his second attempt improves reusability, there are still the issues:
- Occurs regardless of prior state
- No bulk handling
Our developer makes yet another attempt at addressing these concerns.
Attempt 3: Trigger
Attempt 3: Class
This last attempt is slightly better. At least it now handles state transition (i.e. only if the opportunity is closed). Also, it's now bulkified – separate list to keep track of orders, and a single bulk insert. However, the order class is highly coupled and is very hard to reuse outside of the trigger context. You can pass in null into the second argument, but that relies on you knowing the inner workings of the class.
Unified Modeling Language
In the Bulk State Transition design pattern:
- The trigger checks for eligible records that have changed state
- Calls a utility class to perform the work, only passing in the eligible records
- The utility class has a method that does the work in bulk
Implementation
We will implement the Bulk State Transition pattern utilizing two components:
- A trigger that which creates a filtered list of eligible records that have changed state
- A utility class that performs the logic for the list of eligible records in bulk
OpptyTrigger
Above, we have the trigger, OpptyTrigger:
- Checks for the type of trigger (IsBefore, IsAfter, etc.) and the DML type (IsInsert, IsUpdate, etc.).
- Instantiates a list, closedOpptyList, that keeps track of our eligible records.
- Loops through the trigger.new.
- If the opty is eligible (IsClosed), we add it to the list of eligible records. The important thing here is that for inserts, no check is made for the state change (since if the criteria is met, it's always treated as a state change) and if it's an update, we check the oldMap to obtain the prior record's value. Only if it's changed will we make it eligible.
- It is important that the trigger checks for eligibility only and has no logic.
OrderClass
Above we have the utility class, OrderClass:
- OrderClass is passed the list of eligible opportunities from our OpptyTrigger.
- We loop through the list of opportunities, creating a new Order object for each, and adding them to a list of orders.
- We then insert the list of Orders in one operation to ensure the operation is bulk safe.
Conclusion
With the above example, we've demonstrated implementing the Bulk State Transition design pattern as a means to perform bulk actions in Apex based on the change of state in one or more records.
Dennis Thong is a New York-based Director of Technical Architecture in Salesforce Services. An industry veteran with 13 years in building and architecting CRM solutions, he specializes in all things platform related, including integrating with, securing, and customizing Salesforce.com. If he's not working for a customer, he's trying to find the best coffee in the city.
Manu Erwin is a Cloud Computing professional with experience of implementing varied, full lifecycle CRM solutions. With over 5 years at Salesforce.com, 7 years working with the product, 6 years technical support management experience, and 11 years global consulting experience (Deloitte AU & US, Salesforce EMEA & APAC). Read more...
Eric Santiago has been involved with the Salesforce platform since 2005. As a Technical Architect with the Salesforce Services team, he has a broad expertise in all aspects of the platform particularly Apex/VisualForce development, Sites, and Portals. Eric loves adventure travel and has visited 28 countries on 5 continents. He is based in New York City.
Eric Broadaway Director Of Design Apex Tool Group
Source: https://developer.salesforce.com/wiki/apex_design_patterns
Posted by: clyburnnotle1973.blogspot.com
0 Response to "Eric Broadaway Director Of Design Apex Tool Group"
Post a Comment