SoC and the Apex Common Library Tutorial Series Part 10: The Domain Layer

What is the Domain Layer?

The Domain Layer is, “An object model of the domain that incorporates both behavior and data”. – Martin Fowler

In most coding languages you need to connect to the database, query for the data and then you create wrapper classes to represent each underlying table in your database(s) to allow you to define how that particular table (object) should behave. Salesforce, however, already does a lot of this for you, for instance there is no need to connect to a Database, declarative behavior for you tables (objects) are already represented and your tables (objects) already have wrapper classes pre-defined for them (Ex: Contact cont = new Contact()).

However the logic represented in a trigger is an exception to this rule. Apex triggers represent a unique scenario on the Salesforce platform, they are necessary for complex logic, but inherently they do not abide by any object oriented principles. You can’t create public methods in them, you can’t unit test them, you can’t re-use logic placed directly in a trigger anywhere else in your system, etc. Which is a massive detriment we need to overcome. That’s where the domain layer comes in to play.

The Domain Layer will allow you on an object by object basis have an object oriented approach to centralize your logic. Basically, logic specific to a single object will be located in one place and only one place by using the domain layer. This ensures your logic specific to a single object isn’t split into a ton of different places across your org.


When to make a new Domain Layer Class

Basically, at the very least, anytime you need to make a trigger on an object you should implement a Domain Class. However this is a bit generalized, sometimes you don’t actually need a trigger on an object, but you have object specific behavior that should be implemented in a Domain class. For instance, if you have an object that doesn’t need a trigger, but it has a very specific way it should have its tasks created, you should probably create a Domain Layer class for that object and put that task creation behavior there.

A domain layer class is essentially a mixture of a trigger handler class and a class that represents object specific behaviors.


Where should you leverage the domain layer in your code?

You should only ever call to the domain layer code from service class methods or from other domain class methods. Controller, Batch Classes, etc should never call out to the domain directly.


Domain Class Naming Conventions

Class Names – Domain classes should be named as the plural of whatever object you are creating a domain layer for. For instance if you were creating a domain layer class for the Case object, the class would be declared as follows: public inherited sharing class Cases. This indicates that the class should be bulkified and handles multiple records, not a single object record.

Class Constructor – The constructor of these classes should always accept a list of records. This list of records will be leveraged by all of the methods within the domain class. This will be further explained below.

Method Names – Method names for database transaction should use the onTransactionName naming convention (Example: onAfterInsert). If the method is not related to a database transaction it should descriptive to indicate what domain logic is being executed within it (Example: determineCaseStatus).

Parameter Names and Types – You do not typically need to pass anything into your domain layer methods. They should primarily operate on the list of records passed in the constructor in the majority of situations. However some behavior based (non-trigger invoked) methods may need other domain objects and/or units of work passed to them. This will be further explained in the sections below.


Domain Layer Best Practices

Trasnaction Management

In the event you are actually performing DML operations in your Domain class, you should either create a Unit of Work or have one passed into the method doing the DML to appropriately manage your transaction. In the event you are not wanting to leverage the unit of work pattern you should make sure to at the very least set your System.Savepoint savePoint = Database.setSavePoint(); prior to doing your DML statement and use a try catch block to rollback if the DML fails.


Implementing the Domain Layer

To find out how to implement the Domain Layer using Apex Common, continue reading here: Implementing the Domain Layer with the Apex Common Library. If you’re not interested in utilizing the Apex Common library for this layer you can implement really any trigger framework and the core of the domain layer will be covered.

Libraries That Could Be Used for the Domain Layer

Apex Common (Contains a framework for all layers)

Apex Trigger Actions Framework

SFDC Trigger Framework

MyTriggers


Domain Layer Examples

Apex Common Examples (Suggested)

Case Object Domain Layer Example

Contact Object Domain Layer Example

SFDC Trigger Framework Example

Case Object Domain Layer Example


Next Section

Part 11: Implementing the Domain Layer with the Apex Common Library

SoC and the Apex Common Library Tutorial Series Part 11: Implementing The Domain Layer with the Apex Common Library

The template for every Domain Class you create

Every Domain layer class you create for an object should at minimum have the following logic in it for it to work as expected.

//All domain classes should utilize inherited sharing so that the caller determines whether it //should operate in system context or not. The should
//also extend the fflib_SObjectDomain class
public inherited sharing class Cases extends fflib_SObjectDomain{
    
    //The constructor should always accept a list of the SObject type we're creating the 
    //domain class for
    //It should then pass this list to the fflib_SObjectDomain class's constructor which is 
    //what super(cases) does.
    //This sets the records value in the fflib_SObjectDomain class which is very important 
    public Cases(List<Case> cases){
        super(cases);
    }

    //The name of this inner class must always be Constructor to work appropriately. This acts 
    //as a way to use the concept of reflection when initializing
    //this class, despite the fact apex still does not support it.
    public class Constructor implements fflib_SObjectDomain.IConstructable {
        public fflib_SObjectDomain construct(List<SObject> sObjectList) {
            return new Cases(sObjectList);
        }
    }
}

