Design Patterns in Salesforce (Ep. 1) – What Are Design Patterns?

When Should You Learn About Design Patterns?

When you first start learning about software development, I’d recommend against beginning with design patterns. Why? If you start with design patterns, you might be misled and start thinking that all of your code must conform to a design pattern, which isn’t the case and makes the process of learning how to code even more complicated. You’ll end up confused and overwhelmed, and your code could end up overengineered and wonky.

Instead, I encourage you to start with the basic building blocks of code, and design a few applications without using any design patterns, and that can serve as a foundation for more advanced functions, such as design patterns, later on. After you’ve mastered the basics of coding, and experienced a handful of difficult development situations, you’ll be ready to go back and learn about design patterns, and use them to solve tricky and difficult problems or situations in the code you develop.

Also, I recommend you learn more about design principles before getting into design patterns since those principles guide the design patterns. Design patterns will make much more sense once you’ve got a handle on the underlying design principles. To learn more about design principles, you can also check out the book Clean Code by Robert Martin, a fantastic resource for any budding code writer.

What Are Design Patterns?

Once you’re comfortable with the basics of coding and design principles, it’s time for the third step: understanding design patterns! True to their name, design patterns are coding patterns that can help you fix tricky situations you’ll find yourself in while coding, but that’s just the start. Design patterns can also make your code more flexible and easier to read, and be more performant when you’re done writing it.

Suppose you wrote something, and it always takes 2-3 minutes to load. You might be able to use the Singleton pattern to only load something that is very time-consuming once, which will likely cut down on the page-load time. And that’s just one example. Design patterns use their patterns to fix practically any problem or mess you’ve got in your software, and certain design patterns can be prescribed for certain coding issues.

You can think of them as medicine for your code, such as a doctor prescribing either Advil, Tylenol, or Ibuprofin for your headache. Any three of those would work 90% of the time for your headache, and in the other 10%, you may need to try something else. It’s the same with design patterns; none of them is a guaranteed miracle fix for a coding issue, but they generally work, and a skilled developer can prescribe one for a development problem.

Which Design Patterns Should You Learn?

Make no bones about it: there are a lot of design patterns out there! I couldn’t possibly list them all. For now, though, we can narrow the field down to 23 particular design patterns that are best learned first, and they are widely used, too (and they’re well-regarded, too). They are described as the “gang of four” design patterns since they were designed by a quartet of people calling themselves the gang of four. They even wrote a book together on this topic titled Design Patterns: Elements of Reusable Object-Oriented Software. You can check it out to get plenty of in-depth information.

These 23 design patterns are sorted into three categories: behavioral design patterns, creational design patterns, and structural design patterns. These include design patterns that you’ve probably heard of before, such as the Singleton pattern or the Observer pattern. Remarkably, these design patterns are almost 30 years old, but are still in use today, proving just how well-designed and universal in usage they are.

Later in my series, we will review all 23 of those design patterns and how to implement them in your own code. We will also go over some basic areas of object-oriented programming, just in case you’re not familiar with that topic, along with inheritance, encapsulation, and polymorphism.

That’s all for now. I hope that in the future, you’ll master all 23 design patterns and put them to work in your own development tasks and see for yourself just how handy they can really be! Until next time!

Get Coding With The Force Merch!!

We now have a tee spring store setup so you can buy cool Coding With The Force merchandise! Please check it out! Every purchase goes to supporting the blog and YouTube channel.

Get Coding With The Force Merch Here!


Check Out More Coding With The Force Stuff!

If you liked this post make sure to follow us on all our social media outlets to stay as up to date as possible with everything!

Youtube
Patreon
Github
Facebook
Twitter
Instagram


Salesforce Development Books I Recommend

Advanced Apex Programming
Salesforce Lightning Platform Enterprise Architecture
Mastering Salesforce DevOps
Apex Design Patterns Book

Good Non-SF Specific Development Books:

Clean Code
Clean Architecture
Design Patterns: Elements of Reusable Object-Oriented Software Book

SoC and the Apex Common Library Tutorial Series Part 12: The Builder Pattern

What is the Builder Pattern?

The Builder Pattern is a Creational Design Pattern that allows you to construct a complex object one step at a time. Think about the construction of a car or your house or maybe something less complicated, like the construction of a desktop computer. When you’re creating a new desktop computer you have to make a ton of selections to build the computer. You have to get the right cpu, motherboard, etc. Instead of passing all that selection information into a class that constructed the computer, it’d be a lot nicer to build it step by step. Let’s check out some examples:

Non-Builder Pattern Computer Building Class Example:

public class ComputerBuilderController(){
    public ComputerCreator createMidTierComputer(){
        return new ComputerCreator(midTierGraphicsCard, midTierCPU, midTierMotherboard, 
        midTierFan, null, null).getComputer();
    }

    public ComputerCreator createTopTierComputer(){
        return new ComputerCreator(topTierGraphicsCard, topTierCPU, topTierMotherboard, 
        topTierFan, topTierNetworkCard, null).getComputer();
    }
}

public class ComputerCreator{
    private CPU compCPU;
    private GPU compGPU;
    private MotherBoard compMotherBoard;
    private Fan compFan;
    private NetworkCard compNetworkCard;
    private Speakers compSpeakers;

