While you may be familiar with the technical offerings of Salesforce.com, you might not know much about Salesforce.org, the social impact center at Salesforce. We build solutions that utilize the Salesforce Platform, working to empower organizations in the non-profit and education sectors to achieve their missions by unlocking the power of Salesforce CRM.
We’re also the largest Salesforce ISV (independent software vendor; though not quite as independent as we used to be!). We ship profiles, packages, and permission sets (not to mention lots and lots of Apex!). We strive to work on the cutting edge of the Salesforce platform, working with the latest releases of Lightning Web Components and Apex improvements available to us. Salesforce developers don’t showcase design patterns as much as developers in other ecosystems do, but we work with them all the time at Salesforce.org. I’d like to talk about one of my team’s favorite patterns today.
Who is this for?
If you hold a traditional computer science degree, you’re probably well-versed in design patterns and can skip ahead to the nitty-gritty technical details. However, Apex developers aren’t always traditional engineers; plenty of successful developers I know in the Salesforce ecosystem began their coding journey as Salesforce administrators and have picked up development skills in Apex; others have skipped the four-year degree entirely!
I’m also a non-traditional, self-taught developer. I got my technical bonafides through a development bootcamp. The course that I took alluded to the existence of design patterns, but our instructors told us that we wouldn’t have to worry about that until much later in our careers (and they were right!). I’m several years in as a developer now, and I can tell you that design patterns have a place in all modern coding languages, including Apex. (Examples will be provided in Apex, but the principles can apply to other OOP languages.)
So what are design patterns?
A design pattern is a reusable form of a solution to a design problem.
But what does that mean, exactly?
That’s a fancy way of saying that a pattern is a familiar way of solving well-known problems quickly. They can create shared understanding without digging into technical details, and their benefits and drawbacks can be found in numerous books and articles on patterns.
However, patterns can be difficult to maintain and can become more rigid than a simpler solution would have been. If you don’t recognize the pattern (and there are lots of patterns out there!), you can create unnecessary complexity and confusion amongst the team.
For example, if we’re all going out to eat and I say “Let’s go get pizza!,” that’s a lot faster and easier than saying “Let’s go get that wheat-based, cheese and red-sauce covered baked food! You know, the round one!²”
But if I say “Let’s go get penne alla vodka!”, not everyone is going to know what I’m talking about. Some of you might think we’re going out for drinks, others might think I don’t know good Italian food, and some of y’all might be excited that we’re going out for this super specific and tasty pasta dish. It would just be easier to say “let’s go for pasta”, and we’ll figure out the rest when we get there.
In the words of Erich Gamma, one of the authors of the original Design Patterns: Elements of Reusable Object-Oriented Software (aka the Gang of Four): “A design pattern should only be applied when the flexibility it affords is actually needed.” Before we consider using a design pattern, we should be sure that it fits our needs, and that everyone who will be working with it understands it well.
One pattern that I work with every day is the Singleton Pattern. It’s known as one of the foundational patterns, since it was defined in the original Design Patterns book. The Singleton is a creational pattern, which means that it’s used to define the creation of objects.
The Singleton pattern ensures that only one instance of a class exists and there is a global point of access to it.
Clear as mud right? Let’s break it down.
Singleton as a Railroad Switch
I like to think of the Singleton as a railroad switch.
A switch is what determines which direction a train will go when it reaches a possible alternative path. The normal path will allow the train to continue straight ahead. If the switch is pulled, then the train will take the other path. The tracks and the train only respond to what the switch tells them to do!
Let’s add apply this to a simple model:
Here we have a controller class, which in Apex would be called by an Aura or Lightning Web Component client. The controller calls the instance of the “First Class”, which is where our Singleton Pattern is used (we’ll see how to set that up down below!). Execution continues to a second class, and possibly further down the line until it finishes its job.
When the switch is pulled (Example B), our code flow will be diverted into the Stubbed class. Think of that alternate path in the photo above; the journey ends here where the Stub lets you arrive early to the station!
So what does this all have to do with testing?
We’ve covered the basic mechanics of the Singleton pattern, but why should we use it? Isn’t this just making our code more verbose and confusing? And what does all of this have to do with testing anyway?!
As Erich tells us, we should only apply patterns when we really need them, not just because some writer on the internet tells you to use it.
In the case of testing, here are some problems we may encounter:
- Our classes and their dependencies can get very complex, and we don’t want to do end-to-end testing for every class, especially controllers.
- We can’t always test at specific dates or times. What about bugs that happen only on the last day of the month, or 11:59PM GMT?
- We can’t (or don’t want to) create specific data, such as custom settings, objects, or permissions.
How do we solve these problems with this pattern?
Stub it out!
The Singleton pattern allows us to stub out the data we’re expecting, and test one method at a time (as a good test should). We can return “data” from downstream methods that we haven’t actually inserted, or specific dates and times.
For those of you intimately familiar with Apex development, this all might seem eerily similar to the Stub API — and it is! However, this is a fully customizable solution that allows you to stub out everything that you want without worrying about platform limitations.
Building a Switch
So first off, there’s a lot of code coming your way! If you’re not a coder, no worries! We’ll keep our railroad switch example in mind, and I’ll show you where the payoff is at the end. With that, let’s look at some code and get to stubbing it out!
This is a class that returns the current date and time as a single piece of data. We apply the Singleton to the class in order to stub it out easily, and get any date we want using the now() method. Let’s see how that happens:
- To start, we apply the virtual modifier to the class, which allows us to extend the class and override methods.
- Create a private instance variable that’ll be visible to tests only. This is what holds that current instance in memory.
- This is the railroad switch! Create a public method to get the instance. If no instance is provided, then we continue on straight with our normal path. If another instance has been created (which could also be this one, the code that’s being executed doesn’t know or care!), then use that instead.
- Protect the constructor so we can subclass it for tests, but not access it directly during normal runtime (only through the getInstance method).
- Finally — override any methods we want, and stub out the data that we’re expecting.
Think back to our data model — this is where the Apex code flow starts. Here we get the instance of our DateTimeProvider, which will tell us which direction we’re going when the code runs. Again, we’re forced to stay on track with the use of the getInstance method rather than creating a new instance of the class because the DateTimeProvider’s constructor isn’t public.
One scenario where we often need to run extra tests is during a leap year! This method will simply use the now() method to determine if it’s a leap year, and will print out a different message depending on if it is a leap year.
This is where we set up our switch, or stub. We create a new private subclass for the DateTimeProvider instance directly in the test class. This extends the same capabilities as the DateTimeProvider, and also has a now() method. However, we can pass into our now() method whatever date we want! This will allow us to stub out the date that we’re expecting, without us having to wait a whole year to get a different test result.
Now the tracks have been laid out, and we’re ready to get this train moving. We have two test methods to test both scenarios: in one, we’re expecting it’ll be a leap year, and in the other we’re expecting that it won’t be.
For our first test, we don’t have to do anything because 2020 is a leap year! So we can continue on our straight path without pulling the switch*.
*Technical footnote — in practice, you’d want to stub out a set leap year regardless, even if you know that this year is a leap year. Next year (2021) won’t be, so you don’t want your tests to start failing on Jan 1.
In the second test, we’re going to use our stub, and throw the switch. We create a set date (a day in 2019), which we pass into our stub to tell it what day we want to use. When we call printDateTime(), the controller will encounter the already existing DateTimeProvider instance (our stub), and will use that alternative path during execution. If we were doing more with this method, you would also expect to set up some assertions based on our stubbed out data.
From our first test, we see that it is, in fact, a leap year, since 2020 is a leap year!
In our second test we used a date in 2019 as our version of “now”, so the printed message agrees that we shouldn’t expect any weirdness due to leap years.
There are plenty of other reasons to use the Singleton pattern (for instance, my team will sometimes combine it with the Factory pattern when we create new features in order to give our users even more flexibility!).
In this example, you could also provide lots of stubbed classes, and provide them in different combinations to test all of the different conditionals in your code. You can even overwrite the same instance in one test class, if you need to.
Hopefully this leaves you either feeling more confident about using design patterns in your own code, or excited to learn more about design patterns. If you’re a developer looking to learn more about what we’re working on (and take a peek at some of our open source code!), check out our Github repo here. (And if you’d like to learn more about working with us directly, we’re frequently hiring too!)