Patterns in Apex: Dependency Injection, Strategy, and Decorator

by Aidan Harding - April 19, 2018
Patterns in Apex: Dependency Injection, Strategy, and Decorator

When you start out in Salesforce development, there seems to be little need for software design patterns. Perhaps because development starts with little triggers doing this and that in a few lines of code. But, as soon as the requirements, codebase, and team-size grow, then the advantages of patterns and other software engineering practices kick in.In this article, we’re going to look at three patterns (which overlap) and help us to solve a problem that many Apex coders will be familiar with.

The Problem

Suppose you’re writing a function that receives a list of Contacts and needs to return them in reverse order of LastName. When you need to sort, you immediately reach for the sort()  method of the standard List  class. But it’s not quite that simple. sort()  works by requiring the elements in the list to implement the Comparable interface (plus accepting some built-in types that don’t implement Comparable but only sort in a non-configurable way).

So, the standard approach is to write a wrapper class that contains a Contact and implements Comparable in the way you need e.g.

public class ContactWrapper implements Comparable {
    
    public Contact aContact {public get; private set;}

    public ContactWrapper(Contact aContact) {
        this.aContact = aContact;
    }

    public Integer compareTo(Object other) {
        return -aContact.LastName.compareTo(((ContactWrapper)other).aContact.LastName);
    }
}

Which is fine, but if you want to sort a list of Contacts, then there’s a lot of marshalling to do before you get to call sort() :

public static List<Contact> sortContactDescendingLastName(List<Contact> contacts) {
    List<ContactWrapper> wrappers = new List<ContactWrapper>();
    for(Contact c : contacts) {
        wrappers.add(new ContactWrapper(c));
    }
    wrappers.sort();
    List<Contact> returnVal = new List<Contact>();
    for(ContactWrapper cw : wrappers) {
        returnVal.add(cw.aContact);
    }
    return returnVal;
}

Make a list of wrappers, put all the Contacts into wrappers, sort it, make a list of Contacts, copy all the contents of the wrappers into that final list. Who has time for all that?

The Solution

The alternative is to write our own sorting implementation which is not configured by properties of the elements in the list. Instead, it’s configured by an object that we pass in at the time of construction. This is dependency injection. The sorting algorithm depends on being given a method to compare elements, and we’re going to supply (inject) that dependency when we create an instance of the sorter. Get this right, and we’ll have two great benefits:

  1. No need to marshall all our sObjects into a wrapper just to sort them
  2. No need to implement Comparable in our own classes (along with possible configuration to allow sorting by different criteria) just to make them sortable. Importantly, if I wrote a class last year, and today I decide that I need to sort lists of that object, I don’t need to modify that class to make it sortable

The first piece of the puzzle is to define an interface for comparing two objects. Like Comparable , but not tied to the objects we’re comparing:

public interface Comparator { 
  // Compares its two arguments for order. Returns a negative integer, 
  // zero, or a positive integer as the first argument is less than, 
  // equal to, or greater than the second.
  Integer compare(Object o1, Object o2);
}

Then, we can write a sorting class which uses an instance of Comparator  to do the comparisons:

public class QuickSort {

	private Comparator comparator;

	public QuickSort(Comparator comparator) {
		this.comparator = comparator;
	}

	// Sorts in-place, and returns the original array
	public List<Object> quicksort(List<Object> toSort) {
		quicksort(toSort, 0, toSort.size()-1);
		return toSort;
	}

	private void quicksort(List<Object> toSort, Integer low, Integer high) {
		if(low < high) {
			Integer newPivot = partition(toSort, low, high);
			quicksort(toSort, low, newPivot);
			quicksort(toSort, newPivot + 1, high);
		}
	}

	private Integer partition(List<Object> toSort, Integer low, Integer high) {
		Object pivotVal = toSort[low];
		Integer upwards = low - 1;
		Integer downwards = high + 1;

		while(true) {
			while(comparator.compare(toSort[++upwards], pivotVal) < 0);

			while(comparator.compare(toSort[--downwards], pivotVal) > 0);

			if(upwards >= downwards) {
				return downwards;
			}

			Object tmp = toSort[upwards];
			toSort[upwards] = toSort[downwards];
			toSort[downwards] = tmp;
		}
		return null;
	}
}

