2. Here’s the absolute worst explanation ever:
”Instead of newing up objects, you just call ‘container.resolve’”
3. With the definition of, “just call container.Resolve instead of newing an
object up”, when you go to a job interview and whiteboard some pseudo-
code, they might say something like:
Pretty sure this
guy voted ‘NO’
on hiring me…
4. Merriam Webster Dictionary: “something that is dependent on something else”
For example: “A time-traveling DeLorean’s dependency on plutonium was a real
problem in 1955.”
Wikipedia’s definition relative to computer science: “[A dependency is a] coupling,
a state in which one object uses a function of another object.”
For example: My app needs to make calls to a web service to get and store data, so my
business logic has a dependency on the web service.
When you have a “coupling” of two classes, a loose coupling is the way to go in order to
make your code more testable and maintainable for the future.
5. 3 common types of dependency injection:
Setter Injection
Dependencies are injected through specific property setters. I have never seen this in the wild.
Interface Injection
Classes with dependencies implement an interface that exposes a setter method, and
dependencies use this to inject themselves into any class passed to it. I have never seen this in
the wild.
Constructor Injection
Yaaaaaaay! Winner winner!! Dependencies are injected through the class constructor. This is the
only method I’ve seen in the wild.
7. We want ALL of our dependencies to be based on an interface.
Any service code you write should have an interface. Other classes in your app
will rely only on the interface… Not the “concrete” implementation of the
interface.
You will definitely run into situations where some 3rd party code does not provide
an interface (Microsoft’s HttpClient class, as a ubiquitous for-instance).
Never give up… Never surrender! There are ways to create wrappers for such classes
which keep the vast majority of your code testable and loosely coupled. True story!
8. Before DI After DI
You’ll notice you use the “new”
keyword a WHOLE lot less when
using Dependency Injection.
9. When I finally learned how to use dependency injection, I still had no clue WHY
we were using it. All I knew was that some highly paid consultants said to do it,
and that was that.
The two most important reasons to use “DI” (Dependency Injection):
Makes it super-mega-monster-easy to unit test code without insanely complicated
setups.
Caveat: As long as you learn how to use mocks when unit testing. On Luxor, we use MOQ, which
I would absolutely recommend.
Another popular mocking framework for .NET: NSubstitute
Promotes writing code where various services (aka ‘dependencies’) your code requires
can be loosely coupled with your code.
10. The container is at the very heart of your DI implementation.
Interfaces are mapped to concrete types, so that the container can provide the
correct implementation when an interface is requested.
Containers typically allow you to specify the “lifetime” of any object it knows
about. You can have a singleton, one instance per thread, and more.
Containers map views to viewModels in the MVVM design pattern (used in UWP,
WPF, and Xamarin.Forms apps, for example).
The container is the thing that will new up all of your services, views, and
viewModels as they are needed.
11. The magic: When you need some service in a class, you just add the interface to
its constructor, and the container magically will provide it!
No… SERIOUSLY. It’s kind of amazing!!
12. How does the
container know what
concrete types to
provide for your
interfaces?
How does the
container know which
views go with which
viewModels?
Answer:
Registration!
13. Notice that ALL of the constructor parameters are interface types.
When we discover we need a new service, we can just add it to the constructor,
and our DI container takes care of injecting it (thanks to the registration).
Note: Yes, there might be a code smell of too many dependencies in this ViewModel, but
that’s not important right now.
14. The ViewModel from the previous slide has SEVEN dependencies. That would be
a TON of overhead if they were all concrete classes, and LOTS of integration
concerns to worry about when it came to testing!
Instead, we just mock, mock, mock all our problems away!
16. Infinitely easier (and possible!) unit testing of code.
Loosely coupled software.
While DI is complex, the alternative is even MORE complex!
Just ask for whatever services you want in a constructor, and your DI container
will “make it so”!
No complications about whether a class is a singleton or not… You already took
care of that when you registered the class with the container.
As long as the container knows about the interface and the concrete class you
want to implement it with, you’re all set.
Swap out implementations of interfaces (demo mode, anyone??).