To understand why the Constructor inner class is necessary in these classes check out the triggerHandler method in the fflib_SObjectDomain class here: fflib_SObjectDomain triggerHandler method


Trigger Implementations using the Apex Common Library’s Domain Layer

If you didn’t know already, triggers should ideally have no logic in them… ever. Thankfully this concept has also been built into the Apex Common Library. To call the Domain Layer class you have built for your object in your trigger, just do the following:

//Note that I like to use the _Trigger in my trigger names, this is just personal preference //as it makes it easier to discern it's a trigger
trigger NameOfDomainLayerClass_Trigger on YourObject (before insert, before update, after insert, after update)
{
    //This trigger handler method eventually calls the Construct inner class of your Domain 
    //class to construct a version of your class
    //and implement the logic in it
    fflib_SObjectDomain.triggerHandler(NameOfDomainLayerClass.class);
}

How to Access the Trigger variables in your Domain Class

Technically, you could leverage trigger.new, trigger.oldMap etc in your domain class… however you shouldn’t for two reasons. The first reason is you will likely (at some point) want to call some aspects of your Domain class from outside a trigger context. If your Domain relies on the trigger context to operate, that’s less than ideal. The second reason is you can’t mock the trigger context, so a ton of benefit of setting up these separation of concerns will be lost. Short story, never access trigger context variables directly in your domain class.

Now you might be wondering, “This Domain class is supposed to be able to run in trigger context… I need to access those variables!!”. No worries, you can still access them when you need them. If you’ve worked in SF long enough, with time you start to learn the only trigger context variables you need access to are trigger.new and trigger.oldMap. The rest typically really shouldn’t be used. Trust me… you don’t need them.

So how do you actually get access to trigger.oldMap and trigger.new? Well that requires us to take a closer look at the triggerHandler method in the fflib_SObjectDomain class that our actual triggers call (example just above this section).

Basically when our trigger calls that triggerHandler method, it eventually runs the code below (source code here):

 if(isInsert) domainObject = domainConstructor.construct(newRecords);
 else if(isUpdate) domainObject = domainConstructor.construct(newRecords);
 else if(isDelete) domainObject = domainConstructor.construct(oldRecordsMap.values());
 else if(isUndelete) domainObject = domainConstructor.construct(newRecords);

The code above essentially passes trigger.new to the Records variable in the fflib_SObjectDomain class you Domain class extends when you are doing and insert, update or undelete operation; and it passes in trigger.oldMap.values to the Records variable if you are doing a delete operation.

Ok that’s cool, but how do you access trigger.oldMap when you need it?? Well, the only time you need trigger.oldMap are in update operations, so that’s the only time it’s accessible. When you setup your onBeforeUpdate or onAfterUpdate methods in your Domain class you’ll set them up like what you see below:

public override void onBeforeUpdate(Map<Id, SObject> existingRecords){
    //existingRecords is trigger.oldMap
} 

In trigger context when onBeforeUpdate gets called, trigger.oldMap is passed in to the existingRecords variable and you’re free to use it as you please.

There you have it! That’s it! Simpler than you maybe thought… maybe, lol.


The fflib_SObject Domain Class methods Cheat Sheet

While there are many other accessible methods in the fflib_SObjectDomain class below are the methods most commonly utilized in implementations.

1) onApplyDefaults() This method is called in the handleBeforeInsert method and exists so that you can apply default logic that is applicable to all new records that are created in the system.
2) onValidate() This method is called in the handleAfterInsert method and exists so that you can apply validation logic to your inserted records before commiting them to the database.
3) onValidate(Map<Id, SObject> existingRecords) This method is called in the handleAfterUpdate method and exists so that you can apply validation logic to your updated records before commiting them to the database.
4) onBeforeInsert() This method is called in the handleBeforeInsert method and exists so that you can override it to place logic that should occur during a before insert action in a trigger.
5) onBeforeUpdate(Map<Id, SObject>) This method is called in the handleBeforeUpdate method and exists so that you can override it to place logic that should occur during a before update action in a trigger.
6) onBeforeDelete() This method is called in the handleBeforeDelete method and exists so that you can override it to place logic that should occur during a before delete action in a trigger.
7) onAfterInsert() This method is called in the handleAfterInsert method and exists so that you can override it to place logic that should occur during an after insert action in a trigger.
8) onAfterUpdate(Map<Id, SObject>) This method is called in the handleAfterUpdate method and exists so that you can override it to place logic that should occur during an after update action in a trigger.
9) onAfterDelete() This method is called in the handleAfterDelete method and exists so that you can override it to place logic that should occur during an after delete action in a trigger.
10) onAfterUndelete() This method is called in the handleAfterUndelete method and exists so that you can override it to place logic that should occur during an after undelete action in a trigger.
11) handleBeforeInsert() This method is called in the triggerHandler method when a beforeInsert is happening in the trigger. By default it calls the onApplyDefaults method and the onBeforeInsert method but it can be overridden and implemented in a different way if desired.
12) handleBeforeUpdate(Map<Id, SObject>) This method is called in the triggerHandler method when a beforeUpdate is happening in the trigger. By default it calls the onBeforeUpdate method but it can be overridden and implemented in a different way if desired.
13) handleBeforeDelete() This method is called in the triggerHandler method when a beforeDelete is happening in the trigger. By default it calls the onBeforeDelete method but it can be overridden and implemented in a different way if desired.
14) handleAfterInsert() This method is called in the triggerHandler method when an afterInsert is happening in the trigger. By default it calls the onValidate and onAfterInsert method but it can be overridden and implemented in a different way if desired.
15) handleAfterUpdate() This method is called in the triggerHandler method when an afterUpdate is happening in the trigger. By default it calls the onValidate and onAfterUpdate method but it can be overridden and implemented in a different way if desired.
16) handleAfterDelete() This method is called in the triggerHandler method when an afterDelete is happening in the trigger. By default it calls the onAfterDelete method but it can be overridden and implemented in a different way if desired.
17) handleAfterUndelete() This method is called in the triggerHandler method when an afterUndelete is happening in the trigger. By default it calls the onUndelete method but it can be overridden and implemented in a different way if desired.
18) getChangedRecords(Set<String> fieldNames) This method will return a list of records that have had their fields changed (the fields specificied in the method parameter passed in).
19) getChangedRecords(Set<Schema.SObjectField> fieldTokens) This method will return a list of records that have had their fields changed (the fields specificied in the method parameter passed in). I would suggest using this method over the one above. Strongly typed field names are a better choice in my opinion so the system knows your code depends on that field.