    //This could go on for forever and you might have 300 different constructors with 
    //different variations of computer parts... This could become
    //an absolutely enormous class.
    public ComputerCreator(GraphicsCard selectedGraphicsCard, CPU selectedCPU, MotherBoard 
          selectedMotherboard, Fan selectedFan, NetworkCard selectedNetworkCard, Speakers 
          selectedSpeakers){
        setComputer(selectedGraphicsCard, selectedCPU, selectedMotherboard, selectedFan, 
                    selectedNetworkCard, selectedSpeakers);
    }

    //Because of how this is setup, we're setting everything for the computer, even if we're 
    //just setting the computer parts to null
    private void setComputer(GraphicsCard selectedGraphicsCard, CPU selectedCPU, MotherBoard 
            selectedMotherboard, Fan selectedFan, NetworkCard selectedNetworkCard, Speakers 
            selectedSpeakers){
                    this.compGPU= selectedGraphicsCard;
                    this.compCPU = selectedCPU;
                    this.compMotherBoard = selectedMotherboard; 
                    this.compFan= selectedFan; 
                    this.compNetworkCard = selectedNetworkCard; 
                    this.compSpeakers = selectedSpeakers;   
    }

    public ComputerCreator getComputer(){
        return this;
    }
}

You can see in the above example, this setup is not exactly ideal, nor does it lend itself to easy code changes. If you go with the single constructor approach and just allow developers to pass in nulls to the constructor, every time you need to add another option for the computers your code might build, you’ll have to update every piece of code that calls the ComputerCreator class because the constructor will change. Alternatively if you go with new constructor variations for each new option you could end up with hundreds of constructors over time… also not great at all. That can be extremely confusing and difficult to upkeep. So let’s look at how to leverage the builder pattern to achieve the same thing.

Builder Pattern Computer Building Class Example:

public class ComputerBuilderController(){
       
    public ComputerCreator createMidTierComputer(){
        return new ComputerCreator().
                   setCPU(midTierCPU).
                   setGPU(midTierGPU).
                   setMotherBoard(midTierMotherBoard).
                   setFan(midTierFan);
    }

    public void createTopTierComputer(){
        return new ComputerCreator().
                   setCPU(topTierCPU).
                   setGPU(topTierGPU).
                   setMotherBoard(topTierMotherBoard).
                   setFan(topTierFan).
                   setNetworkCard(topTierNetworkCard);
    }
}

public class ComputerCreator{
    private CPU compCPU;
    private GPU compGPU;
    private MotherBoard compMotherBoard;
    private Fan compFan;
    private NetworkCard compNetworkCard;
    private Speakers compSpeakers;
    
    public ComputerCreator setCPU(CPU selectedCPU){
        this.compCPU = selectedCPU;
        return this;
    }

    public ComputerCreator setGPU(GPU selectedGPU){
        this.compGPU = selectedGPU;
        return this;
    }

    public ComputerCreator setMotherBoard(MotherBoard selectedMotherBoard){
        this.compMotherBoard = selectedMotherBoard;
        return this;
    }

    public ComputerCreator setFan(Fan selectedFan){
        this.compFan = selectedFan;
        return this;
    }

    public ComputerCreator setNetworkCard(NetworkCard selectedNetworkCard){
        this.compNetworkCard = selectedNetworkCard;
        return this;
    }

    public ComputerCreator setSpeakers(Speaker selectedSpeakers){
        this.compSpeakers= selectedSpeakers;
        return this;
    }
}

You can see in the above example that using the builder pattern here gives us an enormous amount of flexibility. We no longer need to pass null values into a constructor or build a bajillion constructor variations, we only need to call the methods to set each piece of the computer should we need to set them. You can see we now only worry about setting values for things we actually need to set for our computer. Additionally, you can add new options for computer parts to set in the ComputerCreator class easily and it won’t affect that code that has already been written. For instance if I created a setWebcam method it would be no big deal. My createMidTierComputer and createTopTierComputer methods would not be impacted in any way and continue to function just fine. Builder Pattern FTW!


Why is it Useful?

Take the computer example above, without the builder pattern you get one of two things. You either get an enormous constructor you send all your computer parts to (that you will likely pass a ton of nulls to) or you have a ton of constructors to represent different computer variations… either choice is not a great choice. Complex objects typically have potentially hundreds of optional choices you can make, you need something more robust to select those options.

The builder pattern allows you to select those options piece by piece if you want them. Take for instance the computer example again. Desktop computers do not need things like network cards or speakers or a webcam to function. That being said, many people building a computer may want them for one reason or another to make their specific computer useful for them. Instead making constructor variations for every combination of those items, why not just use the builder pattern to add them as needed? It makes the code a whole lot easier to deal with and easier to extend in the future.


Where does it fit into Separation of Concerns?

Builder classes are typically service classes of some sort, maybe you create some super elaborate Opportunities in your org. You might have an Opportunity_Builder_Service or something along those lines. It can help in a lot of areas to reduce your code in the long term and to increase your codes flexibility for allowing new options for the object you are building, and I think we all know (if you’ve been doing this long enough), businesses like to add and subtract things from the services they create on a whim.


Where is it used in the Apex Common Library?

This design pattern is leveraged heavily by the fflib_QueryFactory class in the Apex Common Library. It allows us to build complex SOQL queries by building them step by step.


Example Code

The fflib_QueryFactory class is an example of a class designed using the builder pattern.

The Case_Selector class I’ve created has several examples of how it looks when you call and utilize a class leveraging the builder pattern.


Next Section

Part 13: The Selector Layer