Wednesday, December 15, 2021

What is a Flow in Salesforce?

 In Salesforce, a flow is an application that automates complex business processes. Simply put, it collects data and then does something with that data.

Flow Builder is the declarative interface used to build individual flows. Flow Builder can be used to build code-like logic without using a programming language.

Flows fall into five categories:

  • Screen Flows:
  • These are flows that have a UI element and require input from users. These types of flows are either launched as an action or embedded as an element on a Lightning page.
  • Schedule-Triggered Flows:
  • These autolaunched flows launch at a specified time and frequency for each record in a batch, and they run in the background.
  • Autolaunched Flows:
  • Run automated tasks with this flow type. Autolaunched flows can be invoked from process builder, from within an Apex class, from a set schedule, from record changes, or from platform events.
  • Record-Triggered Flows:
  • These autolaunched flows run in the background when a record is created, updated, or deleted.
  • Platform Event-Triggered Flows:
  • When a platform event message is received, these autolaunched flows runs in the background.

Check out this example of a schedule-triggered flow, pulled from a well-known Salesforce group:

Screen Shot 2020-08-14 at 10.40.54 AM.png


When/why should I use a flow?

To answer this question, we really need to look into what automation is needed. In most cases, the type of automation to use for a specific process is determined by evaluating where the data for the processes originates from and where it needs to go. Consider whether what you need to accomplish is best handled by a flow, workflow field update, or a process.

  • Flows are able to create, edit, and delete any record passed into the flow. Records do not have to be related in order to pass data in a flow. Flows can also be scheduled to run on a set interval with a collection of records.
  • The workflow field update can write data to the same record that invoked the workflow rule, or to the master record of a master-detail relationship on the record that invoked the rule. Workflow rules are not able to create, edit, or delete records.
  • Processes, created in the Process Builder, can write data to the same record that invoked the process, or to records related by either lookup or master-detail relationships. Processes can also create records, but they cannot delete them. Processes also cannot query records unrelated to the invoking record.


When should I not use a flow?

Generally, you should not use a flow in the following situations:

  • There is complicated logic involved that is better managed with Apex code. An example of this is the flow shown in the Overview section. The logic in this flow is so complicated that it makes debugging a pain, plus it makes documenting and managing the flow difficult.
  • Your Salesforce edition limits how many flows you can create. Essentials and Professional editions of have a limit of five processes (per process type) and flows (per flow type) in each organization. For most logic in these editions, it is easier to use a process.


How do I create a flow in Salesforce?

  • Open Flow Builder. From Setup, enter “Flows” into the Quick Find box, select Flows, and then click New Flow.
  • Select the Flow Type, then click Create.
  • Drag the elements you want to use onto the canvas. Each element represents an action that the flow can execute. Examples of such actions include reading or writing Salesforce data, displaying information and collecting data from flow users, executing business logic, or manipulating data.
  • Connect the elements to determine the order in which they’re executed at run time. Don’t forget to connect the Start element to another element!
  • Save your flow.

After you build a flow, make sure that it’s working correctly by thoroughly testing it. Once you’ve tested it, activate the flow. You’re now ready to distribute the flow to users.

Pro tip: Flows can be executed in several ways, depending on who the flow is designed for. Internal users, external users, or systems can run a flow, or a flow can be deployed for another organization. Just remember, no matter how you execute it…you’ve got to go with the flow.


Flows vs. Apex

  • Apex code requires a developer and Sandbox to deploy, meaning it can only really be built in organizations using a Professional or above edition of Salesforce. Flows can be built in all editions, as a Sandbox is not required for deployment.
  • Apex is not available in Essentials, and some Apex features are limited in Professional. Organizations with Enterprise and above have no Apex limitations, but flow features are not limited based on the edition.
  • Apex code requires constant development and discipline to maintain. Flows require less work to keep up-to-date.
  • Flows can be built by admins, while Apex code is typically built by developers only.
  • Apex code is considered a tool of last resort. Flows are simpler and should be used before Apex code.
  • If the logic is too complex, Apex code should be used. There is unlimited potential with Apex; flow capabilities are catching up, but they are still inferior to Apex.
  • Renewal generation, OLI creation, and other pieces of automation that were traditionally built as Apex code can now be built as flows, preserving code space for projects that require Apex.