The Configuration Inner Class for fflib_SObjectDomain (Setting trigger state and trigger security)

Inside the fflib_SObjectDomain class you’ll find an inner class called Configuration. This inner class allows you to enable and disable Trigger State as well as enable and disable CRUD security in your trigger. By default trigger state is disabled and CRUD security is enabled.

Trigger State

The trigger state parameter allows you to choose to use the same instance of your Domain class between the before and after portion of the trigger. It needs to be used carefully as this could cause trigger recursion if not implemented properly.

How to turn trigger state on and off using the Configuration inner class:

//Turn on
Configuration.enableTriggerState();
//Turn off
Configuration.disableTriggerState();

Enforcing CRUD

The enforcing trigger CRUD (Create, Read, Update, Delete) ensures that a users has the appropriate object CRUD permissions before performing any actual DML actions. By default in the fflib_SObjectDomain class this is enforced. Ideally you should leave this as enforced unless you have a really excellent business reason to not enforce it.

How to turn CRUD enforcement on and off using the Configuration inner class:

//Enable CRUD
Configuration.enforceTriggerCRUDSecurity();
//Disable CRUD
Configuration.disableTriggerCRUDSecurity();

The Trigger Event Inner Class (Turning trigger events on and off)

Inside the fflib_SObjectDomain class is an inner class called TriggerEvent that allows you to turn on and off the various trigger events at will. By default all trigger events are turned on.

Example Code for shutting down and re-enabling a portion of a domain trigger

//Disables to before insert portion of the trigger
DomainClassName.getTriggerEvent(DomainClassName.class).disableBeforeInsert();
//Code to execute
//Enables the before insert portion of the trigger
DomainClassName.getTriggerEvent(DomainClassName.class).enableBeforeInsert();

The following is a list of trigger event methods a what they do:

1) TriggerEvent.enableBeforeInsert() This method enables the before insert portion of the trigger.

2) TriggerEvent.enableBeforeUpdate() This method enables the before update portion of the trigger.

3) TriggerEvent.enableBeforeDelete() This method enables the before delete portion of the trigger.

4) TriggerEvent.disableBeforeInsert() This method disables the before insert portion of the trigger.

5) TriggerEvent.disableBeforeUpdate() This method disables the before update portion of the trigger.

6) TriggerEvent.disableBeforeDelete() This method disables the before delete portion of the trigger.

7) TriggerEvent.enableAfterInsert() This method enables the after insert portion of the trigger.

8) TriggerEvent.enableAfterUpdate() This method enables the after update portion of the trigger.

9) TriggerEvent.enableAfterDelete() This method enables the after delete portion of the trigger.

10) TriggerEvent.enableAfterUndelete() This method enables the after undelete portion of the trigger.

11) TriggerEvent.disableAfterInsert() This method disables the after insert portion of the trigger.

12) TriggerEvent.disableAfterUpdate() This method disables the after update portion of the trigger.

13) TriggerEvent.disableAfterDelete() This method disables the after delete portion of the trigger.

14) TriggerEvent.disableAfterUndelete() This method disables the after undelete portion of the trigger.

15) TriggerEvent.enableAll() This method enables all portions of the trigger.

16) TriggerEvent.disableAll() This method disables all portions of the trigger.

17) TriggerEvent.enableAllBefore() This method enables all before portions of the trigger.

18) TriggerEvent.disableAllBefore() This method disables all before portions of the trigger.

19) TriggerEvent.enableAllAfter() This method enables all after portions of the trigger.

20) TriggerEvent.disableAllAfter() This method disables all after portions of the trigger.


Example Apex Common Implementation of a Domain Class

Cases Domain Layer Example

Contacts Domain Layer Example


