SlideShare a Scribd company logo
http://stackoverflow.com/questions/1638919/how-to-explain-dependency-injection-to-a-5-year-old/1638961#1638961
Dependency Injection, 
the right way 
Thibaud DESODT 
@tsimbalar
This talk 
• What it is about 
– Dependency Injection (DI) patterns 
– Benefits 
– Common pitfalls 
• What it is not about 
– Specific IoC/DI Container implementations 
• Pre-requisites 
– OOP 
– Class-based statically-typed languages 
• Based on examples
What ? 
DEPENDENCY INJECTION
Dependency Injection 
Dependency Injection is a set of practices that 
allow to build loosely coupled applications
Dependency Injection 
Dependency Injection is a set of practices that 
allow to build loosely coupled applications 
It’s NOT : 
– A library 
– A framework 
– A tool 
It IS : 
- A way of thinking 
- A way of designing code 
- General guidelines
Dependency Injection 
Dependency Injection is a set of practices that 
allow to build loosely coupled applications 
Small components … 
- Independent 
- Reusable 
- Interchangeable 
… plugged together to 
form a bigger system 
Benefits : 
- Small classes with single 
responsibility 
- Easier maintenance 
- Extensibility 
- Testable
Show me the code ! 
FROM TIGHTLY TO LOOSELY 
COUPLED
Example : Boring Bank™ System 
• Features 
– User can list his 
accounts 
– User can rename his 
accounts 
– User can transfer money 
from an account to the 
other 
• Tech : 
– Web front-end 
– Relational database
Starting from scratch 
public class AccountController : BaseController 
{ 
// GET: Account 
[HttpGet] 
public ActionResult Index() 
{ 
var userId = this.User.AsClaimsPrincipal().UserId(); 
using (var context = new BankingDbContext()) 
{ 
var accounts = context.Accounts 
.Where(a => a.CustomerId == userId) 
.OrderBy(a => a.Title).ToList(); 
return View(accounts); 
} 
} 
[HttpPost] 
public ActionResult TransferPost(int from, int to, decimal amount) 
{ 
var userId = this.User.AsClaimsPrincipal().UserId(); 
using (var context = new BankingDbContext()) 
{ 
var accountFrom = context.Accounts 
.Single(a => a.CustomerId == userId && a.Id == from); 
var accountTo = context.Accounts 
.Single(a => a.CustomerId == userId && a.Id == to); 
accountFrom.Balance -= amount; 
accountTo.Balance += amount; 
context.SaveChanges(); 
return RedirectToAction("Index"); 
} 
} 
data 
business 
presentation
Tightly-coupled code 
• Using another kind of UI ? 
• Using another kind of storage ? 
• Using the business rules somewhere else ?
Separation of Concerns 
• Layered architecture / split assemblies 
– Presentation 
– Business 
– Data-access (Repository) 
• Separated : 
– Persistence Entities 
– Domain Entities 
– View Models
public class AccountController : BaseController 
public Account GetAccountForCustomer(int customerId, int accountId) 
{ 
// GET: Account 
[HttpGet] 
public ActionResult Index() 
{ 
var userId = this.User.AsClaimsPrincipal().UserId(); 
public void Transfer(int userId, int fromAccountId, int toAccountId, decimal amountToTransfer 
var userAccountService = new UserAccountService(); 
var accounts = userAccountService.GetAccountsForCustomer(userId); 
return View(ToViewModel(accounts)); 
} 
[HttpPost] 
public ActionResult TransferPost(int from, int to, decimal amount) 
{ 
var userId = this.User.AsClaimsPrincipal().UserId(); 
var userAccountService = new UserAccountService(); 
userAccountService.Transfer(userId, from, to, amount); 
return RedirectToAction("Index"); 
} 
AccountController.cs (WebPortal) 
UI talks to Business 
{ 
// TODO : validate arguments 
var accountRepository = new AccountRepository(); 
var fromAccount = accountRepository.GetAccountForCustomer(userId, fromAccountId); 
var toAccount = accountRepository.GetAccountForCustomer(userId, toAccountId); 
// TODO : verify that there is enough money 
fromAccount.Balance -= amountToTransfer; 
toAccount.Balance += amountToTransfer; 
accountRepository.Update(fromAccount); 
accountRepository.Update(toAccount); 
} 
UserAccountService.cs (Business) 
Business talks to Data 
{ 
using (var context = new BankingDbContext("BankingDbContext")) 
{ 
var account = context.Accounts 
.Single(a => a.CustomerId == customerId && a.Id == accountId); 
return account; 
} 
} 
public void Update(Account account) 
{ 
using (var context = new BankingDbContext("BankingDbContext")) 
{ 
var accountEf = context.Accounts.Find(account.Id); 
// theoretically, could do "if not changed" 
accountEf.Balance = account.Balance; 
accountEf.Title = account.Title; 
context.SaveChanges(); 
} 
} 
AccountRepository.cs (Data)
That looks fine … but is it ?
anti-pattern : Control Freak 
• Symptoms: 
– Code insists on how the dependencies are built 
– Makes it impossible to use component in isolation 
– Not testable without full stack 
• Easy to spot : new everywhere 
AccountController : BaseController 
Account 
HttpGet] 
ActionResult Index() 
userId = this.User.AsClaimsPrincipal().UserId(); 
userAccountService = new UserAccountService(); 
accounts = userAccountService.GetAccountsForCustomer(userId); 
return View(ToViewModel(accounts)); 
public void Transfer(int userId, int fromAccountId, int toAccountId 
{ 
// TODO : validate arguments 
var accountRepository = new AccountRepository(); 
var fromAccount = accountRepository.GetAccountForCustomer 
var toAccount = accountRepository.GetAccountForCustomer 
// TODO : verify that there is enough money 
fromAccount.Balance -= amountToTransfer; 
toAccount.Balance += amountToTransfer; 
accountRepository.Update(fromAccount); 
accountRepository.Update(toAccount); 
}
Unit tests as a Coupling Detector 
• Unit tests are “just another client” for your 
code 
• If unit tests are hard to write, the code is 
probably too tightly coupled 
-> Let’s make it testable !
Making it testable - Properties 
public class UserAccountService 
{ 
[TestMethod] 
public void RenameAccount_must_UpdateAccountName() 
{ 
public UserAccountService() 
{ 
AccountRepository = new AccountRepository("BankingContext"); 
} 
#region Dependency Management 
public AccountRepository AccountRepository { get; set; } 
#endregion 
Settable property allows 
to “inject” another instance 
// Arrange 
var newName = "someName"; 
var existingAccount = AnAccount(); 
var sut = new UserAccountService(); 
sut.AccountRepository = FAIL FAIL//I want to put a fake here ! 
// Act 
sut.RenameAccount(existingAccount.CustomerId, existingAccount.Id, 
newName); 
// Assert 
// I want to verify what happened .. 
} 
In UserAccountServiceTest.cs , in test project Business.Tests
Programming to an interface 
public class UserAccountService : IUserAccountService 
[TestMethod] 
{ 
public void RenameAccount_must_UpdateAccountName() 
{ 
public UserAccountService() 
{ 
// Arrange 
var newName = "someName"; 
AccountRepository = new AccountRepository("BankingContext"); 
} 
var existingAccount = AnAccount(); 
#region Dependency Management 
var mockRepo = new Mock<IAccountRepository>(); 
mockRepo.Setup(r => r.GetAccountForCustomer(It.IsAny<int>(), It.IsAny<int>())) 
public IAccountRepository AccountRepository { get; set; } 
.Returns(existingAccount); 
var sut = new UserAccountService(); 
sut.AccountRepository = mockRepo.Object; //I want to put a fake here ! 
#endregion Use an interface (or abstract class) instead of concrete class 
// Act 
sut.RenameAccount(existingAccount.CustomerId, existingAccount.Id, newName); 
// Assert 
mockRepo.Verify(r=> r.Update(It.Is<Data.Account>(a=> a.Title == newName))); 
} 
Inject fake instance
pattern : Property Injection 
Expose settable properties to modify dependencies 
Benefits 
• Useful to provide optional extensibility 
• There must be a good “local default” implementation 
Caveats 
• Not very easy to discover point of extension 
• Easy to forget 
• Extra care to avoid NullReferenceExceptions, handle 
thread-safety etc
Making it more explicit - Constructor 
public class UserAccountService : IUserAccountService 
{ 
private readonly IAccountRepository _accountRepository; 
Injection constructor 
used in tests - declare required dependencies as constructor parameters 
public UserAccountService(IAccountRepository accountRepository) 
{ 
public IAccountRepository AccountRepository { get { return _accountRepository; if (accountRepository == null) throw new ArgumentNullException("accountRepository 
_accountRepository = accountRepository; 
} 
public UserAccountService() 
:this(new AccountRepository("BankingContext")) 
{ 
} 
#region Dependency Management 
Default constructor 
used in production code 
[TestMethod] 
public void RenameAccount_must_UpdateAccountName() 
{ 
// Arrange 
var newName = "someName"; 
var existingAccount = AnAccount(); 
var mockRepo = new Mock<IAccountRepository>(); 
mockRepo.Setup(r => r.GetAccountForCustomer(It.IsAny<int>(), It.IsAny<int>())) 
.Returns(existingAccount); 
var sut = new UserAccountService(mockRepo.Object); 
// Act 
sut.RenameAccount(existingAccount.CustomerId, existingAccount.Id, newName); 
// Assert 
mockRepo.Verify(r=> r.Update(It.Is<Data.Account>(a=> a.Title == newName))); 
} 
Inject fake instance
anti-pattern : Bastard Injection 
Enable dependencies for testing, but use hard-code 
implementation in production code 
• Paradox: 
– Lots of efforts to reduce coupling 
– … but forcing a hard-coded value 
• Test-specific code 
• Ambiguity
Cutting the dependency chain 
public class AccountController : BaseController 
{ 
private readonly IUserAccountService _userAccountService; 
public class UserAccountService : IUserAccountService 
Only 1 constructor - dependencies passed as constructor arguments 
{ 
public private AccountController(readonly IAccountRepository IUserAccountService _accountRepository; 
userAccountService) 
{ 
if (userAccountService == null) throw new ArgumentNullException("userAccountService 
_userAccountService = userAccountService; 
} 
public UserAccountService(IAccountRepository accountRepository) 
{ 
if (accountRepository == null) throw new ArgumentNullException("accountRepository 
_accountRepository = accountRepository; 
AccountController (WebPortal) 
} 
UserAccountService.cs (Business)
pattern : Constructor Injection 
Declare required dependencies as constructor 
parameters 
• Declarative 
• Discoverable (Intellisense, Reflection …) 
• Recommended approach in 99.9% of cases 
• Easy to implement 
Need Guard clause because C# does not support non-nullable 
reference types …
Inverted depency
This is great and everything except … 
[InvalidOperationException: An error occurred when trying to create a controller of 'BoringBank.WebPortal.Controllers.AccountController'. Make sure that the controller System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext 
System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext
The chicken and the egg 
IAccountRepository repo = new IAccountRepository(); 
• Ideal world: Programming to interfaces 
vs 
• Real world : applications do not work with only 
interfaces 
• Class instances have to be created and assembled 
(=composed) at some point 
• This happens only in one place in an application
pattern : Composition Root 
Composition of classes into a larger system should 
happen only in one place 
• Create one object-graph 
• As late as possible 
• Only part of the code that can reference concrete types 
Where ? 
• Only applications have a Composition Root 
• There is no Composition Root in a class library 
• Extension point depends on the kind of app
ASP.NET MVC Composition Root 
public class AppCompositionRoot : DefaultControllerFactory 
• IControllerFactory 
• Creates a controller instance based on URL 
• DefaultControllerFactory uses default 
constructor on Controller 
• … but it can be changed ! 
{ 
protected override IController GetControllerInstance(RequestContext requestContext 
Type controllerType) 
{ 
// how to compose an AccountController ? 
if (controllerType == typeof(AccountController)) 
{ 
var connectionString = ConfigurationManager 
.ConnectionStrings["BankingDbContext"].ConnectionString; 
var repo = new AccountRepository(connectionString); 
var service = new UserAccountService(repo); 
return new AccountController(service); 
Controller 
composition 
} 
// standard way in MVC to use default strategy 
return base.GetControllerInstance(requestContext, controllerType); 
} 
} 
public class MvcApplication : System.Web.HttpApplication 
{ 
protected void Application_Start() 
{ 
var factory = new AppCompositionRoot(); 
ControllerBuilder.Current.SetControllerFactory(factory); 
In Global.asax 
tell MVC to use our composition root
Pure DI (aka Poor Man’s DI) 
Manual wiring of dependencies 
• Very explicit (no « magic ») 
• Type-safe 
• … but repetitive and boring 
var connectionString = ConfigurationManager 
.ConnectionStrings["BankingDbContext"].ConnectionString; 
var repo = new AccountRepository(connectionString); 
var service = new UserAccountService(repo); 
return new AccountController(service);
And we did that because … ? 
SO WHAT ?
Benefits of full DI-friendly codebase 
• Testability 
• Maintainability 
• Allows parallel work 
• … and more ! 
• Defined in a centralized location
Reusability / Extensibility 
or CLI 
or WPF 
or Web API 
or WCF 
… 
or files 
or NoSQL 
or Azure 
or Http Client 
…
Extensibility 
public class CachedAccountRepository : IAccountRepository 
{ 
private readonly ICache _cache; 
private readonly IAccountRepository _decorated; 
• Decorator Pattern 
public CachedAccountRepository(ICache cache, IAccountRepository decorated) 
{ 
– Very DI-friendly pattern 
var nakedRepo = new AccountRepository(connectionString); 
if (cache == null) throw new ArgumentNullException("cache"); 
if (decorated == null) throw new ArgumentNullException("decorated"); 
_cache = cache; 
_decorated = decorated; 
// decorate the nakedRepository with caching features 
var • Example longCache = : new caching 
DotNetCache(TimeSpan.FromHours(1)); 
var cachedRepo = new CachedAccountRepository(longCache, nakedRepo); 
var service } 
= new UserAccountService(cachedRepo); 
public IReadOnlyList<Account> GetAccountsForCustomer(int userId) 
{ 
var accounts = _cache.GetOrAdd("accounts_" + userId, 
() => _decorated.GetAccountsForCustomer(userId)); 
return accounts; 
} 
Decorator 
delegate to decorated instance
DI CONTAINERS
DI Container – how they work 
• Mapping Abstraction-> Concrete Type 
– Usually initialized on app start 
– Methods like 
Register<IAbstraction,ConcreteType>() 
• Method Resolve<TRequired>() 
• Recursively resolves dependencies reading 
constructor parameters
public class DependencyConfig 
Example - Unity 
{ 
public static void Configure(IUnityContainer container) 
{ 
var connectionString = ConfigurationManager.ConnectionStrings["BankingDbContext" 
public class MvcApplication : System.Web.HttpApplication 
{ 
public class AppCompositionRoot : DefaultControllerFactory 
protected void Application_Start() 
{ 
private readonly IUnityContainer _unityContainer; 
var container = new UnityContainer(); 
DependencyConfig.Configure(container); 
var compositionRoot = new AppCompositionRoot(container); 
ControllerBuilder.Current.SetControllerFactory(compositionRoot 
{ 
In Global.asax 
.ConnectionString; 
container.RegisterType<IAccountRepository, AccountRepository>( 
new InjectionConstructor(connectionString)); 
container.RegisterType<IUserAccountService, UserAccountService>(); 
} 
} 
public AppCompositionRoot(IUnityContainer unityContainer) 
{ 
In DependencyConfig 
if (unityContainer == null) throw new ArgumentNullException("unityContainer 
_unityContainer = unityContainer; 
} 
protected override IController GetControllerInstance(RequestContext requestContext 
controllerType) 
{ 
return (IController) _unityContainer.Resolve(controllerType); 
} 
} 
In CompositionRoot 
Register / Resolve (/ Release)
Aspects of DI 
• Composition 
• Lifetime Management 
• Interception
Interception 
• ~ Dynamic Decorators 
• Cross-cutting concerns 
– Logging 
– Auditing 
– Profiling … 
• AOP-like !
public class TimingBehavior : IInterceptionBehavior 
{ 
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext 
{ 
var stopwatch = new Stopwatch(); 
// Before invoking the method on the original target. 
Debug.WriteLine("> {0}.{1}", input.MethodBase.DeclaringType, input.MethodBase.Name); 
stopwatch.Start(); 
// Invoke the next behavior in the chain. 
var result = getNext()(input, getNext); 
stopwatch.Stop(); 
// After invoking the method on the original target. 
if (result.Exception != null) 
{ 
Debug.WriteLine( 
Call to decorated instance 
"< {0}.{1} failed - after {3} ms", 
input.MethodBase.DeclaringType, input.MethodBase.Name, result.Exception.GetType(), 
stopwatch.ElapsedMilliseconds); 
} 
else 
{ 
Debug.WriteLine("< {0}.{1} - after {2} ms", 
input.MethodBase.DeclaringType, input.MethodBase.Name, 
stopwatch.ElapsedMilliseconds); 
} 
Before each method call of decorated class 
After each method call 
public class DependencyConfig 
{ 
public static void Configure(IUnityContainer container) 
{ 
container.AddNewExtension<Interception>(); 
var connectionString = ConfigurationManager.ConnectionStrings["BankingDbContext"] 
.ConnectionString; 
container.RegisterType<IAccountRepository, AccountRepository>( 
new InjectionConstructor(connectionString), 
new Interceptor<InterfaceInterceptor>(), 
new InterceptionBehavior<TimingBehavior>()); 
container.RegisterType<IUserAccountService, UserAccountService>( 
new Interceptor<InterfaceInterceptor>(), 
new InterceptionBehavior<TimingBehavior>()); 
} 
}
TO CONCLUDE …
Things to remember 
• DI Patterns … 
– Don’t be a Control Freak 
– Constructor Injection is your friend 
– Compose you object graphs in one place 
– DI Containers are powerful but not magical 
• … can help you achieve loosely coupled code 
– Maintainable 
– Testable
Going further … 
• Mark Seemann’s book 
and blog posts 
– http://blog.ploeh.dk/ 
• Conversation about DI 
in aspnet vNext 
– http://forums.asp.net/t/1989008.aspx?Feedback+ 
on+ASP+NET+vNext+Dependency+Injection 
• SOLID principles
Shoot ! 
Q&A
Contact : @tsimbalar 
THANKS FOR ATTENDING !
You want more ? 
EXTRAS
Late-binding 
• Dynamically decide which implementation to 
protectuedsoeverride IController GetControllerInstance(RequestContext requestContext, 
Type controllerType) 
{ 
// how to compose an AccountController ? 
if (controllerType == typeof(AccountController)) 
{ 
var repo = LoadInstanceFromPluginFolder<IAccountRepository>(); 
Plugin scenarios – scan assemblies in a folder for implementations 
var service = new UserAccountService(repo); 
return new AccountController(service); 
} 
// standard way in MVC to use default strategy 
return base.GetControllerInstance(requestContext, controllerType);
LifeTime Management
anti-pattern : Service Locator
SOLID 
Single Responsibility Principle 
Open Closed Principle 
Liskov Substitution Principle 
Interface Segregation Principle 
Dependency Inversion Principe

More Related Content

What's hot

Dependency injection ppt
Dependency injection pptDependency injection ppt
Dependency injection ppt
Swati Srivastava
 
Spring boot
Spring bootSpring boot
Spring boot
Pradeep Shanmugam
 
Asp.net mvc
Asp.net mvcAsp.net mvc
Asp.net mvc
Er. Kamal Bhusal
 
Dependency injection
Dependency injectionDependency injection
Dependency injection
Mindfire Solutions
 
ASP.NET Core MVC + Web API with Overview
ASP.NET Core MVC + Web API with OverviewASP.NET Core MVC + Web API with Overview
ASP.NET Core MVC + Web API with Overview
Shahed Chowdhuri
 
Spring boot jpa
Spring boot jpaSpring boot jpa
Spring boot jpa
Hamid Ghorbani
 
Spring Boot
Spring BootSpring Boot
Spring Boot
Jiayun Zhou
 
Clean code slide
Clean code slideClean code slide
Clean code slide
Anh Huan Miu
 
Spring boot introduction
Spring boot introductionSpring boot introduction
Spring boot introduction
Rasheed Waraich
 
Modern Java web applications with Spring Boot and Thymeleaf
Modern Java web applications with Spring Boot and ThymeleafModern Java web applications with Spring Boot and Thymeleaf
Modern Java web applications with Spring Boot and Thymeleaf
LAY Leangsros
 
Node Architecture and Getting Started with Express
Node Architecture and Getting Started with ExpressNode Architecture and Getting Started with Express
Node Architecture and Getting Started with Express
jguerrero999
 
Spring beans
Spring beansSpring beans
Spring beans
Roman Dovgan
 
MVC Architecture in ASP.Net By Nyros Developer
MVC Architecture in ASP.Net By Nyros DeveloperMVC Architecture in ASP.Net By Nyros Developer
MVC Architecture in ASP.Net By Nyros Developer
Nyros Technologies
 
Introduction to Spring Boot
Introduction to Spring BootIntroduction to Spring Boot
Introduction to Spring Boot
Purbarun Chakrabarti
 
SOLID Principles and The Clean Architecture
SOLID Principles and The Clean ArchitectureSOLID Principles and The Clean Architecture
SOLID Principles and The Clean Architecture
Mohamed Galal
 
React js
React jsReact js
Spring Boot in Action
Spring Boot in Action Spring Boot in Action
Spring Boot in Action
Alex Movila
 
Introduction to spring boot
Introduction to spring bootIntroduction to spring boot
Introduction to spring boot
Santosh Kumar Kar
 
Spring - Part 1 - IoC, Di and Beans
Spring - Part 1 - IoC, Di and Beans Spring - Part 1 - IoC, Di and Beans
Spring - Part 1 - IoC, Di and Beans
Hitesh-Java
 
ASP.NET MVC Presentation
ASP.NET MVC PresentationASP.NET MVC Presentation
ASP.NET MVC Presentation
ivpol
 

What's hot (20)

Dependency injection ppt
Dependency injection pptDependency injection ppt
Dependency injection ppt
 
Spring boot
Spring bootSpring boot
Spring boot
 
Asp.net mvc
Asp.net mvcAsp.net mvc
Asp.net mvc
 
Dependency injection
Dependency injectionDependency injection
Dependency injection
 
ASP.NET Core MVC + Web API with Overview
ASP.NET Core MVC + Web API with OverviewASP.NET Core MVC + Web API with Overview
ASP.NET Core MVC + Web API with Overview
 
Spring boot jpa
Spring boot jpaSpring boot jpa
Spring boot jpa
 
Spring Boot
Spring BootSpring Boot
Spring Boot
 
Clean code slide
Clean code slideClean code slide
Clean code slide
 
Spring boot introduction
Spring boot introductionSpring boot introduction
Spring boot introduction
 
Modern Java web applications with Spring Boot and Thymeleaf
Modern Java web applications with Spring Boot and ThymeleafModern Java web applications with Spring Boot and Thymeleaf
Modern Java web applications with Spring Boot and Thymeleaf
 
Node Architecture and Getting Started with Express
Node Architecture and Getting Started with ExpressNode Architecture and Getting Started with Express
Node Architecture and Getting Started with Express
 
Spring beans
Spring beansSpring beans
Spring beans
 
MVC Architecture in ASP.Net By Nyros Developer
MVC Architecture in ASP.Net By Nyros DeveloperMVC Architecture in ASP.Net By Nyros Developer
MVC Architecture in ASP.Net By Nyros Developer
 
Introduction to Spring Boot
Introduction to Spring BootIntroduction to Spring Boot
Introduction to Spring Boot
 
SOLID Principles and The Clean Architecture
SOLID Principles and The Clean ArchitectureSOLID Principles and The Clean Architecture
SOLID Principles and The Clean Architecture
 
React js
React jsReact js
React js
 
Spring Boot in Action
Spring Boot in Action Spring Boot in Action
Spring Boot in Action
 
Introduction to spring boot
Introduction to spring bootIntroduction to spring boot
Introduction to spring boot
 
Spring - Part 1 - IoC, Di and Beans
Spring - Part 1 - IoC, Di and Beans Spring - Part 1 - IoC, Di and Beans
Spring - Part 1 - IoC, Di and Beans
 
ASP.NET MVC Presentation
ASP.NET MVC PresentationASP.NET MVC Presentation
ASP.NET MVC Presentation
 

Viewers also liked

Inversion of Control - Introduction and Best Practice
Inversion of Control - Introduction and Best PracticeInversion of Control - Introduction and Best Practice
Inversion of Control - Introduction and Best Practice
Lars-Erik Kindblad
 
Functional Dependency Injection in C#
Functional Dependency Injection in C#Functional Dependency Injection in C#
Functional Dependency Injection in C#
Thomas Jaskula
 
Clean Code II - Dependency Injection
Clean Code II - Dependency InjectionClean Code II - Dependency Injection
Clean Code II - Dependency Injection
Theo Jungeblut
 
IoC and Mapper in C#
IoC and Mapper in C#IoC and Mapper in C#
IoC and Mapper in C#
Huy Hoàng Phạm
 
Dependency Injection in .NET
Dependency Injection in .NETDependency Injection in .NET
Dependency Injection in .NET
Remik Koczapski
 
Dependency injection for beginners
Dependency injection for beginnersDependency injection for beginners
Dependency injection for beginners
Bhushan Mulmule
 
Dependency Injection with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3Dependency Injection with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3Fabien Potencier
 
Dependency Injection in Laravel
Dependency Injection in LaravelDependency Injection in Laravel
Dependency Injection in Laravel
HAO-WEN ZHANG
 
Dependency Injection And Ioc Containers
Dependency Injection And Ioc ContainersDependency Injection And Ioc Containers
Dependency Injection And Ioc Containers
Tim Murphy
 
Java Spring framework, Dependency Injection, DI, IoC, Inversion of Control
Java Spring framework, Dependency Injection, DI, IoC, Inversion of ControlJava Spring framework, Dependency Injection, DI, IoC, Inversion of Control
Java Spring framework, Dependency Injection, DI, IoC, Inversion of Control
Arjun Thakur
 
Functional programming in C#
Functional programming in C#Functional programming in C#
Functional programming in C#
Thomas Jaskula
 
Dependency injection with Symfony 2
Dependency injection with Symfony 2Dependency injection with Symfony 2
Dependency injection with Symfony 2
cammanderson
 
MVVM - Model View ViewModel
MVVM - Model View ViewModelMVVM - Model View ViewModel
MVVM - Model View ViewModel
Dareen Alhiyari
 
Javascript & Ajax Basics
Javascript & Ajax BasicsJavascript & Ajax Basics
Javascript & Ajax BasicsRichard Paul
 
Spring IOC and DAO
Spring IOC and DAOSpring IOC and DAO
Spring IOC and DAO
AnushaNaidu
 
EJB and CDI - Alignment and Strategy
EJB and CDI - Alignment and StrategyEJB and CDI - Alignment and Strategy
EJB and CDI - Alignment and Strategy
David Delabassee
 
System Integration with Akka and Apache Camel
System Integration with Akka and Apache CamelSystem Integration with Akka and Apache Camel
System Integration with Akka and Apache Camelkrasserm
 

Viewers also liked (20)

Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 
Inversion of Control - Introduction and Best Practice
Inversion of Control - Introduction and Best PracticeInversion of Control - Introduction and Best Practice
Inversion of Control - Introduction and Best Practice
 
Functional Dependency Injection in C#
Functional Dependency Injection in C#Functional Dependency Injection in C#
Functional Dependency Injection in C#
 
Clean Code II - Dependency Injection
Clean Code II - Dependency InjectionClean Code II - Dependency Injection
Clean Code II - Dependency Injection
 
IoC and Mapper in C#
IoC and Mapper in C#IoC and Mapper in C#
IoC and Mapper in C#
 
Dependency Injection in .NET
Dependency Injection in .NETDependency Injection in .NET
Dependency Injection in .NET
 
Dependency injection for beginners
Dependency injection for beginnersDependency injection for beginners
Dependency injection for beginners
 
Dependency Injection with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3Dependency Injection with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3
 
Dependency Injection in Laravel
Dependency Injection in LaravelDependency Injection in Laravel
Dependency Injection in Laravel
 
Dependency Injection And Ioc Containers
Dependency Injection And Ioc ContainersDependency Injection And Ioc Containers
Dependency Injection And Ioc Containers
 
Java Spring framework, Dependency Injection, DI, IoC, Inversion of Control
Java Spring framework, Dependency Injection, DI, IoC, Inversion of ControlJava Spring framework, Dependency Injection, DI, IoC, Inversion of Control
Java Spring framework, Dependency Injection, DI, IoC, Inversion of Control
 
Functional programming in C#
Functional programming in C#Functional programming in C#
Functional programming in C#
 
Dependency injection with Symfony 2
Dependency injection with Symfony 2Dependency injection with Symfony 2
Dependency injection with Symfony 2
 
MVVM - Model View ViewModel
MVVM - Model View ViewModelMVVM - Model View ViewModel
MVVM - Model View ViewModel
 
Javascript & Ajax Basics
Javascript & Ajax BasicsJavascript & Ajax Basics
Javascript & Ajax Basics
 
Hash map
Hash mapHash map
Hash map
 
Spring IOC and DAO
Spring IOC and DAOSpring IOC and DAO
Spring IOC and DAO
 
EJB and CDI - Alignment and Strategy
EJB and CDI - Alignment and StrategyEJB and CDI - Alignment and Strategy
EJB and CDI - Alignment and Strategy
 
System Integration with Akka and Apache Camel
System Integration with Akka and Apache CamelSystem Integration with Akka and Apache Camel
System Integration with Akka and Apache Camel
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 

Similar to Dependency injection - the right way

Cbsecomputersciencecclass12boardproject bankmanagmentsystem-180703065625-conv...
Cbsecomputersciencecclass12boardproject bankmanagmentsystem-180703065625-conv...Cbsecomputersciencecclass12boardproject bankmanagmentsystem-180703065625-conv...
Cbsecomputersciencecclass12boardproject bankmanagmentsystem-180703065625-conv...
sriram sarwan
 
Jasigsakai12 columbia-customizes-cas
Jasigsakai12 columbia-customizes-casJasigsakai12 columbia-customizes-cas
Jasigsakai12 columbia-customizes-casellentuck
 
Introduction to Domain driven design (LaravelBA #5)
Introduction to Domain driven design (LaravelBA #5)Introduction to Domain driven design (LaravelBA #5)
Introduction to Domain driven design (LaravelBA #5)
guiwoda
 
Building the an End-to-End ASP.NET MVC 4, Entity Framework, HTML5, jQuery app...
Building the an End-to-End ASP.NET MVC 4, Entity Framework, HTML5, jQuery app...Building the an End-to-End ASP.NET MVC 4, Entity Framework, HTML5, jQuery app...
Building the an End-to-End ASP.NET MVC 4, Entity Framework, HTML5, jQuery app...
Dan Wahlin
 
Cbse computer science (c++) class 12 board project bank managment system
Cbse computer science (c++)  class 12 board project  bank managment systemCbse computer science (c++)  class 12 board project  bank managment system
Cbse computer science (c++) class 12 board project bank managment system
pranoy_seenu
 
Apex Enterprise Patterns: Building Strong Foundations
Apex Enterprise Patterns: Building Strong FoundationsApex Enterprise Patterns: Building Strong Foundations
Apex Enterprise Patterns: Building Strong Foundations
Salesforce Developers
 
Yii Introduction
Yii IntroductionYii Introduction
Yii Introduction
Jason Ragsdale
 
A Unified View of Modeling and Programming
A Unified View of Modeling and ProgrammingA Unified View of Modeling and Programming
A Unified View of Modeling and Programming
Ed Seidewitz
 
Redux. From twitter hype to production
Redux. From twitter hype to productionRedux. From twitter hype to production
Redux. From twitter hype to production
Jenya Terpil
 
Redux. From twitter hype to production
Redux. From twitter hype to productionRedux. From twitter hype to production
Redux. From twitter hype to production
FDConf
 
Developing ASP.NET Applications Using the Model View Controller Pattern
Developing ASP.NET Applications Using the Model View Controller PatternDeveloping ASP.NET Applications Using the Model View Controller Pattern
Developing ASP.NET Applications Using the Model View Controller Pattern
goodfriday
 
ELEVATE Paris
ELEVATE ParisELEVATE Paris
ELEVATE Paris
Peter Chittum
 
Paul Lammertsma: Account manager & sync
Paul Lammertsma: Account manager & syncPaul Lammertsma: Account manager & sync
Paul Lammertsma: Account manager & sync
mdevtalk
 
1-What are the opportunities and threats that could impact the org
1-What are the opportunities and threats that could impact the org1-What are the opportunities and threats that could impact the org
1-What are the opportunities and threats that could impact the org
AbbyWhyte974
 
1-What are the opportunities and threats that could impact the org
1-What are the opportunities and threats that could impact the org1-What are the opportunities and threats that could impact the org
1-What are the opportunities and threats that could impact the org
MartineMccracken314
 
From CRUD to messages: a true story
From CRUD to messages: a true storyFrom CRUD to messages: a true story
From CRUD to messages: a true story
Alessandro Melchiori
 
Refatorando com a API funcional do Java
Refatorando com a API funcional do JavaRefatorando com a API funcional do Java
Refatorando com a API funcional do Java
Giovane Liberato
 
Asp.NET MVC
Asp.NET MVCAsp.NET MVC
Asp.NET MVC
vrluckyin
 
SQL Server 2008 Portfolio
SQL Server 2008 PortfolioSQL Server 2008 Portfolio
SQL Server 2008 Portfolio
anthonyfeliciano
 

Similar to Dependency injection - the right way (20)

Cbsecomputersciencecclass12boardproject bankmanagmentsystem-180703065625-conv...
Cbsecomputersciencecclass12boardproject bankmanagmentsystem-180703065625-conv...Cbsecomputersciencecclass12boardproject bankmanagmentsystem-180703065625-conv...
Cbsecomputersciencecclass12boardproject bankmanagmentsystem-180703065625-conv...
 
Jasigsakai12 columbia-customizes-cas
Jasigsakai12 columbia-customizes-casJasigsakai12 columbia-customizes-cas
Jasigsakai12 columbia-customizes-cas
 
Introduction to Domain driven design (LaravelBA #5)
Introduction to Domain driven design (LaravelBA #5)Introduction to Domain driven design (LaravelBA #5)
Introduction to Domain driven design (LaravelBA #5)
 
Building the an End-to-End ASP.NET MVC 4, Entity Framework, HTML5, jQuery app...
Building the an End-to-End ASP.NET MVC 4, Entity Framework, HTML5, jQuery app...Building the an End-to-End ASP.NET MVC 4, Entity Framework, HTML5, jQuery app...
Building the an End-to-End ASP.NET MVC 4, Entity Framework, HTML5, jQuery app...
 
Cbse computer science (c++) class 12 board project bank managment system
Cbse computer science (c++)  class 12 board project  bank managment systemCbse computer science (c++)  class 12 board project  bank managment system
Cbse computer science (c++) class 12 board project bank managment system
 
Apex Enterprise Patterns: Building Strong Foundations
Apex Enterprise Patterns: Building Strong FoundationsApex Enterprise Patterns: Building Strong Foundations
Apex Enterprise Patterns: Building Strong Foundations
 
Yii Introduction
Yii IntroductionYii Introduction
Yii Introduction
 
A Unified View of Modeling and Programming
A Unified View of Modeling and ProgrammingA Unified View of Modeling and Programming
A Unified View of Modeling and Programming
 
Jsf intro
Jsf introJsf intro
Jsf intro
 
Redux. From twitter hype to production
Redux. From twitter hype to productionRedux. From twitter hype to production
Redux. From twitter hype to production
 
Redux. From twitter hype to production
Redux. From twitter hype to productionRedux. From twitter hype to production
Redux. From twitter hype to production
 
Developing ASP.NET Applications Using the Model View Controller Pattern
Developing ASP.NET Applications Using the Model View Controller PatternDeveloping ASP.NET Applications Using the Model View Controller Pattern
Developing ASP.NET Applications Using the Model View Controller Pattern
 
ELEVATE Paris
ELEVATE ParisELEVATE Paris
ELEVATE Paris
 
Paul Lammertsma: Account manager & sync
Paul Lammertsma: Account manager & syncPaul Lammertsma: Account manager & sync
Paul Lammertsma: Account manager & sync
 
1-What are the opportunities and threats that could impact the org
1-What are the opportunities and threats that could impact the org1-What are the opportunities and threats that could impact the org
1-What are the opportunities and threats that could impact the org
 
1-What are the opportunities and threats that could impact the org
1-What are the opportunities and threats that could impact the org1-What are the opportunities and threats that could impact the org
1-What are the opportunities and threats that could impact the org
 
From CRUD to messages: a true story
From CRUD to messages: a true storyFrom CRUD to messages: a true story
From CRUD to messages: a true story
 
Refatorando com a API funcional do Java
Refatorando com a API funcional do JavaRefatorando com a API funcional do Java
Refatorando com a API funcional do Java
 
Asp.NET MVC
Asp.NET MVCAsp.NET MVC
Asp.NET MVC
 
SQL Server 2008 Portfolio
SQL Server 2008 PortfolioSQL Server 2008 Portfolio
SQL Server 2008 Portfolio
 

Recently uploaded

Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
Max Andersen
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
Rakesh Kumar R
 
Artificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension FunctionsArtificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension Functions
Octavian Nadolu
 
GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
Neo4j
 
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of CodeA Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
Aftab Hussain
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
Adele Miller
 
Graspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code AnalysisGraspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code Analysis
Aftab Hussain
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Łukasz Chruściel
 
AI Genie Review: World’s First Open AI WordPress Website Creator
AI Genie Review: World’s First Open AI WordPress Website CreatorAI Genie Review: World’s First Open AI WordPress Website Creator
AI Genie Review: World’s First Open AI WordPress Website Creator
Google
 
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdfAutomated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
timtebeek1
 
OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024
OpenMetadata
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
Shane Coughlan
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOMLORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
lorraineandreiamcidl
 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
Ayan Halder
 
Launch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in MinutesLaunch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in Minutes
Roshan Dwivedi
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
Drona Infotech
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Crescat
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
NYGGS Automation Suite
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
Łukasz Chruściel
 
E-commerce Application Development Company.pdf
E-commerce Application Development Company.pdfE-commerce Application Development Company.pdf
E-commerce Application Development Company.pdf
Hornet Dynamics
 

Recently uploaded (20)

Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
 
Artificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension FunctionsArtificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension Functions
 
GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
 
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of CodeA Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
 
Graspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code AnalysisGraspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code Analysis
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
 
AI Genie Review: World’s First Open AI WordPress Website Creator
AI Genie Review: World’s First Open AI WordPress Website CreatorAI Genie Review: World’s First Open AI WordPress Website Creator
AI Genie Review: World’s First Open AI WordPress Website Creator
 
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdfAutomated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
 
OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOMLORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
 
Launch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in MinutesLaunch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in Minutes
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
 
E-commerce Application Development Company.pdf
E-commerce Application Development Company.pdfE-commerce Application Development Company.pdf
E-commerce Application Development Company.pdf
 

Dependency injection - the right way

  • 2. Dependency Injection, the right way Thibaud DESODT @tsimbalar
  • 3. This talk • What it is about – Dependency Injection (DI) patterns – Benefits – Common pitfalls • What it is not about – Specific IoC/DI Container implementations • Pre-requisites – OOP – Class-based statically-typed languages • Based on examples
  • 4.
  • 5. What ? DEPENDENCY INJECTION
  • 6. Dependency Injection Dependency Injection is a set of practices that allow to build loosely coupled applications
  • 7. Dependency Injection Dependency Injection is a set of practices that allow to build loosely coupled applications It’s NOT : – A library – A framework – A tool It IS : - A way of thinking - A way of designing code - General guidelines
  • 8. Dependency Injection Dependency Injection is a set of practices that allow to build loosely coupled applications Small components … - Independent - Reusable - Interchangeable … plugged together to form a bigger system Benefits : - Small classes with single responsibility - Easier maintenance - Extensibility - Testable
  • 9. Show me the code ! FROM TIGHTLY TO LOOSELY COUPLED
  • 10. Example : Boring Bank™ System • Features – User can list his accounts – User can rename his accounts – User can transfer money from an account to the other • Tech : – Web front-end – Relational database
  • 11. Starting from scratch public class AccountController : BaseController { // GET: Account [HttpGet] public ActionResult Index() { var userId = this.User.AsClaimsPrincipal().UserId(); using (var context = new BankingDbContext()) { var accounts = context.Accounts .Where(a => a.CustomerId == userId) .OrderBy(a => a.Title).ToList(); return View(accounts); } } [HttpPost] public ActionResult TransferPost(int from, int to, decimal amount) { var userId = this.User.AsClaimsPrincipal().UserId(); using (var context = new BankingDbContext()) { var accountFrom = context.Accounts .Single(a => a.CustomerId == userId && a.Id == from); var accountTo = context.Accounts .Single(a => a.CustomerId == userId && a.Id == to); accountFrom.Balance -= amount; accountTo.Balance += amount; context.SaveChanges(); return RedirectToAction("Index"); } } data business presentation
  • 12. Tightly-coupled code • Using another kind of UI ? • Using another kind of storage ? • Using the business rules somewhere else ?
  • 13. Separation of Concerns • Layered architecture / split assemblies – Presentation – Business – Data-access (Repository) • Separated : – Persistence Entities – Domain Entities – View Models
  • 14. public class AccountController : BaseController public Account GetAccountForCustomer(int customerId, int accountId) { // GET: Account [HttpGet] public ActionResult Index() { var userId = this.User.AsClaimsPrincipal().UserId(); public void Transfer(int userId, int fromAccountId, int toAccountId, decimal amountToTransfer var userAccountService = new UserAccountService(); var accounts = userAccountService.GetAccountsForCustomer(userId); return View(ToViewModel(accounts)); } [HttpPost] public ActionResult TransferPost(int from, int to, decimal amount) { var userId = this.User.AsClaimsPrincipal().UserId(); var userAccountService = new UserAccountService(); userAccountService.Transfer(userId, from, to, amount); return RedirectToAction("Index"); } AccountController.cs (WebPortal) UI talks to Business { // TODO : validate arguments var accountRepository = new AccountRepository(); var fromAccount = accountRepository.GetAccountForCustomer(userId, fromAccountId); var toAccount = accountRepository.GetAccountForCustomer(userId, toAccountId); // TODO : verify that there is enough money fromAccount.Balance -= amountToTransfer; toAccount.Balance += amountToTransfer; accountRepository.Update(fromAccount); accountRepository.Update(toAccount); } UserAccountService.cs (Business) Business talks to Data { using (var context = new BankingDbContext("BankingDbContext")) { var account = context.Accounts .Single(a => a.CustomerId == customerId && a.Id == accountId); return account; } } public void Update(Account account) { using (var context = new BankingDbContext("BankingDbContext")) { var accountEf = context.Accounts.Find(account.Id); // theoretically, could do "if not changed" accountEf.Balance = account.Balance; accountEf.Title = account.Title; context.SaveChanges(); } } AccountRepository.cs (Data)
  • 15. That looks fine … but is it ?
  • 16. anti-pattern : Control Freak • Symptoms: – Code insists on how the dependencies are built – Makes it impossible to use component in isolation – Not testable without full stack • Easy to spot : new everywhere AccountController : BaseController Account HttpGet] ActionResult Index() userId = this.User.AsClaimsPrincipal().UserId(); userAccountService = new UserAccountService(); accounts = userAccountService.GetAccountsForCustomer(userId); return View(ToViewModel(accounts)); public void Transfer(int userId, int fromAccountId, int toAccountId { // TODO : validate arguments var accountRepository = new AccountRepository(); var fromAccount = accountRepository.GetAccountForCustomer var toAccount = accountRepository.GetAccountForCustomer // TODO : verify that there is enough money fromAccount.Balance -= amountToTransfer; toAccount.Balance += amountToTransfer; accountRepository.Update(fromAccount); accountRepository.Update(toAccount); }
  • 17. Unit tests as a Coupling Detector • Unit tests are “just another client” for your code • If unit tests are hard to write, the code is probably too tightly coupled -> Let’s make it testable !
  • 18. Making it testable - Properties public class UserAccountService { [TestMethod] public void RenameAccount_must_UpdateAccountName() { public UserAccountService() { AccountRepository = new AccountRepository("BankingContext"); } #region Dependency Management public AccountRepository AccountRepository { get; set; } #endregion Settable property allows to “inject” another instance // Arrange var newName = "someName"; var existingAccount = AnAccount(); var sut = new UserAccountService(); sut.AccountRepository = FAIL FAIL//I want to put a fake here ! // Act sut.RenameAccount(existingAccount.CustomerId, existingAccount.Id, newName); // Assert // I want to verify what happened .. } In UserAccountServiceTest.cs , in test project Business.Tests
  • 19. Programming to an interface public class UserAccountService : IUserAccountService [TestMethod] { public void RenameAccount_must_UpdateAccountName() { public UserAccountService() { // Arrange var newName = "someName"; AccountRepository = new AccountRepository("BankingContext"); } var existingAccount = AnAccount(); #region Dependency Management var mockRepo = new Mock<IAccountRepository>(); mockRepo.Setup(r => r.GetAccountForCustomer(It.IsAny<int>(), It.IsAny<int>())) public IAccountRepository AccountRepository { get; set; } .Returns(existingAccount); var sut = new UserAccountService(); sut.AccountRepository = mockRepo.Object; //I want to put a fake here ! #endregion Use an interface (or abstract class) instead of concrete class // Act sut.RenameAccount(existingAccount.CustomerId, existingAccount.Id, newName); // Assert mockRepo.Verify(r=> r.Update(It.Is<Data.Account>(a=> a.Title == newName))); } Inject fake instance
  • 20. pattern : Property Injection Expose settable properties to modify dependencies Benefits • Useful to provide optional extensibility • There must be a good “local default” implementation Caveats • Not very easy to discover point of extension • Easy to forget • Extra care to avoid NullReferenceExceptions, handle thread-safety etc
  • 21. Making it more explicit - Constructor public class UserAccountService : IUserAccountService { private readonly IAccountRepository _accountRepository; Injection constructor used in tests - declare required dependencies as constructor parameters public UserAccountService(IAccountRepository accountRepository) { public IAccountRepository AccountRepository { get { return _accountRepository; if (accountRepository == null) throw new ArgumentNullException("accountRepository _accountRepository = accountRepository; } public UserAccountService() :this(new AccountRepository("BankingContext")) { } #region Dependency Management Default constructor used in production code [TestMethod] public void RenameAccount_must_UpdateAccountName() { // Arrange var newName = "someName"; var existingAccount = AnAccount(); var mockRepo = new Mock<IAccountRepository>(); mockRepo.Setup(r => r.GetAccountForCustomer(It.IsAny<int>(), It.IsAny<int>())) .Returns(existingAccount); var sut = new UserAccountService(mockRepo.Object); // Act sut.RenameAccount(existingAccount.CustomerId, existingAccount.Id, newName); // Assert mockRepo.Verify(r=> r.Update(It.Is<Data.Account>(a=> a.Title == newName))); } Inject fake instance
  • 22. anti-pattern : Bastard Injection Enable dependencies for testing, but use hard-code implementation in production code • Paradox: – Lots of efforts to reduce coupling – … but forcing a hard-coded value • Test-specific code • Ambiguity
  • 23. Cutting the dependency chain public class AccountController : BaseController { private readonly IUserAccountService _userAccountService; public class UserAccountService : IUserAccountService Only 1 constructor - dependencies passed as constructor arguments { public private AccountController(readonly IAccountRepository IUserAccountService _accountRepository; userAccountService) { if (userAccountService == null) throw new ArgumentNullException("userAccountService _userAccountService = userAccountService; } public UserAccountService(IAccountRepository accountRepository) { if (accountRepository == null) throw new ArgumentNullException("accountRepository _accountRepository = accountRepository; AccountController (WebPortal) } UserAccountService.cs (Business)
  • 24. pattern : Constructor Injection Declare required dependencies as constructor parameters • Declarative • Discoverable (Intellisense, Reflection …) • Recommended approach in 99.9% of cases • Easy to implement Need Guard clause because C# does not support non-nullable reference types …
  • 26. This is great and everything except … [InvalidOperationException: An error occurred when trying to create a controller of 'BoringBank.WebPortal.Controllers.AccountController'. Make sure that the controller System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext
  • 27. The chicken and the egg IAccountRepository repo = new IAccountRepository(); • Ideal world: Programming to interfaces vs • Real world : applications do not work with only interfaces • Class instances have to be created and assembled (=composed) at some point • This happens only in one place in an application
  • 28. pattern : Composition Root Composition of classes into a larger system should happen only in one place • Create one object-graph • As late as possible • Only part of the code that can reference concrete types Where ? • Only applications have a Composition Root • There is no Composition Root in a class library • Extension point depends on the kind of app
  • 29. ASP.NET MVC Composition Root public class AppCompositionRoot : DefaultControllerFactory • IControllerFactory • Creates a controller instance based on URL • DefaultControllerFactory uses default constructor on Controller • … but it can be changed ! { protected override IController GetControllerInstance(RequestContext requestContext Type controllerType) { // how to compose an AccountController ? if (controllerType == typeof(AccountController)) { var connectionString = ConfigurationManager .ConnectionStrings["BankingDbContext"].ConnectionString; var repo = new AccountRepository(connectionString); var service = new UserAccountService(repo); return new AccountController(service); Controller composition } // standard way in MVC to use default strategy return base.GetControllerInstance(requestContext, controllerType); } } public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { var factory = new AppCompositionRoot(); ControllerBuilder.Current.SetControllerFactory(factory); In Global.asax tell MVC to use our composition root
  • 30. Pure DI (aka Poor Man’s DI) Manual wiring of dependencies • Very explicit (no « magic ») • Type-safe • … but repetitive and boring var connectionString = ConfigurationManager .ConnectionStrings["BankingDbContext"].ConnectionString; var repo = new AccountRepository(connectionString); var service = new UserAccountService(repo); return new AccountController(service);
  • 31. And we did that because … ? SO WHAT ?
  • 32. Benefits of full DI-friendly codebase • Testability • Maintainability • Allows parallel work • … and more ! • Defined in a centralized location
  • 33. Reusability / Extensibility or CLI or WPF or Web API or WCF … or files or NoSQL or Azure or Http Client …
  • 34. Extensibility public class CachedAccountRepository : IAccountRepository { private readonly ICache _cache; private readonly IAccountRepository _decorated; • Decorator Pattern public CachedAccountRepository(ICache cache, IAccountRepository decorated) { – Very DI-friendly pattern var nakedRepo = new AccountRepository(connectionString); if (cache == null) throw new ArgumentNullException("cache"); if (decorated == null) throw new ArgumentNullException("decorated"); _cache = cache; _decorated = decorated; // decorate the nakedRepository with caching features var • Example longCache = : new caching DotNetCache(TimeSpan.FromHours(1)); var cachedRepo = new CachedAccountRepository(longCache, nakedRepo); var service } = new UserAccountService(cachedRepo); public IReadOnlyList<Account> GetAccountsForCustomer(int userId) { var accounts = _cache.GetOrAdd("accounts_" + userId, () => _decorated.GetAccountsForCustomer(userId)); return accounts; } Decorator delegate to decorated instance
  • 36. DI Container – how they work • Mapping Abstraction-> Concrete Type – Usually initialized on app start – Methods like Register<IAbstraction,ConcreteType>() • Method Resolve<TRequired>() • Recursively resolves dependencies reading constructor parameters
  • 37. public class DependencyConfig Example - Unity { public static void Configure(IUnityContainer container) { var connectionString = ConfigurationManager.ConnectionStrings["BankingDbContext" public class MvcApplication : System.Web.HttpApplication { public class AppCompositionRoot : DefaultControllerFactory protected void Application_Start() { private readonly IUnityContainer _unityContainer; var container = new UnityContainer(); DependencyConfig.Configure(container); var compositionRoot = new AppCompositionRoot(container); ControllerBuilder.Current.SetControllerFactory(compositionRoot { In Global.asax .ConnectionString; container.RegisterType<IAccountRepository, AccountRepository>( new InjectionConstructor(connectionString)); container.RegisterType<IUserAccountService, UserAccountService>(); } } public AppCompositionRoot(IUnityContainer unityContainer) { In DependencyConfig if (unityContainer == null) throw new ArgumentNullException("unityContainer _unityContainer = unityContainer; } protected override IController GetControllerInstance(RequestContext requestContext controllerType) { return (IController) _unityContainer.Resolve(controllerType); } } In CompositionRoot Register / Resolve (/ Release)
  • 38. Aspects of DI • Composition • Lifetime Management • Interception
  • 39. Interception • ~ Dynamic Decorators • Cross-cutting concerns – Logging – Auditing – Profiling … • AOP-like !
  • 40. public class TimingBehavior : IInterceptionBehavior { public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext { var stopwatch = new Stopwatch(); // Before invoking the method on the original target. Debug.WriteLine("> {0}.{1}", input.MethodBase.DeclaringType, input.MethodBase.Name); stopwatch.Start(); // Invoke the next behavior in the chain. var result = getNext()(input, getNext); stopwatch.Stop(); // After invoking the method on the original target. if (result.Exception != null) { Debug.WriteLine( Call to decorated instance "< {0}.{1} failed - after {3} ms", input.MethodBase.DeclaringType, input.MethodBase.Name, result.Exception.GetType(), stopwatch.ElapsedMilliseconds); } else { Debug.WriteLine("< {0}.{1} - after {2} ms", input.MethodBase.DeclaringType, input.MethodBase.Name, stopwatch.ElapsedMilliseconds); } Before each method call of decorated class After each method call public class DependencyConfig { public static void Configure(IUnityContainer container) { container.AddNewExtension<Interception>(); var connectionString = ConfigurationManager.ConnectionStrings["BankingDbContext"] .ConnectionString; container.RegisterType<IAccountRepository, AccountRepository>( new InjectionConstructor(connectionString), new Interceptor<InterfaceInterceptor>(), new InterceptionBehavior<TimingBehavior>()); container.RegisterType<IUserAccountService, UserAccountService>( new Interceptor<InterfaceInterceptor>(), new InterceptionBehavior<TimingBehavior>()); } }
  • 42. Things to remember • DI Patterns … – Don’t be a Control Freak – Constructor Injection is your friend – Compose you object graphs in one place – DI Containers are powerful but not magical • … can help you achieve loosely coupled code – Maintainable – Testable
  • 43. Going further … • Mark Seemann’s book and blog posts – http://blog.ploeh.dk/ • Conversation about DI in aspnet vNext – http://forums.asp.net/t/1989008.aspx?Feedback+ on+ASP+NET+vNext+Dependency+Injection • SOLID principles
  • 45. Contact : @tsimbalar THANKS FOR ATTENDING !
  • 46. You want more ? EXTRAS
  • 47. Late-binding • Dynamically decide which implementation to protectuedsoeverride IController GetControllerInstance(RequestContext requestContext, Type controllerType) { // how to compose an AccountController ? if (controllerType == typeof(AccountController)) { var repo = LoadInstanceFromPluginFolder<IAccountRepository>(); Plugin scenarios – scan assemblies in a folder for implementations var service = new UserAccountService(repo); return new AccountController(service); } // standard way in MVC to use default strategy return base.GetControllerInstance(requestContext, controllerType);
  • 50. SOLID Single Responsibility Principle Open Closed Principle Liskov Substitution Principle Interface Segregation Principle Dependency Inversion Principe

Editor's Notes

  1. Present you self
  2. Talk about Dependency Injection Dependency Injection patterns You may know about it under a form or another, or ay have used tools Who has ? You must unlearn ! Need to understand the philosophy and concepts in order to use the tools properly It’s easy to misuse the tools and miss some benefits
  3. There is no magic !
  4. Let’s see … Inside a controller Creating a dbcontext (Entity Framework) … imagine if that was ADO .NET Selecting a few things Passing it to the view… Has anybody ever written code like that ? That’s only a read page … imagine action with side effects… Simplified, no error handling whatsoever You may argue that it is loosely coupled … there’s only one class … but what a class !
  5. Turned spaghetti into lasagna 
  6. Business depends on Data layer … it should be an implementation detail Presentation depends on Business which depends on Data … which depends on EF … we’ll see that a bit later But mostly about using components in isolation … this is not testable right now
  7. Comment : First encounter with need for loosely coupled code came from unit tests Who write unit tests here ? Anybody who writes unit tests first ? First encounter where you code MUST BE loosely coupled : unit tests ! Actually consume components out of the scope of the application Tightly coupled code is hard to test or not testable at all … if it’s testable it’s not too tightly coupled
  8. Interface of abstract class …. I can’t do new I….. The closest we can get is this …. Note that even though we introduced interfaces, we still have a hard reference between all projects
  9. Used in default Visual Studio Template for MVC apps until not so long ago
  10. Comment about moving the interface into business Where to put the interface ? Separate project “Abstractions” ? The consumer owns the interface
  11. If you remember one thing, it’s that !
  12. Top down
  13. Can be done with Adapter pattern
  14. Traditionnal approach would be : Modify code Subclass..