Apex code should be used in the following scenarios:

  • You’re dealing with complex Salesforce automation that requires multiple steps and actions where a flow will become cumbersome.
  • You need custom-built integrations with other systems (such as a connection to a SQL database that requires bi-directional syncs).
  • ERP integrations are involved.
  • You need to be able to control the batch size of your automation in order to prevent limit errors.
  • You need to present an error message in the UI if the automation fails or doesn’t find what it’s looking for.


Flows vs. Processes

  • Processes are more user-friendly as far setup and management goes.
  • Flows allow you to add screens where users can enter data. Processes do not have this capability.
  • Flows can be invoked, started by users, triggered by a record change, or scheduled to run on their own at a custom time and frequency. A process, however, runs automatically (either immediately or scheduled) when criteria is met. It can also be invoked by another process created in the Process Builder.
  • Both flows and process can include scheduled actions.
  • Flows can be paused by users, but processes run when the criteria is met and cannot be paused.
  • Flows and processes both contribute to CPU limits and other automation limits in Salesforce.
  • Process actions are executed in the order in which they appear in the process definition, but flows can have different and more complex orders of operations.
  • Flows can be built to cycle through multiple unrelated and related objects. Processes, however, are limited to the base object (opportunities, for example) and related objects (accounts).
  • Flows can be designed to run either before or after a record has been saved to the database, but processes can only trigger after a record has been saved.
  • Flows can be designed to trigger upon creation, update, or deletion of a record. Processes can trigger only for creation or updates to a record.
  • Flows can be test-run and run in debug mode on the flow canvas, including in a rollback mode, which allows you to test your automation without making changes to your data.

The following actions are only available for processes:

  • Quip actions
  • Send survey invitation


Flows vs. Workflow Rules

  • Flows are available in all Salesforce editions, including Essentials. Workflow rules (WFRs) are not available in Essentials or Professional editions.
  • WFRs are not actively being updated by Salesforce (but you can still use them for the time being). Flows are constantly being updated with new features and capabilities in each Salesforce release.
  • There are limitations with how many WFRs can be active at once, but they typically do not contribute to CPU limits unless the WFR triggers a process or flow through one of its updates (such as a field update).
  • Both flows and WFRs can have scheduled actions, but WFRs are limited to 1000 triggers per hour.
  • WFRs can only make one decision, but you can call other flows and Apex code with a flow.
  • WFRs are limited to just a few actions: creating a task record, sending an email, updating a field, or sending an outbound message. Flows can do all of these actions and many more.


Testing Flows

To test a flow, click the Debug button on the canvas, input your variables, and click Run. Then run through the flow to make sure it works properly. This process is especially helpful with screen flows.

Note that as of the Winter 2021 Salesforce release, a beta feature called Debug on Canvas is available. This feature makes flow debugging easier by visually demonstrating the path your flow will take when it runs. It also shows query limits of the flow in the debug details. Additionally, debugging now offers a two more options than it did previously: Run flow as another user, and Run flow in rollback mode.


Where is the Flow Builder in Salesforce?

To find the Flow Builder in Salesforce (Lightning) navigate to Setup > Process Tools > Flows.

Setup.png
Screen Shot 2020-08-10 at 11.03.20 AM.png


What are the different Flow Types in Salesforce?

Auto-Launched Flows with No Flow Trigger

These flows don’t require user interaction, and they don’t support screens, local actions, choices, or choice sets. The available distribution methods available are:

  • Flow actions
  • Lightning pages
  • Lightning community pages
  • Custom Aura components
  • Custom Lightning web components
  • Custom buttons or custom links
  • Web tabs
  • Direct flow URLs
  • Visualforce pages
  • Lightning out
  • Embedded service deployments