Next Section

Part 12: The Builder Pattern

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

SoC and the Apex Common Library Tutorial Series Part 13: The Selector Layer

What is the Selector Layer

The Selector Layer is Salesforce is based off Martin Fowler’s Data Mapper Layer concept. It’s, “a layer of Mappers that moves data between objects and a database while keeping them independent of each other and the Mapper itself”.

In most tech stacks when you want to represent records in a database table you create classes in your code base to represent them to hold them in memory and prep them for transit to the actual database. These are what Martin references as “objects” in the above quote. Salesforce already creates these classes for you in the background to represent your Custom and Standard Objects. It’s why you can just inherently write Case cs = new Case(); in Apex and it creates a brand new Case record for you.

Since Salesforce already does that work for you, the Data Mapper Layer, just turns into the Selector Layer and within the Selector Layer we are basically just concerned with housing and performing queries for our respective objects. You will ideally call upon the Selector Layer every single time you need to make a query in Apex. The largest goal with this layer is to avoid having repetitive queries everywhere within the system and to have some overall consistency with your object queries (the fields always queried, limits, order by clause, etc).


When to make a new Selector Layer Class

Whenever you need to create queries on an object you’ve never done queries on before, you would create a new Selector Layer Class. So for instance if you needed to create some queries for the case object to use in your service or domain layer classes, you would create a Case Selector class. There should typically be one selector class per object you intend to query on.


Selector Layer Naming Conventions

Class Names – Your classes should ideally follow the naming conventions of the domain layer just with Selector appended to the end of them, unless you have common cross object queries then it’s a bit different.

Selector Class Naming Examples (Note that I prefer underscores in names, this is personal preference):

Accounts_Selector
Opportunities_Selector
OpportunityQuotes_Selector

Method Naming and Signatures – The names of the methods in a selector class should all start with the word “select”. They should also only return a list, map or QuerySelector and should only accept bulkified parameters (Sets, Lists, Maps, etc). A few good examples of method examples are below.

Selector Method Examples

public List<sObject> selectById(Set<Id> sObjectIds)
public List<sObject> selectByAccountId(Set<Id> accountIds)
public Database.QueryLocator selectByLastModifiedDate(Date dateToFilterOn)

Selector Layer Security

The Selector Layer classes should all ideally inherit their sharing from the classes calling them. So they should typically be declared as follows:

public inherited sharing class Account_Selector

If there are queries for your object that you absolutely must have run in system context (without sharing) you would want to elevate those permissions through the use of a private inner class like so:

public inherited sharing class Account_Selector 
{
    public List<Account> selectAccountsById(Set<Id> acctIds){
        return new Account_Selector_WithoutSharing().selectAccountsByIdElevated(acctIds);
    } 

    private without sharing Account_Selector_WithoutSharing{
        public List<Account> selectAccountsByIdElevated(Set<Id> acctIds){
            return [SELECT Id FROM Account WHERE Id IN : acctIds]; 
        }
    }
}

Implementing the Selector Layer

To find out how to implement the Selector Layer using Apex Commons, continue reading here: Implementing the Selector Layer with the Apex Common Library . If you’re not interested in utilizing the Apex Common library for this layer there are pretty sparing options out there that are pre-built, the only other option I’m aware of at this time is Query.apex. Outside of that, you could certainly roll your own selector layer, but it is no small feat if done right.

Libraries That Could Be Used for the Domain Layer

Apex Common (Contains a framework for all layers)

Query.apex


Selector Layer Examples

Apex Common Examples (Suggested)

Case Object Selector Example (Lots of comments)

Contact Object Selector Example

Task Object Selector Example

Non Apex Common Examples

Case Object Selector Simple Example


Next Section

Part 14: Implementing the Selector Layer with the Apex Common Library

SoC and the Apex Common Library Tutorial Series Part 14: Implementing the Selector Layer with the Apex Common Library

The Template for every Selector Class you create

Every Selector layer class you create should at least implement the following methods for it to work as anticipated.

//Selector layer classes should all use the inherited sharing keyword so that the caller //determines to context it operates in.
//It should also always extend the fflib_SObjectSelector so it can inherit that classes //methods and functionality.
public inherited sharing class Contact_Selector extends fflib_SObjectSelector
{
	public Contact_Selector(){
                /*This is calling the fflib_SObjectSelector classes constructor and setting 
                  the following booleans:
                  1) If the selector queries should use field sets
                  2) If you would like to enforce CRUD security
                  3) If you would like to enforce FLS
                  4) If you would like to sort selected fields
                */
		super(false, true, true, false);
	}

        //Add the base fields for the object that should just be used in absolutely every 
        //query done by this class
	public List<Schema.SObjectField> getSObjectFieldList(){
		return new List<Schema.SObjectField>{
				Contact.Id,
				Contact.Name,
				Contact.FirstName,
				Contact.LastName
		};
	}

        //Allows you to easily get the object type for the object being queried by this class
	public Schema.SObjectType getSObjectType(){
		return Contact.SObjectType;
	}

        //Allows you to create a query that selects records by a set of ids (basically adds 
        //the WHERE Id IN :ContactIds to the query)
	public List<Contact> selectById(Set<Id> contactIds){
		return (List<Contact>) selectSObjectsById(contactIds);
	}
}

