💃 Design Patterns for Salesforce🕺

Take command of your code

Good morning, Salesforce Nerds! Today is a good day!

You know we love a good design pattern! 😍 

And today we get to talk about another fav of ours!

I’m gonna keep it real, though. This one can bend your brain a bit and be tough to grasp for beginners. 😬 

Regardless of your level, I encourage you to read on and find out a bit more about a little thing called the Command Pattern.

TABLE OF CONTENTS

QUICK REMINDER

Design Patterns

A design pattern is a reusable solution to a common software design problem.

These patterns are generalized templates that developers can apply to resolve issues they commonly encounter when designing software. 💪 

Here’s how they help dev’s:

✔️ Structured Solutions

✔️ Shared Vocabulary

✔️ Promote Reusability

✔️ Encourage Best Practices

✔️ Accelerate Development

Now, let’s dig into another pattern I’ve used in the wild! 🤠 

TAKING COMMAND

Command Pattern

First, the official definition: 📚️ 

A design pattern that turns a request into a stand-alone object that contains all information about the request. This transformation lets you pass requests as a method arguments, delay or queue a request’s execution, and support undoable operations.

GoF

This type of pattern falls under the Behavioral Patterns.

Let’s check out some of the advantages this pattern gives us …

📦️ Encapsulation of Actions: Commands encapsulate actions and parameters into objects, making it easier to parameterize clients with different requests in Salesforce processes.

🥨 Flexibility in Queuing and Logging: Commands can be queued for execution, facilitating asynchronous handling and enhanced logging of operations for audit trails in Salesforce applications.

🔙 Undo Operations: It supports undo operations by implementing an undo method, which can be crucial in Salesforce applications for reverting changes or transactions.

⛓️ Decoupling Sender and Receiver: It decouples the object invoking an operation (command sender) from the object that performs it (command receiver), promoting loose coupling and easier extensibility in Salesforce codebases.

🏗️ Support for Composite Commands: Composite commands can be created by nesting command objects, allowing complex operations to be built from simple ones, which is beneficial in complex Salesforce workflows and processes.

LET’S SEE AN EXAMPLE

Simple Problem

Imagine a situation where you have a custom object that you want to move along in a series of stages or statuses.

Only let’s imagine we’re building this from scratch. 🤙 

We have a custom object named Application__c and this object contains a handful of different date fields.

Each represent the date something important with the application happened.

When a date field is populated, we want update a Status__c field to a corresponding status. 😎 

We also want to be able to roll back to a previous status if a date field is cleared - like if it was filled out by accident or something.

Application entity

Now, there are a number of ways to get this done.

Something like this might work …

public class DoTheStatusThing {
        Application__c app;

        public DoTheStatusThing(Application__c app) {
            this.app = app;
        }

        public void execute() {
            if (
                this.app.Application_Date__c != null && 
                this.app.Processing_Date__c == null && 
                this.app.Approval_Date__c == null && 
                this.app.Funded_Date__c == null && 
                this.app.Closed_Date__c == null
                ) {
                    this.app.Status__c = 'Application Created';
            } else if (
                this.app.Application_Date__c != null && 
                this.app.Processing_Date__c == null && 
                this.app.Approval_Date__c == null && 
                this.app.Funded_Date__c == null && 
                this.app.Closed_Date__c == null
                ) {
                    this.app.Status__c = 'Application Processing';
            } else if (
                // So on ...
            ) {
                // Move app to next status
            }
        }
    }

I’ll be honest though. This code sucks. We can absolutely optimize this so it executes faster and is cleaner to maintain.

Read on for more! 👇️ 

 

SHOW ME THE CODE

The Solution

Okay, let’s see how we can command pattern-ize this requirement.

Step 1 - Create an interface

public interface ICommand {
    void execute();
    void undo();
}

Step 2 - Create your concrete implementations

public class ApplicationCreated implements ICommand {
    private List<Application__c> apps = new List<Application__c>();

    public ApplicationCreated(Application__c app) {
        if(app.Application_Date__c != null) {
            this.apps.add(app);
        }
    }

    public void execute() {
        for(Application__c app :this.apps) {
            app.Status__c = 'Application Created';
        }
    }

    public void undo() {
        for(Application__c app :this.apps) {
            app.Status__c = 'Incomplete';
        }
    }
}
public class ApplicationProccessing implements ICommand {
    private List<Application__c> apps = new List<Application__c>();

    public ApplicationProccessing(Application__c app) {
        if(app.Processing_Date__c != null) {
            this.apps.add(app);
        }
    }

    public void execute() {
        for(Application__c app :this.apps) {
            app.Status__c = 'Application Processing';
        }
    }

    public void undo() {
        for(Application__c app :this.apps) {
            app.Status__c = 'Application Created';
        }
    }
}
public class ApplicationApproved implements ICommand {
    private List<Application__c> apps = new List<Application__c>();

    public ApplicationApproved(Application__c app) {
        if(app.Approval_Date__c != null) {
            this.apps.add(app);
        }
    }

    public void execute() {
        for(Application__c app :this.apps) {
            app.Status__c = 'Application Approved';
        }
    }

    public void undo() {
        for(Application__c app :this.apps) {
            app.Status__c = 'Application Processing';
        }
    }
}

You get the idea … Create as many of these as you need. We’ll stop here for brevity.

Notice each execute method moves the Status__c field through the “pipeline” and the undo method moves it back it’s previous status.

Step 3 - Create a Macro concretion (this is optional, but it’s sexy so I always do it)

public class MacroCommand implements ICommand {
    private List<ICommand> commands;

    public MacroCommand(List<ICommand> commands) {
        this.commands = commands;
    }

    public void execute() {
        for(ICommand cmd :this.commands) {
            cmd.execute();
        }
    }

    public void undo() {
        for(ICommand cmd :this.commands) {
            cmd.undo();
        }
    }
}

Notice this class takes a list of ICommand instances, iterates over them to execute or undo them all! 🔥 

Step 4 - Construct and execute the macro from your client:

List<ICommand> commands = new List<ICommand> {
    new MilestoneCommand.ApplicationCreated(app),
    new MilestoneCommand.ApplicationProccessing(app),
    new MilestoneCommand.ApplicationApproved(app),
    new MilestoneCommand.ApplicationFunded(app),
    new MilestoneCommand.ApplicationClosed(app)
};

MilestoneCommand.MacroCommand macro = new MilestoneCommand.MacroCommand(commands);

macro.execute();

WRAPPING IT UP

Takeaway

There you have it.

An elegant, maintainable way to encapsulate commands into an object and execute them all in a single invocation. 💯 

I’ve used this pattern many times in my Salesforce career for similar use cases.

If this is something that peaks your interest I highly recommend watching this video!

The delivery is spot on!

Happy coding!

SOUL FOOD

Today’s Principle

"Theories are patterns without value. What counts is action.”

Constantin Brancusi

and now....Salesforce Memes

What did you think about today's newsletter?

Login or Subscribe to participate in polls.