Auto-Launched Flows with a Schedule Trigger

These flows only run from a schedule that the user sets. They don’t support user interaction, screens, local actions, choices, or choice sets. The available distribution methods are:

  • Processes
  • Custom Apex classes
  • REST API
  • Web tabs
  • Custom buttons or custom links
  • Visualforce pages

Screen Flows

Screen flows require user interaction because they include screens, local actions, steps, choices, or dynamic choices. Screen flows don’t support Pause elements. A schedule-triggered flow only runs at the scheduled time and frequency.

Auto-Launched Flows with a Record Trigger

These flows are designed to quickly make simple changes to a record when the record is created, updated, or deleted. They can also be configured to make those changes either before or after the record has been saved to the database. In a before-save flow, the supported elements are AssignmentDecisionGet Records, and Loop. After-save flows have access to all flow capabilities, but they cannot launch sub flows.

User Provisioning Flow

User provisioning flows provision users for third-party services. You could use this flow type to customize the user provisioning configuration for a connected app, linking Salesforce users with their Google Apps accounts. A user provisioning flow can only be implemented by associating it with a connected app when running the User Provisioning Wizard.

Field Service Mobile Flow

These flows require user interaction because they have one or more screens.

Field Service Embedded Flow

These flows require user interaction because they have one or more screens.

Contact Request Flow

These flows require user interaction because they have one or more screens. Use one of the following Experience Builder components to add this flow:

  • Contact Request Button & Flow (launch the flow in a popup window)
  • Flow (embed the flow directly on the page)

For more on Flow Types in Salesforce, check out the official documentation.


What is a flow interview in Salesforce?

While a flow is an application built by your administrator that asks you for inputs and does something in Salesforce based on those inputs, a flow interview is a running instance of a flow.

For example, a flow could provide a call script for customer support calls using the information you provided to create a case. What the flow does with the information you provide is entirely up to your administrator.

When you run a flow interview, whether through a link, button, or tab, you’re running a single instance of a flow. If the terminology is confusing, consider the difference between a record and an object. You create an account record, which is a single instance of the account object that your administrator customized.

Read more about flow interviews in Salesforce’s documentation.


How do you call a flow from a button in Lightning?

Since Winter 2018, Salesforce has offered an easy way to trigger a flow using a Quick Action button in Lightning.

Note: Only screen flows or field service mobile flows may be launched from a Quick Action button.

  1. Create a custom action for the record in question by navigating to Object Manager > (Object Name) > Buttons, Actions and Links.
  2. Select “Flow” as the type for the custom action.
  3. Configure the custom action to reference the flow, then name it.
  4. Add the custom action to the page layout of your choice.


Common Mistakes When Designing Flows

We see a lot of flows here at Kicksaw, and we build even more of them. Here are some common and avoidable mistakes we’ve identified:

  • Using the wrong field or variable
  • Not checking for null values
  • Too many SOQL queries
  • Object & field-level security for running user
  • No access to running flows


Using PRIORVALUE of a record in a Lightning flow

Salesforce allows you to add access to the PRIORVALUE of a record in a Lightning flow, in a way that is similar to the way the Process Builder worked. This brings flows to the next level.

After selecting the object, Salesforce will automatically create a record variable ($Record__Prior) for it. You will then be able to refer to it anywhere in the flow.


Using the Aura.Action Attribute Type

 An Aura.Action is a reference to an action in the framework. If a child component has an Aura.Action attribute, a parent component can pass in an action handler when it instantiates the child component in its markup. This pattern is a shortcut to pass a controller action from a parent component to a child component that it contains, and is used for on* handlers, such as onclick.

Warning

Although Aura.Action works for passing an action handler to a child component, we recommend registering an event in the child component and firing the event in the child’s controller instead. Then, handle the event in the parent component. The event approach requires a few extra steps in creating or choosing an event and firing it but events are the standard way to communicate between components.