The fflib_SObjectSelector Constructor Parameters and what each of them mean

When you create a Selector class that extends the fflib_SObjectSelector class you have the option to send some parameters to its constructor that determine how to the selector class functions. They are the following (in order of parameters passed to the constructor):

1) Would you like to allow your class to use field sets when building the initial query fields for your selector layer class? By default this parameter is set to false.

2) Would you like to enforce CRUD (Object level create, read, update, delete) security on your selector layer class? By default this parameter is set to true.

3) Would you like to enforce FLS (Field level security) on your selector layer class? By default this parameter is set to false.

4) Would you like your selected fields in your query to be sorted alphabetically when your query is created (this is literally just a sort call on a list of strings in the code)? By default this parameter is set to true.

If you would like to alter any of these settings for your selector class you can do the following:

public inherited sharing class Contact_Selector extends fflib_SObjectSelector
{
        //In our selector classes constructor we are calling the fflib_SObjectSelector using the super() call
        //and setting out parameters.
	public Contact_Selector(){
                //This is completely optional. If you like the defaults listed above you do not have to call the super class constructor at all.  
		super(false, true, true, false);
	}
}

Note that this is completely optional, if you like the default behavior listed above, just don’t bother calling the super method and overriding them!


How to set the default field selection for your Selector Class

One of the biggest benefits of the selector layer is selected field consistency in your queries. If 99% of the time you are querying for the subject field on your Case object, why not just query for it by default without ever thinking about it again right?? Well the getSObjectFieldList method that you implement in your Selector classes does just that. Here’s how to implement that method in your selector:

public List<Schema.SObjectField> getSObjectFieldList(){
        //Note that this is using concrete references to the fields, not dynamic soql (here at 
        //least). This is to ensure the system knows
        //your code is dependent on these fields so you don't accidentally delete them some 
        //day.
	return new List<Schema.SObjectField>{
                        //In this list, place every field you would like to be queried for by 
                        //default when creating a query
                        //with your selector class.
			Contact.Id,
			Contact.Name,
			Contact.FirstName,
			Contact.LastName
	};
}

If you choose to enable field sets to allow for default field selection for your selector class, you can implement the following method to select fields from the field set to be included in your queries:

public override List<Schema.FieldSet> getSObjectFieldSetList(){
    return new List<Schema.FieldSet>{SObjectType.Case.FieldSets.CaseFieldSetForSelector};
}

The major benefit of using the field sets for query fields is you can add new fields on the fly without adding extra code. This becomes super important if you’re building a managed package.


How to set your default OrderBy clause in your Selector Class

By default all Selector Layer Classes that extend the fflib_SObjectSelctor are ordered by the Name field (if the name field isn’t available on the queried object it defaults to CreatedDate). If that’s kewl with you, no need to override it, but if you’d prefer the default sort order for your select class be different then you just need to override the following method like so:

public override String getOrderBy(){
    return 'Subject';
}

If you wanted to order by multiple fields you would just do the following (basically just create a comma separated list in the form of a string):

public override String getOrderBy(){
    return 'Subject, Name, CustomField__c, CustomLookup__r.Name';
}

The fflib_QueryFactory class and Custom Queries

Chances are you’re gonna wanna query something that’s not immediately available via the fflib_SObjectSelect class, well lucky for you the fflib_QueryFactory class is here just for that! Here is an example of a custom query via the use of the fflib_QueryFactory class (a list of all available query factory methods are at the bottom of this wiki article).

//This allows us to select all new cases in the system using the QueryFactory in //fflib_SObjectSelector
public List<Case> selectNewCases(){
    return (List<Case>) Database.query(newQueryFactory().
    selectField(Case.Origin).
    setCondition('Status = \'New\'').
    setLimit(1000).
    toSOQL());
}

There are also tons of other methods that allow you to add offsets, subselects, set ordering and more (outlined in the method cheat sheet section).


How to Do Sub-Select Queries (Inner Queries)

There’s a kinda handy way to do sub-select queries by using the fflib_QueryFactory class. You can use it in your selector class’s methods as outlined below:

//Pretend this method exists in a Case_Selector class
public List<Case> innerQueryExample(){
    //Using this Case_Selectors newQueryFactory method that it inherits from the 
    //fflib_SObjectSelector class it extends
    fflib_QueryFactory caseQueryFactory = newQueryFactory();

    //Creating a new instance of our Task_Selector class and using the 
    //addQueryFactorySubselect method to add the task query as a 
    //inner query for the caseQueryFacorty
    fflib_QueryFactory taskSubSelectQuery = new 
    Task_Selector().addQueryFactorySubselect(caseQueryFactory);
  
    //Querying for our data and returning it.
    return (List<Case>) Database.query(caseQueryFactory.toSOQL());
}

How to do Aggregate Queries

There’s not really a built-in method in either the fflib_SObjectSelector or the QueryFactory class to deal with this. So you just deal with aggregate queries by building a method in your Selector Class in the following way:

public List<AggregateResult> selectAverageTacosPerTacoBell(){
    List<AggregateResult> tacoData = new List<AggregateResult>();
    for(AggregateResult result: [SELECT Id, AVG(Tacos_Sold__c) avgTacos FROM Taco_Bell__c 
        GROUP BY Taco_Type__c]){
        tacoData.add(result);
    }
    return tacoData;
}

The fflib_SObjectSelector Class methods Cheat Sheet

While there are many other methods within the fflib_SObjectSelector class below are the methods most commonly utilized in implementations.

1) getSObjectName()_ – Returns the name of the object that your select was built for.

2) selectSObjectsById(Set<Id> idSet) – Returns a query that selects all the records in your id set. It constructs a query based on the fields you declare in your selector class’s getSObjectFieldsList method and orders them by whatever is represented in the m_orderBy variable.

3) queryLocatorById(Set<Id> idSet) – This method is basically the same as the selectSObjectsById method except that it returns a query locator instead. This should be leveraged for batch classes that need query locators.

4) newQueryFactory – This method returns a new instance of the fflib_QueryFactory class and uses your selector classes fields listed in the getSObjectFieldsList method and orders them by whatever you set the default orderby to in your selector class.

5) addQueryFactorySubselect(fflib_QueryFactory parentQueryFactory) – This method basically just creates a subselect query (an inner query) for the “parentQueryFactory” and then returns the parent query with a subselect query that represents the query for your objects selector class (more info on how this method works in the sub-select query section in this wiki article).


The fflib_QueryFactory Class methods Cheat Sheet

While there are many other methods within the fflib_QueryFactory class below are the methods most commonly utilized in implementations.

1) assertIsAccessible() – This method checks to see if the running user can actually read to object this selector was built for.

2) setEnforceFLS(Boolean enforce) – This method determines whether or not to enforce field level security on the query you are running.

3) setSortSelectFields(Boolean doSort) – If you would like the list of fields selected to be selected in alphabetical order, you can use this method to make your selected fields be selected in alphabetical order.

4) selectField(Schema.SObjectField field) – Use this method to select a field for your query.

5) selectFields(Set fields) – Use this method to select multiple fields for your query at the same time.

6) selectFieldSet(Schema.FieldSet fieldSet) – Use this method to select fields for your query from a field set.

7) setCondition(String conditionExpression) – Use this method to set the conditions for your query (basically you are setting the WHERE clause in your query. Do NOT add the WHERE to the string you pass into to this method).

8) setLimit(Integer limitCount) – Sets a limit for your query.

9) setOffset(Integer offsetCount) – Sets an offset for your query.

10) addOrdering(Ordering o) – Sets up an ORDER BY clause for your query. You need to build an fflib_QueryFactory.Ordering object to pass to this method. There are a ton of ordering method permutations in this class, so definitely check them all out.

11) subselectQuery(String relationshipName) – Sets up a subquery for the query. You need to pass in a string representation of the relationship fields developer name to this method.

12) toSOQL() – Takes the fflib_QueryFactory you’ve just built and turns it into an actual string representation of the query that you can use in a Database.query() call.

13) deepClone() – Creates a clone of your fflib_QueryBuilder query in case you’d like an easy way to generate another permutation of this query without rebuilding the whole thing.


Next Section

Part 15: The Difference Between Unit Tests and Integration Tests

SoC and the Apex Common Library Tutorial Series Part 15: The Difference Between Unit Tests and Integration Tests

What is Unit Testing?

Unit Testing, is a way to test the logic in one class and ONLY one class at a time. Most classes in your system at some point do one of the following:

1) Call to another class to get some work done.
2) Query the database directly in the class.
3) Do DML transactions directly in the class.

However, in unit testing, we ideally don’t want to do any of those things, we don’t care if the querying or the DML transactions or the calls to those other classes work, because what we want to test is that the logic of our class works in every theoretical permutation we can think of AND THAT’S IT! We just want to know if our logic, that we designed for this one class actually works as we anticipate it to work.

You might be thinking, “How is that possible? We need those queries and those dml statements and those classes to successfully run our code!”. Well that my friends is simply not true. With the implementation of separation of concerns and by leveraging one of the many available mocking frameworks we can fake all of those things to build true unit tests.


When Should I use Unit Testing?

Just because you are leveraging unit testing doesn’t mean there still isn’t a need for integration tests (more on that below), so when should you do Unit Tests in favor of Integration tests? It’s a pretty simple answer. The logic in your class’s code could have 40+ paths it could take… maybe even 100… The code in your class could have logic that runs when your code fails, logic that runs when your codes successful, logic that runs when someone creates a $200,000,000 opportunity as opposed to a $2,000 opportunity. There could be so many paths. We DO NOT need an integration test for every single one of those paths. It could take 20+ minutes to run integration tests for all those paths whereas unit testing them could take just seconds. As your codebase grows, if you didn’t make these unit tests your test class runs to deploy to prod could take hours… maybe days… we don’t want that homie. So when do you unit test? You unit test to test the bajillions of permutations of your class’s logic. When do we choose integration tests?? Keep reading. You’ll find out below.