We won’t get into the details of the quicksort sorting algorithm, but we will note that in lines 29 and 31 we are using the Comparator  to compare the elements. The Quicksort  class doesn’t entirely perform a sorting algorithm, it is missing the part where it knows exactly how to compare two elements in the list. That detail is provided at runtime by passing in a instance of Comparator. This is a use of the Strategy Pattern and, as we noted before, dependency injection.

So, let’s build a Comparator  for our earlier example:

public class ContactLastNameDescendingComparator implements Comparator {

    public Integer compare(Object o1, Object o2) {
        return -((Contact)o1).LastName.compareTo(((Contact)o2).LastName);
    }

}

Pretty simple, so what does the actual sort look like?

public static List<Contact> quicksortContactDescendingLastName(List<Contact> contacts) {
    QuickSort sorter = new QuickSort(new ContactLastNameDescendingComparator());
    return (List<Contact>)sorter.quicksort(contacts);
}

Wow, so much better!

Going Further

But, we can go further. What about classes that already implement Comparable ? Piece of cake:

public class ComparableComparator implements Comparator {

    public Integer compare(Object o1, Object o2) {
        return ((Comparable) o1).compareTo((Comparable) o2);
    }
}

What if I wanted to reverse the ordering? Do I have to write a new Comparator  for each combination of sorting criteria that I’ll ever want? Or maybe one MegaComparator  with lots of parameters and switches? No… we can keep things clean by using the Decorator Pattern. This allows us to modify the behaviour of a Comparator  by wrapping it inside another one (decorating it). For example, we can write a reversing comparator like this:

public class ReverseComparator implements Comparator {

    private Comparator comparator;

    public ReverseComparator(Comparator comparator) {
        this.comparator = comparator;
    }

    public Integer compare(Object o1, Object o2) {
        return -comparator.compare(o1, o2);
    }
}

And then we can sort our Contacts in ascending order of LastName by putting the two Comparators together:

public static List<Contact> quicksortContactAscendingLastName(List<Contact> contacts) {
    QuickSort sorter = new QuickSort(new ReverseComparator(new ContactLastNameDescendingComparator()));
    return (List<Contact>)sorter.quicksort(contacts);
}

If you’re a Java programmer, you’ll be familiar (and probably a bit frustrated by) the decorator pattern due to its extensive use in the IO libraries (Reader , BufferedReader , etc.).

If you’ve been paying very close attention, you’ll notice that ReverseComparator  is using dependency injection and the strategy pattern on its way to being part of the decorator pattern.

Final Thoughts

This all seems like fun, but do you use it every day? I don’t write the utility classes with these patterns every day, but I do use code written with these patterns every day. When you’re trying to pull out general solutions that you can re-use everywhere, and pondering how to make them configurable for scenarios that you can’t yet imagine, these patterns give you some great ways to build in all the flexibility that you need. So, if you’re a senior engineer building some of the tracks for your colleagues to run on, this gives you a great way of doing it.

For example, we have utility classes to convert sObjects to/from JSON using metadata to specify the JSON structure. How can you deal with external systems that have a million different ways of storing dates? Or when they decide to store some numbers in strings? By writing the utility classes with the strategy pattern, and allowing the developer in a specific situation to fill in those details themselves. The utility class can deal with how to fetch Contact.Account.Name through those object relations, and it can deal with building nested JSON objects. You can concentrate on whether or not there should be a ‘T’ or not between the date and the time on this particular integration.

As always, happy to hear feedback on Twitter @AidanHarding or email aidan@nebulaconsulting.co.uk.

Related Content


Get In Touch

Whatever the size and sector of your business, we can help you to succeed throughout the customer journey, designing, creating and looking after the right CRM solution for your organisation