Hello friends, welcome to programming concepts my
name is amit and in this video we will learn the basics of dependency injection with the help of
same example, we will learn inversion of control, dependency inversion principle and dependency
injection. We will also answer the very basic but most confusing question which developer have? that
is, How dependency injection help in unit testing? we will also explore how web.config can
be your best example in interview, when explaining about inversion of control and
last but not the least we will also answer why should we use dependency injection when
we already have dependency inversion principle. so dependency injection itself is not difficult to
understand you must have heard dependency injected by a constructor, method, or property and that's it
you are done the real problem arise when you start comparing different terms available in the market
in the IT industry like IOC inversion of control dependency inversion principle DI or IOC container
this is the time when we start doubting ourselves why should we use dependence injection how
they are different from each other etc etc we will compare and cover every aspect in
this video and by end of this video you will get all your answers all right so let's begin
before moving forward it is really important to understand what dependency and tight coupling
is let's say for example we have a class B and this class B has some dummy method and that
will do something that's it our class B is ready then we have a class A where we
declare the variable of classB and within the constructor of classA
we instantiated the object of classB so if we created some class that must
be responsible for doing something so for that let's say classA has to perform some
task let's name it task1 and here we do something and the activity of task1 is dependent on class B
So we call the method of classB dummy method and then again we will do something within classA
that's it simple very straightforward example but if you can see that task 1 is dependent
on dummy method of class b so it has some kind of dependency on classB and when we
initialize the object of classB within constructor that is tightly coupled with classB
for example if there is any change in classB it definitely going to impact classA so this is what
dependency and tight coupling is in about, so all these concept dependency, tight coupling, dependency inversion principle
IOC, dependency injection these concepts are really simple but the basic problem
with developers to understand this concept is when we start our career we generally have full
control over complete application so we act as a full stack developer, Right? Where we own UI, we own
services, we own business logic, database and all just in case you are also in a similar kind
of project or your team is in a similar kind of project where you own everything so we just
wanted to make an assumption before going forward so for the rest of this video, I would request
you to assume that you don't own even a single other class in your project. Simple? Although this
assumption or the statement seems pretty easy but believe me for full-stack developers or developers
like me who started their career with complete ownership of each and every module even to
assume we don't have access to any other class is extremely difficult. So, I would request you to make
that assumption in your mind for the rest of the video. In that note let's suppose we have a project
requirement with us and the requirement is like create module to log errors in text file to
achieve this let's say we will first create class library project and first class of this project
will be log to text and this will be managed by teamA, second class will be business logic
class and suppose this will be managed by teamB so we will create another project and that
project will be a console application project and again this will be a dummy client who will use
our project, our organization project or services so here we are creating a class library project so
this console application project will consume our class library project, the DLL and assume class library
project will be used by similar multiple clients I already created both the projects in visual
studio. Let's see, this is our empty class library project and the next one, this is our console
application project so let's get back to slide and create both the classes so public class log to
text bracket open public void log string message so console.writeline message bracket close bracket
close and your class is ready. So here just assume that instead of console.writeline in real world
it will log your message into a some kind of text file. Let's create another class so public
class business logic bracket open log to text let's name it underscore obj log public business
logic bracket open we created a constructor here and again obj log is equal to new log to text public void dummy method string message
and this method will consume log to text method which is log, bracket close so if we look
at this code this project is similar to what we had shown you in the slide of dependency
and tight coupling so here you can see business logic is dependent on logtotext class All right, also business logic is tightly coupled
with log to text because we created the object within business logic constructor so the question
is, is there any problem with this implementation because we already following such kind of approach
since we are doing a development. Correct? so in general not not a big problem if you have control
over all the classes and your project is small let's see the problems one by one so the first
problem is in case of change in dependent class log to text we need to make changes in all
places where we are referencing this class okay let me just copy and
paste the code in visual studio so open a class library project right
click on the project add a class and let's name it businesslogic.cs click on it so let's copy and paste
our code in this particular file so this is similar code which we have seen
in the slides we have a business logic class we have a log to text class so the problem
statement was if there is any modification in log to text class then it will impact all
the classes which is referencing this class all right so for example this class as of
now we have a default constructor which is created by dotnet itself let's create another
constructor public lock to text bool is valid so what will happen now it will start impacting
business logic class and in this project you know seems really easy that you can modify the business
logic class but in real-world that log to text class might be used by, you know, multiple projects
where you don't have much control over them so this is one of the problem that we need to modify
all the dependent classes who are using our class let's get back to the slide and let's say in case
of future upgrade, our product starts supporting logging the logs into the database. All right!!
so again we need to make modification in all our dependent classes let's get back to the code
so here you can see that log to text file is hard coded within business logic class so again
all the classes who are referencing log to text we need to change the name to log to sql database
or something to make it easy let's create another class let's just copy log to text class
and let's rename it log to sql database so now if business logic class have to consume
log to sql database class they need to rename log to text class with log to sql database
class and that log to text class might be used in 1000 other classes. All right? so you
need to rename them again in all the classes so if you're from a dot-net background or
using some powerful IDE like visual studio then you must be wondering what's the problem in
renaming log to text class so if I have to rename log to text to log to sql database then what we
can do, we can just right click on log to text click on rename and rename as per our convenience
like log to sql database and then what i will do i will click apply so that will rename log to text
to log to sql database across application. Correct? If you are thinking in that way then you are still
in full stack developer mode. Remember I asked you to make an assumption that you don't have control
over other classes, correct, so you can make modification in business logic class there might
be a possibility that other class which you don't own. Another possibility is that this particular
dll class library vendor so this particular dll might be used by some other project where you
don't even have access to their code correct so let's see how we can overcome these limitations for that first we need to understand what
inversion of control is? so let me read out the definition then we will understand what
actually the concept is so inversion of control is a design principle remember it is a principle
not a pattern, is a design principle used to invert different kinds of control in
object-oriented design to achieve loose coupling the main objective of inversion of control
is to remove dependency between objects of an application which makes the application more
decoupled and maintainable inversion of control is a principle which means it is a general guidelines
and end user can choose the way how they wants to implement it all right so let's use this principle
to refactor our code so this is our existing code so let's create another class public class factory and this class have one static method
public static log to text get logger and it will simply written log to text
object that's it our factory class is ready now we need to refactor our business
logic class so public class business logic log to text underscore obj log public business
logic this is the constructor bracket open so now there is a change instead of creating new log
to text let's use the factory class to provide us the instance of log to text class so obj log is
equal to factory dot get logger other code will remain the same public void dummy method string
message bracket open underscore objlog.log message that's it so if you look at the code closely this
will resolve the problem statement one in case of change in dependent class log to text we need
to make changes in all the places where we are referencing this class now if multiple classes are
using log to text class with a default constructor and there is a change in constructor then we only
need to make modification within our factory class so that will be our central point so what we
had done here we just inverted the control previously business logic class has control
to create the object of log to text class now we just give this responsibility to another
class, Iknow this is a very basic example of IOC inversion of control and that too is
not implemented properly but that's what inversion of control is all about we are just
inverting the control just in case if you have any confusion let's cover another example of IOC
another very good example I can think of IOC is connection string in web.config. what?
connection string in web.config but how let's see a practical example
of it let's get back to our code let's create this method within business logic
class so public string get connection string and that will return configuration manager
press ctrl dot to add the reference dot connection strings and let's name
it myconstring dot tostring that's it so this connection string my con string
is not present within my dll i haven't specified it anywhere correct so
let's rebuild our class library project and let's get back to our console application I
already added the reference of that class library project and if you can see in the app.config
I already specify one connection string with the name my con string which is there in my
class library project and here it is. All right let's go to program.cs file and within
static void main method let's write new business logic ctrl dot to add the reference dot
get connection string that's it our code is ready now if I run this program what do
you think what would be the output so if you guessed that it will
return the connection string which is present in the console application our
client application then you are correct all right but how it is possible so that's what
internally inversion of control is all about so ideally we should define the connection string
and everything within our class library project but what we want we want that it should be
provided by our client so my business logic class is not owned the responsibility to have the
connection string right so that responsibility has been provided to the clients now I hope you
understand the concept of IOC slightly better just give the responsibility to someone else
who can manage it better than you alright let's get back to the slide so with the current implementation we are able to
get rid of problem one but the problem statement two still persist let's learn another concept
before getting rid of this problem statement and the new principle is dependency inversion
principle so let me read out the definition I already covered dependency inversion principle
in a great detail so you can watch that if you are not much aware of dependency inversion
principle i will share the link in the description so the dependency inversion principle states that
high-level module or classes.. high level should not be dependent on low level modules or classes both
should depend upon abstraction also abstractions should not depend upon details but details should
depend upon abstractions, again i am assuming you have basic idea of what DIP is just in case you
are completely unaware of what DIP is I would strongly recommend you to watch that video and then
get back to this video all right so let's refactor our code according to DIP so first create an
interface public interface Ilogger void log string message then create our log to text class
public class log to text and that class will be inherited from Ilogger class next is method public
void log string message console.writeline message and that's it logtotext class is also ready
next is factory class so public class factory public static ilogger get logger so instead of
returning the exact class name we are returning the interface return new log to text class
and that's it our factory class is also ready our final class is business logic class so
public class business logic now again instead of log to text class we are using i logger
interface so ilogger underscore obj log public business logic and again underscore
obj log is equal to factory.getlogger so the responsibility is still with factory class and
rest of the code is same public void dummy method string message underscore objlog.log message and
that's it our business logic class is also ready so this code will solve our problem statement 2
as well for example in future if we need to save these logs into a database so when the new class
will be created so that will also inherit it from logger interface so in future if business
logic or similar other class wants to use log to sql database instead of log to text we only
need to make modification within our factory class like this and that's it everything is
perfect right so all the scenarios and all the problems has been covered
but there is still one problem like the control to select logger class
is still within our business logic dll right and that dll will be consumed by
our clients and our client project console application project is still not in control to
select which logger class they wanted to use so here is the expectation just like we had
specified connection string in our main project console application project and our dll picked
it dynamically can't we create such mechanism with a code as well so that our end user is in
control to select which logger they want to use obviously depending on the scenario
you can use if an else statement to achieve this but let's see
how to do it in an efficient way let's learn dependency injection so dependency
injection is a design pattern that used to implement IOC so IOC was a principle DI is a
pattern it allows the creation of dependent objects outside of class and provide those
objects to a class through different ways using DI we move the creation and binding of
dependent objects outside of the class that depends on them so there are different types
of dependency injection available like you can inject it by a constructor you can inject it
by property and you can inject it via methods so let's refactor our class so
our interface will remain the same log to text class will remain the
same there is no need of factory class let's refactor our business logic
class so public class business logic let's create an object of i logger i logger
underscore obj and within the constructor specify the parameter as i logger let's name it underscore
logger and assign this injected ilogger object to our local variable next is public void dummy
method string message objlog.log message etc etc so this is what we call dependency injection via
constructor so because we injected dependency of log to text file via our constructor now
if end-user or the client can use it like new business logic new log to text bracket
close dot dummy method my log message so that will work the same way
it was working previously let's see how it will work in our code so let's
copy and paste the code of our dll class rebuild that dll and within our console application just
write new business logic bracket open new log to text bracket close again close dot dummy method
my log message and that's it just run the application and eventually, it will print my log message so we successfully injected the
dependency of log to text class in future if client want to use a log to sql then
instead of using log to text class they can use log to sql database class so the control is with
the client not within our dll or the jar file let's get back to the slides and see the benefits
and drawbacks of this approach so the benefits is it provide loose coupling it will help in
unit testing drawbacks are no compilation time IntelliSense and chances of runtime error
but wait help in unit testing but how let's see how this approach will help us in unit testing so
let's see the code without dependency injection and here it is and let's assume that we need
to add few more parameters to log to text file so let's assume this log to text file has couple
of parameters like id and name the only problem is that id we need to fetch it from database and
that name we need to fetch it from client api now because the responsibilities with class
itself you cannot provide dummy data to this class right so let's say your manager say provide me the
unit test report with logger with id 1 logger name is pro. developer.. but client database and its
API is not available for any reason how does it matters i only want a unit test report and boom
you're stuck but if you had used the dependency injection approach then unit testing will be quite
easy because the responsibility is someone else into the client so we can simply test it with obj
id is equal to 1 obj name is equal to pro and then business logic objBL is equal to new business
logic and done that's it a unit testing is completed and independent of database independent
of any API I hope these simple examples will help you to understand what DI is their significance
and how it is different from IOC and DIP so that's it from this video if you have any
query do ask me in comments. thanks for watching