An additional benefit to unit testing/mocking responses is testing hard to test or impossible to test error catching scenarios. One common scenario that I find myself frequently building error catching around is record locking… but how on earth can you test that with real data at run time? It’s borderline impossible, however unit testing makes testing for errors a breeze. It’s so easy you’ll cry, lol, the dream of 100% code coverage can go from just a dream to a very real and easily obtainable thing with unit tests and mocking.


What is Integration Testing?

Integration testing is when you test your code from point A all the way to point Z. What I mean by that is, you actually have your code in your test classes doing SOQL statements, DML transactions, calling the other classes it depends on, etc. Basically your code is truly calling all the real logic from beginning to end, no mocking or fake return results anywhere. Integration testing is what 90%+ of Salesforce orgs seem to do 100% of the time and that is one dangerous game to play. The majority of your tests should not be integration tests… maybe like 20% of them or so. If 100% of your test classes are integration tests, over time you’ll suffer from long test execution and deployment times (or alternatively poorly tested code to reduce those times). If you’ve ever been stuck in a 6+ hour deployment, I think you know what I mean… and what if one test fails during that deploy?… it really hurts, lol. Please, don’t get me wrong though, you can not replace integration tests with unit tests, they are of equal importance, it’s just important that you only use integration tests when needed.


When Should I use Integration Testing?

All apex classes should have some level of integration testing. I like to write somewhere around 20% of my tests as integration tests and 80% of my tests for a class as unit tests. Typically I will, for each class that has dependencies (classes that the class I’m currently testing calls) write two integration tests for each dependency. One integration test that tests a successful path through my classes code and its dependencies and another that tests failures. This may be, in some peoples opinion, overkill, but I personally feel that it’s not an enormous amount of overhead (typically) and it gives me some piece of mind that all of the classes my class I’m testing depends on still operate well with it. So, when to use integration testing? In my opinion, in every test class, but use them sparingly, use them to check that your transactions between classes still work, don’t use them to test every logical path in your class’s code. That will spiral out of control.


Next Section

Part 16: Unit Test Mocks with Separation of Concerns

SoC and the Apex Common Library Tutorial Series Part 16: Unit Test Mocks with Separation of Concerns

How does Unit Testing fit into Separation of Concerns?

The answer to this is simple, without Separation of Concerns, there is no unit testing, it just simply isn’t possible. To unit test you need to be able to create stub (mock) classes to send into your class you are testing via dependency injection (or through the use of a factory, more on this in the next section). If all of your concerns are in one class (DML transactions, SOQL queries, service method, domain methods, etc) you cannot fake anything. Let’s take a look at a couple examples to illustrate this problem:

Unit Testing a class with SoC Implemented

//This is the class we would be testing
public with sharing class SoC_Class
{
	private DomainClass domainLayerClass;
	private SelectorClass selectorLayerClass;

	public SoC_Class(){
		//This is calling our private constructor below
		this(new domainLayerClass(), new selectorLayerClass());
	}

	//Using a private constructor here so our test class can pass in dependencies we would
	//like to mock in our unit tests
	@TestVisible
	private SoC_Class(DomainClass domainLayerClass, SelectorClass selectorLayerClass){
		this.domainLayerClass = domainLayerClass;
		this.selectorLayerClass = selectorLayerClass;
	}

	public List<Case> updateCases(Set<Id> objectIds){
		//Because of our dependency injection in the private constructor above we can 
                //mock the results of these class calls.
		List<Case> objList = selectorLayerClass.selectByIds(objectIds);
		if(!objList.isEmpty()){
			List<Case> objList = domainLayerClass.updateCases(objList);
			return objList;
		}
		else{
			throw new Custom_Exception();
		}
	}
}

//This is the class that we build to unit test the class above
@IsTest
public with sharing class SoC_Class_Test
{
	@IsTest
	private static void updateCases_OppListResults_UnitTest(){
		//Creating a new fake case id using the IdGenerator class. We do this
		//to avoid unnecessary dml insert statements. Note how the same id is used 
                //everywhere.
		Id mockCaseId = fflib_IDGenerator.generate(Case.SObjectType);
		//Creating a set of ids that we pass to our methods.
		Set<Id> caseIds = new Set<Id>{mockCaseId};
		//Creating the list of cases we'll return from our selector method
		List<Case> caseList = new List<Case>{new Case(Id = mockCaseId, Subject = 'Hi', 
                Status = 'New', Origin = 'Email')};
		List<Case> updatedCaseList = new List<Case>{new Case(Id = mockCaseId, Subject 
                = 'Panther', Status = 'Chocolate', Origin = 'Email')};

		//Creating our mock class representations by using the ApexMocks class's mock 
                //method and passing it the appropriate class type.
		fflib_ApexMocks mocks = new fflib_ApexMocks();
		DomainClass mockDomain = (DomainClass) mocks.mock(DomainClass.class);
		SelectorClass mockSelector = (SelectorClass) mocks.mock(SelectorClass.class);

		//After you've setup your mocks above, we need to stub (or setup the expected
		//method calls and what they would return.
		mocks.startStubbing();

		//This is the actual selectByIds method that we call in the
		//createNewOpportunities method that we are testing
		//Here we are setting up the fake return result it will return.
		mocks.when(mockSelector.selectByIds(caseIds)).thenReturn(caseList);

		mocks.when(mockDomain.updateCases(caseList)).thenReturn(updatedCaseList);

		//When you are done setting these up, DO NOT FORGET to call the stopStubbing 
                //method or you're gonna waste hours of your life confused
		mocks.stopStubbing();

		Test.startTest();
		//Passing our mock classes into our private constructor
		List<Case> updatedCases = new SoC_Class(mockDomain, 
                mockSelector).updateCases(caseIds);
		Test.stopTest();

		System.assertEquals('Panther', updatedCases[0].Subject, 
                                    'Case subject not updated');
		//Verifying this method was never called, we didn't intend to call it, so
		//just checking we didn't
		((Cases)mocks.verify(mockDomain, mocks.never().description('This method was 
                called but it shouldn\'t have been'))).createOpportunities();
		//Checking that we did indeed call the createTasks method as expected.
		((Cases)mocks.verify(mockDomain)).updateCases(caseList);
	}
}