Aura.Action shouldn’t be used for other use cases. Here are some known limitations of Aura.Action.

  • Don’t use cmp.set() in JavaScript code to reset an attribute of type="Aura.Action" after it’s previously been set. Doing so generates an error.
  • Don’t use $A.enqueueAction() in the child component to enqueue the action passed to the Aura.Action attribute.
Unable to set value for key 'c.passedAction'. Value provider does not implement 'set(key, value)'. : false

Example

This example demonstrates how to pass an action handler from a parent component to a child component.

Here’s the child component with the Aura.Action attribute. The onclick handler for the button uses the value of the onclick attribute, which has type of Aura.Action.

<!-- child.cmp -->
<aura:component>
    <aura:attribute name="onclick" type="Aura.Action"/>

    <p>Child component with Aura.Action attribute</p>
    <lightning:button label="Execute the passed action" onclick="{!v.onclick}"/>
</aura:component>

Here’s the parent component that contains the child component in its markup.

<!-- parent.cmp -->
<aura:component>
    <p>Parent component passes handler action to c:child</p>
    <c:child onclick="{!c.parentAction}"/>
</aura:component>

When you click the button in c:child, the parentAction action in the controller of c:parent is executed.

Instead of an Aura.Action attribute, you could use <aura:registerEvent> to register an onclick event in the child component. You’d have to define the event and create an action in the child’s controller to fire the event. This event-based approach requires a few extra steps but it’s more in line with standard practices for communicating between components.

Apex Design Patterns

 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

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

1
2
3
4
5
6
trigger AccountTrigger on Account (before insert, before update) {
    for(Account record : Trigger.new){
        AccountFooRecordType rt = new AccountFooRecordType();
        ....
    }
}


The Class

1
2
3
4
5
6
7
8
9
public class AccountFooRecordType {
    public String id {get;private set;}
    public AccountFooRecordType(){
        // This could breach the governor limits on describes
        // if a trigger is executed in bulk
        id = Account.sObjectType.getDescribe()
            .getRecordTypeInfosByName().get('Foo').getRecordTypeId();
    }
}

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

Singleton.png

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

1
2
3
4
5
6
7
trigger AccountTrigger on Account (before insert, before update) {
    for(Account record : Trigger.new){
        // Instantiate the record type using the singleton class
        AccountFooRecordType rt = AccountFooRecordType.getInstance();
        ....
    }
}

