What Is Dependency Injection

What Is Dependency Injection

ยท

5 min read

Injections anyone? ๐Ÿ˜ฃI hate them too ๐Ÿ˜‚. Well, turns out modern software development can't live without injections ๐Ÿ˜‚. It's no secret that we write a lot of code as software engineers. In a bid to improve the functionality of code, we optimize performance as much as possible. A lot of code is broken up into classes, some of which have methods that perform certain critical operations. Depending on the size and complexity of these classes, calling a new instance of them can be very draining on the machine.

An image of a little girl sitting on a man's laps while she's being taught by the man

A Relatable Explanation

To put it into a more relatable perspective, imagine you have a 50-story building where a lot of serious work is done, possibly the HQ of your organization. The average company relies on HQ on a daily basis for different things. Now imagine if everytime your office needs something from your HQ, you need to erect another 50-story building near your office, fill it up with the same people and equipment your HQ has just to get the result you wanted from HQ. It's impractical, yes? ๐Ÿ˜….

But what if you need a small tent at your office? Would you call HQ to send one your way or build a tent yourself? ๐Ÿ˜. So, we see that the building of structures isn't the problem, it's only a problem when it takes too much time and resources. Dependency Injection (DI) is a design pattern that lets us avoid creating new instances of a class (that already exists), DI has many utilities (which I won't bore you with here ๐Ÿ˜…), but for the purpose of this small intro, let's just understand that it helps make code cleaner, more maintainable, and testable.

Having to create new instances of a class everytime you need it slows down the application's performance as processing power is used in recreating the class for use. One beautiful thing about DI is despite its fancy name, it's quite easy to use in its basic sense. All one needs to know is how to create private variable, create a method, constructor, or property, register the dependency, and simply pass the registered dependency (which is more or less the class) into the method, constructor, or property you need it in, then assign your private variable to the value of the dependency you injected.

An image of three miniature toys in the woods

Registration Types Of Dependency Injection

Now some of you may be asking if one needs DI in a situation where you need a new instance of something everytime you call it, DI is built in such a way that it provides three ways you can register it. You can register a singleton dependency to be consistent throughout the lifetime of a request (even across linked applications), within a scope (limited region of code/request) which is a scoped dependency injection, or the dependency can act brand new everytime you call it (transient)๐Ÿ˜‰.

For a singleton, you don't need a new instance of the dependency throughout the lifetime of the request, a scoped restricts the consistency of a dependency within a region (class) of code, while a transient registration means you want a new instance of the dependency whenever you call the class. A request can simply be a finite space of time with which a user interacts with a platform.

An image of a fog toy holding a pen

How To Implement Dependency Injection

This is done in literally two phases. Firstly, I'll assume you already have the class you want to inject and it's interface; I'll take you through a simple method dependency injection. I will be taking you through this using C#.

Step 1: Register the dependency in the ConfigureServices middleware. You can find this in your program.cs class. Note that you need to add

using Microsoft.Extensions.DependencyInjection; to your using statements.

        public static IHostBuilder CreateHostBuilder(string[] args)
        {
            return Host.CreateDefaultBuilder(args)
                //This configures the service to run as a windows service so it can be deployed.
               .UseWindowsService()
               .ConfigureServices((hostContext, services) =>
               {
                  //I'm running with the assumption that this project is a worker service, your project can be anything, I just didn't want to leave out this part
                   services.AddHostedService<WorkerService>();
                   //The services below show how to register Singleton, Scoped, and Transcient dependency. 
                   //The values with "I" prefix are interfaces.
                   services.AddSingleton<ICustomerData, CustomerData>();
                   services.AddScoped<ICustomerRequest, CustomerRequest>();
                   services.AddTranscient<ICustomerResponse, CustomerResponse>();
               })
        }

Step 2: Call the dependency within your method

namespace SampleProject
{
//This is a sample class
public class Customer
{
//Initializing the class(es) you'd using dependency injection for within the class you plan to use it in is necessary so you can obtain and leverage the injected dependency 
private ICustomerData, _customerData;
private ICustomerRequest, _customerRequest;
private ICustomerResponse, _customerResponse;

//You're able to inject the dependency by passing each value as parameters into this method.
public void HandleCustomer(ICustomerData customerData, ICustomerRequest customerRequest, ICustomerResponse customerResponse)
{
//Here we assign the value of the value of the injected dependency to the initialized classes.
//After the bit below, you can go on to leverage the methods within the injected dependency by calling the initialized classes that have the "this" prefix.
this._customerData = customerData;
this._customerRequest = customerRequest;
this._customerResponse = customerResponse;
}
}
}

An image of a girl walking with three balloons that look like planets

Finally...

Dependency Injection can be a really great way to improve the quality and performance of written code. While this isn't an exhaustive tutorial, it'll be enough to help get you started ๐Ÿฅ‚.