Above you can see we are passing in fake/mock classes to the class we are testing and staging fake return results for the class methods we are calling. Thanks to separating out our concerns this is possible. Let’s take a look at how impossible this is without SoC in place.

Unit Testing a class without SoC Implemented

//This is the class we would be testing
public with sharing class No_SoC_Class
{
	public List<Case> updateCases(Set<Id> objectIds){
		//Because of our dependency injection in the private constructor above we can 
                //mock the results of these class calls.
		List<Case> objList = [SELECT Id, Name FROM Case WHERE Id IN: objectIds]
		if(!objList.isEmpty()){
			for(Case cs: objList){
				cs.Subject = 'Panther';
				cs.Status = 'Chocolate';
			}

			update objList;
			return objList;
		}
		else{
			throw new Custom_Exception();
		}
	}
}

@IsTest
public with sharing class No_SoC_Class_Test
{
	@TestSetup
	private static void setupData(){
		Case newCase = new Case(Subject = 'Hi', Status = 'New', Origin = 'Email');
		insert newCase;
	}

	@IsTest
	private static void updateCases_CaseListResults_IntegrationTest(){
		Set<Id> caseIds = new Map<Id, SObject>([SELECT Id FROM Case]).keySet();
		List<Case> updatedCases = new No_SoC_Class().updateCases(caseIds);
		System.assertEquals('Panther', updatedCases[0].Subject, 'Case subject not 
                updated');
	}
}

You can see above we did no mocking… it wasn’t possible, we had no way of passing in fake/mock classes to this class at all so we had to do an integration test where we create real data and update real data. This test will run considerably slower.


How do I transition my Existing Code to start leveraging SoC so I can use Unit Test Mocking?

It’s not a simple path unfortunately, there is a lot of work ahead of you to start this transition, but it is possible. The key is to start small, if you are a tech lead the first thing you need to do is find the time to train your devs on what SoC and mocking is and why you would use it. It’s critical they understand the concepts before trying to roll something like this out. You cannot do everything as a lead even if you’d like to, you need to build your team’s skillset first. If you aren’t a lead, you first need to convince your lead why it’s critical you start taking steps in that direction and work to get them onboard with it. If they ignore you, you need a new lead… After accomplishing either the above you should do the following:

1) Frame your situation in a way that the business arm of your operation understands the importance of altering your code architecture to leverage SoC and unit testing. This is typically pretty easy, just inform them that by spending a few extra points per story to transition the code you are going to gain more robust testing (resulting in less manual tests) and that the code will become more flexible over time, allowing for easier feature additions to your org. Boom, done, product owner buy in has been solidified. Ok, lol, sometimes it’s not quite this easy, but you know your business people, give them something they won’t ignore, just be careful to not make yourself or your team sound incompetent, don’t overcommit and make promises you can’t keep and frame it in words business people understand (mostly dollar signs).

2) Start small, take this on a story by story basis. Say you have a new story to update some UI in your org, with business owner buy-in, tack on a few extra points to the story to switch it to start using SoC and Unit Testing. Then, MAKE SURE YOUR TESTS ARE INCREDIBLE AND YOU TRUST THEM! I say this because, if your tests are incredible you never have to ask for permission again… I mean think about it, wtf does the average business person know about code. As long as I don’t introduce any new bugs I could change half the code base and they’d never even know. If your tests are golden, your ability to change on a whim is as well. Make those test classes more trustworthy than your dog (or cat I guess… but I wouldn’t trust a cat).

3) Over time, your transition will be done… it might take a year, it might take 5 years, depends on how busted your codebase was to begin with. Hopefully, by the time you are done, you have an extremely extensible codebase with tests you can trust and you never have to ask for permission to do a damn thing again.


Additional Information

If the above didn’t make how to implement mocking via separation of concerns any clearer, I also have a video covering the subject here.


Next Section

Part 17: Implementing Mock Unit Testing with Apex Mocks