The Singleton Class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class AccountFooRecordType {
    // private static variable referencing the class
    private static AccountFooRecordType instance = null;
    public String id {get;private set;} // the id of the record type
 
    // The constructor is private and initializes the id of the record type
    private AccountFooRecordType(){
        id = Account.sObjectType.getDescribe()
            .getRecordTypeInfosByName().get('Foo').getRecordTypeId();
    }
    // a static method that returns the instance of the record type
    public static AccountFooRecordType getInstance(){
        // lazy load the record type - only initialize if it doesn't already exist
        if(instance == null) instance = new AccountFooRecordType();
        return instance;
    }
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class AccountFooRecordType {
    // a static, final variable that initializes an instance of the class
    // as it's final, it will only be initialized once
    private static final AccountFooRecordType instance = new AccountFooRecordType();
    public String id {get;private set;}
    private AccountFooRecordType(){
        id = Account.sObjectType.getDescribe()
            .getRecordTypeInfosByName().get('Foo').getRecordTypeId();
    }
    public static AccountFooRecordType getInstance(){
        // eager load of the class
        return instance;
    }
}

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.

1
2
geocode('moscone center')
//=> 37.7845935,-122.3994262

Unified Modeling Language

Apex Design Patterns Strategy.png

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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public interface GeocodeService{
    List<Double> getLatLong(String address);
}
 
public class GoogleMapsImpl implements GeocodeService{
    public List<Double> getLatLong(String address){
        // Web service callout
        return new List<Double>{0,0};
    }
}
 
public class MapQuestImpl implements GeocodeService{
    public List<Double> getLatLong(String address){
        // Web service callout
        return new List<Double>{1,1};
    }
}

So the specific Unified Modeling Language (UML) for this implementation is

Apex Design Patterns Strategy Geocoder Example.png

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class Geocoder {
  public class NameException extends Exception{}
 
  public static final Map<String,GeocodeService> strategies;
 
  static{
      // Retrieve comma delimited list of strategies from a Custom Setting
      GlobalVariable__c gv = GlobalVariable__c.getInstance('strategies');
 
      // Populate a List Collection of strategy names e.g., googleMaps, mapQuest etc
      List<String> strategyNames = new List<String>();
      if(gv != null && gv.value__c != null) strategyNames = gv.value__c.split(',');
 
      // Populate a map of strategy names to concrete implementations
      // using Type.forName for each strategy string
      strategies = new Map<String,GeocodeService>();
      for(String name : strategyNames){
          try{strategies.put(name, (GeocodeService)Type.forName(name + 'impl').newInstance());}
          catch(Exception e){continue;} //skip bad name silently
      }
  }
 
  private GeocodeService strategy;
 
  public Geocoder(String name){
      if(!strategies.containsKey(name)) throw new NameException(name);
      strategy = strategies.get(name);
  }
 
  public List<Double> getLatLong(String address){
      return strategy.getLatLong(address);
  }
}

Calling googleMaps

1
2
3
Geocoder geocoder = new Geocoder('googlemaps');
System.debug(geocoder.getLatLong('moscone center'));
//=> 13:56:36.029 (29225000)|USER_DEBUG|[29]|DEBUG|(0.0, 0.0)

Calling MapQuest

1
2
3
Geocoder geocoder = new Geocoder('MapQuest');
System.debug(geocoder.getLatLong('moscone center'));
//=> 13:56:36.129 (29225000)|USER_DEBUG|[29]|DEBUG|(0.0, 0.0)

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

Apex Design Patterns Decorator.png

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

Decorator Weather Example.png

The Code - Decorated sObject Class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class DecoratedWeather {
 
  public Weather__c weather { getprivate set; }
 
  public DecoratedWeather (Weather__c weather) {
            this.weather = weather; 
  }
 
  public Decimal tempInCelcius {
    get {
      if (weather != null && tempInCelcius == null )
        tempInCelcius = new Temperature().FtoC(weather.TempInFahrenheit__c);
                     
      return tempInCelcius; 
    }  
    set {
      if (weather != null && value != null )
        weather.TempInFahrenheit__cnew Temperature().CtoF(value);
 
            tempInCelcius = value;
    }
  }
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Weather_Controller {
 
  public List<DecoratedWeather> listOfWeather {
 
    get {
      if (listOfWeather == null) {
        listOfWeather = new List<DecoratedWeather>();
 
        for (Weather__c weather : [select name, temperature__c from Weather__c]) {       
            listOfWeather.add(new DecoratedWeather(weather));
        }
      }
      return listOfWeather;
    }
 
    private set;
  }
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<apex:page controller="weather_controller">
  <!-- VF page to render the weather records with Ajax that only rerenders
     the page on change of the temperature
  -->
  <apex:form id="theForm">
    <apex:pageBlock id="pageBlock">
      <apex:pageBlockTable value="{!listOfWeather}" var="weather">
        <apex:column value="{!weather.weather.name}"/>
        <apex:column headerValue="Temperature (C)">
          <apex:actionRegion >
            <apex:inputText value="{!weather.tempInCelcius}">
              <apex:actionSupport event="onchange"
                      reRender="pageBlock"/>
            </apex:inputText>
          </apex:actionRegion>
        </apex:column>
        <apex:column headerValue="Temperature (F)"
              value="{!weather.weather.Temperature__c}"
              id="tempInF"/>
      </apex:pageBlockTable>
    </apex:pageBlock>
  </apex:form>
</apex: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.

Facade2.png

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

Facade.png

1
2
3
4
5
6
7
8
public FooFacade {
  public String LotsOfFoo() {
    Foo1 f1 = new Foo1();
    Foo2 f2 = new Foo2();
   
    return f1.Foo1() + f2.Foo2();
  }
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class CreateCustomerFacade {
 
    // Inner class representing the response from the web service
    public class CreateCustomerResponse {
        public String accountNumber; 
        public String contactNumber;
 
        public CreateCustomerResponse(String accountNumber, String contactNumber) {
            this.accountNumber = accountNumber;
            this.contactNumber = contactNumber;
        }
    }
 
    // Method to call the two external web services
    public String CreateCustomerExternal(String Name, String LastName, String FirstName) {
        // Setup the web service proxy class to create an account in the target system
        CreateAccount_Service.CreateAccount stubCA = new CreateAccount_Service.CreateAccount();
        CreateAccount_Service.Inputs inputCA = new CreateAccount_Service.Inputs();
 
        // Set timeout and endpoint
      stubCA.timeout_x = 60000;
      stubCA.endpoint_x = 'https://www.foo.com/ca';
       
        // Default other values
        inputCA.userid = Userinfo.getUserName();
        inputCA.timestamp = datetime.now();
        inputCA.Name = name.toUpperCase();
     
        // Call the web service and retrieve the account number
        String accountNumber = inputCA.CreateAccount(input);
 
        /* REPEAT FOR CONTACT - Code not shown */
   
        // Generate and return a response
        return new CreateCustomerResponse (accountNumber, contactNumber);              
    }
}

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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class FooController{
 
    public Account account { get; set; }
    public Contact contact { get; set; }
    
    public void CallCreateCustomerWS() {
        CreateCustomerFacade ca = new CreateCustomerFacade();
 
        CreateCustomerFacade.CreateCustomerResponse resp = ca.CreateCustomerExternal(account.name, contact.LastName, contact.FirstName);
 
  account.accountNumber = resp.accountNumber;
  contact.contactNumber__c = resp.contactNumber;
    }
}

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.

ExpressionScreen.jpg

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

Composite uml.jpg

Implementation

To implement the Composite Design Pattern, deploy the following interface and classes in your environment.

Expression Interface

1
2
3
4
5
public interface Expression {
    Expression add(Expression expr);
    Expression set(String name, Boolean value);
    Boolean evaluate();
}

Composite class

1
2
3
4
5
6
7
8
9
10
11
12
13
public abstract class Composite implements Expression{
    public List<Expression> children {getprivate set;}
    public Composite(){ this.children = new List<Expression>(); }
    public Expression add(Expression expr){
        children.add(expr); return this;
    }
    public Expression set(String name, Boolean value){
        for(Expression expr : children) expr.set(name,value);
        return this;
    }
    public abstract Boolean evaluate();
    public Boolean hasChildren{getreturn !children.isEmpty(); }}
}

AndComposite Class

1
2
3
4
5
6
public class AndComposite extends Composite{
    public override Boolean evaluate(){
        for(Expression expr : children) if(!expr.evaluate()) return false;
        return true;
    }
}

OrComposite class

1
2
3
4
5
6
public class OrComposite extends Composite{
    public override Boolean evaluate(){
        for(Expression expr : children) if(expr.evaluate()) return true;
        return false;
    }
}

Variable class

1
2
3
4
5
6
7
8
9
10
11
12
public class Variable implements Expression{
    public String  name  {get;private set;}
    public Boolean value {get;private set;}
    public Variable(String name){ this.name = name; }
    public Expression add(Expression expr){ return this; }
    public Expression set(String name, Boolean value){
        if(this.name != null && this.name.equalsIgnoreCase(name))
            this.value = value;
        return this;
    }
    public Boolean evaluate(){ return value; }
}

Examples/Usage

The examples below illustrate how to use the Expression interface.

Example: 1 AND 2

1
2
3
4
//1 AND 2
Expression expr = new AndComposite();
expr.add(new Variable('1'));
expr.add(new Variable('2'));

Example: 1 OR (2 AND 3)

1
2
3
4
5
6
7
//1 OR (2 AND 3)
Expression expr = new OrComposite();
expr.add(new Variable('1'));
Expression expr2 = new AndComposite();
expr.add(expr2);
expr2.add(new Variable('2'));
expr2.add(new Variable('3'));

Example: Method Chaining

1
2
3
4
5
6
7
8
//no need for expr2 var if using "method chaining"
//last line of add method: return this;
Expression expr = (new OrComposite())
    .add(new Variable('1'))
    .add((new AndComposite())
        .add(new Variable('2'))
        .add(new Variable('3'))
    );

Example: 1 OR (2 AND 3)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//1 OR (2 AND 3)
Expression expr = (new OrComposite())
    .add(new Variable('1'))
    .add((new AndComposite())
        .add(new Variable('2'))
        .add(new Variable('3'))
    )
    .set('1',false)
    .set('2',true)
    .set('3',false);
 
System.debug(expr.evaluate());
//FALSE OR (TRUE AND FALSE) => FALSE
 
expr.set('3',true);
 
System.debug(expr.evaluate());
//FALSE OR (TRUE AND TRUE) => TRUE

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

1
2
3
4
5
6
7
8
trigger OpptyTrigger on Opportunity (after insert, after update) {
 
  if (trigger.new[0].isClosed) {
    Order__c order new Order__c();
    
    insert order
  }
}

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

1
2
3
4
5
trigger OpptyTrigger on Opportunity (after insert, after update) {
 
  new OrderClass().CreateOrder(trigger.new);
 
}

Attempt 2: Class

1
2
3
4
5
6
7
8
9
10
11
12
13
public class OrderClass {
   
  public void CreateOrder(List<Opportunity> opptyList) {
    for (Opportunity oppty : opptyList) {
      if (oppty.isClosed) {
        Order__c order new Order__c();
        ...
        insert order;
      }
    }
     
  }
}

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

1
2
3
4
5
6
7
trigger OpptyTrigger on Opportunity (before insert, before update) { 
  if (trigger.isInsert) {
    new OrderClass().CreateOrder(trigger.newMap, null);
  else
    new OrderClass().CreateOrder(trigger.newMap, trigger.oldMap);
  }
}

Attempt 3: Class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class OrderClass {
   
  public void CreateOrder(Map<Opportunity> opptyMapNew
              Map<Opportunity> opptyMapOld) {
    List<Order__c> orderList = new List<Order__c>();
    for (Opportunity oppty : opptyMapNew.values()) {
      if (oppty.isClosed && (opptyMapOld == null ||
          !opptyMapOld.get(oppty.id).isClosed)) {
        Order__c order new Order__c();
        ...
        orderList.add(order);
      }
    }
    insert orderList ;
  }
}

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

BulkTransition uml.jpg

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
trigger OpptyTrigger on Opportunity (after insert, after update) {
  if (trigger.isAfter && (trigger.isInsert || trigger.isUpdate)) {
    List<Opportunity> closedOpptyList = new List<Opportunity>();
     
    //loop through opportunities and check if closed
    for (Opportunity oppty : trigger.new) {
      /* Note: for insert, check current state,
          for update, check current state and prior state */
      if (oppty.isClosed && (trigger.isInsert ||
          (trigger.isUpdate &&
          !trigger.oldMap.get(oppty.id).isClosed)))
        closedOpptyList.add(oppty);
    }
     
    //send eligible records to OrderClass
    if (!closedOpptyList.isEmpty())
      new OrderClass().CreateOrderFromOpptys(closedOpptyList); 
  }
}

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

1
2
3
4
5
6
7
8
9
10
11
public class OrderClass {
  public void CreateOrdersFromOpptys(List<Opportunity> opptyList) {
    List<Order__c> orderList = new List<Order__c>();
    for (Opportunity oppty : opptyList) {
      Order__c order new Order__c();
      //more logic here
      orderList.add(order);
    }
    insert orderList ;
  }
}

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.