Dependency injection in apex

Manjot Singh
Salesforce-Lightning
3 min readDec 10, 2023

What is dependency injection? It is a programming technique in which an object or function receives other objects or functions that it requires, as opposed to creating them internally.

What does above definition means. Let’s try to see that by a simple example. Let’s say we are writing a method to send a notification to user. We can write this code like below:-

Here we are sending notification to contact using an Email. Also creating an email object in this method itself.

Now let’s implement same with dependency injection. Our new method will look like this

So in this method we are not creating any object but using object that was returned by createNotificationObject() method. In this method we can write logic to insert dependency injection for NotificationObject. So based on some custom settings we can toggle which notification we want to send. This will look similar to factory pattern but most important difference between factory and DI is, In DI Classes are loosely coupled.

Now let’s see how we can implement Dependency Injection (DI) in apex with an example. One important area where DI is used is by ISV’s(App-exchange app) where they don’t know how different customers will use their product. In our app we usually build functionality which will be used by most of the customers. But for some customers with special use cases we will write or help them write small code which will work with our code using DI.

Let’s say we are building an app for doing Backup of salesforce data. So, this app will have 2 main parts. First one will be for which data(records) you want to do backup. Second part will be how to do backup. We will try to implement DI for First part.

For Backup we will have a batch class. We can divide this batch class also into 2 main parts. Start method will have logic for which data we want to do backup and Execute method will have logic for how to do backup.

Most common use cases will be to do backup of any object older than some days. To handle this, we can build a custom metadata setting with 2 fields object name and Days older and whenever we run our backup job in start method, we can use these two fields to build our start query.

Now let’s say there is customer who says he want to backup all the case records which are more than a year older, if their status is resolved and last message day is more than 6 months old. So, our current logic in start method will not work.

Now one solution can be to extend our setting to include more fields and their values and keep updating them to include more customer scenario. Other solution will be using DI to help customers who have special use cases.

To implement DI first thing that we will do is create a global interface

We will also add a new field on custom setting called as DIClassName. This field will store name of class that we will create in customers org if they want to use DI. This class should also implement BackupJobInterface. We will also make changes to our BatchJob start method.

What we are doing in this method is if DIClassName is provided in setting then create an Instance of that className and typecasting it to our BackupJobinterface.

So if any salesforce org which has installed our package and want to build some custom logic. They will extend our global interface and create a new class. Like for use case mentioned above for case records we can write below class.

Now in custom metadata field we can populate CaseBackupJob in DIClassName field. When our app’s batch code runs then in start method we will run CaseBackupJob class to get QueryLocator.

This CaseBackupJob class will be in customer’s org whereas interface and batch class will be part of app’s(Manage package) code base.

There are many more use cases where we can use DI. Popular ones are with Triggers and Testing Frameworks.

If you learned something new…. Follow and Clap 👏 🙂

--

--