SlideShare une entreprise Scribd logo
1  sur  50
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

Contenu connexe

Tendances

Spring boot introduction
Spring boot introductionSpring boot introduction
Spring boot introductionRasheed Waraich
 
Java EE Introduction
Java EE IntroductionJava EE Introduction
Java EE Introductionejlp12
 
ASP.NET MVC Presentation
ASP.NET MVC PresentationASP.NET MVC Presentation
ASP.NET MVC Presentationivpol
 
Dependency injection presentation
Dependency injection presentationDependency injection presentation
Dependency injection presentationAhasanul Kalam Akib
 
Spring Boot in Action
Spring Boot in Action Spring Boot in Action
Spring Boot in Action Alex Movila
 
Spring Framework
Spring Framework  Spring Framework
Spring Framework tola99
 
Introduction to Spring Framework
Introduction to Spring FrameworkIntroduction to Spring Framework
Introduction to Spring Framework Serhat Can
 
What is Dependency Injection in Spring Boot | Edureka
What is Dependency Injection in Spring Boot | EdurekaWhat is Dependency Injection in Spring Boot | Edureka
What is Dependency Injection in Spring Boot | EdurekaEdureka!
 
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 OverviewShahed Chowdhuri
 

Tendances (20)

Spring boot introduction
Spring boot introductionSpring boot introduction
Spring boot introduction
 
Java EE Introduction
Java EE IntroductionJava EE Introduction
Java EE Introduction
 
ASP.NET MVC Presentation
ASP.NET MVC PresentationASP.NET MVC Presentation
ASP.NET MVC Presentation
 
Dependency injection presentation
Dependency injection presentationDependency injection presentation
Dependency injection presentation
 
Spring Boot
Spring BootSpring Boot
Spring Boot
 
Spring data jpa
Spring data jpaSpring data jpa
Spring data jpa
 
Model View Controller (MVC)
Model View Controller (MVC)Model View Controller (MVC)
Model View Controller (MVC)
 
Java Spring Framework
Java Spring FrameworkJava Spring Framework
Java Spring Framework
 
Spring Boot
Spring BootSpring Boot
Spring Boot
 
Spring Boot
Spring BootSpring Boot
Spring Boot
 
Spring boot jpa
Spring boot jpaSpring boot jpa
Spring boot jpa
 
Spring Framework
Spring FrameworkSpring Framework
Spring Framework
 
Introduction to spring boot
Introduction to spring bootIntroduction to spring boot
Introduction to spring boot
 
Spring Boot in Action
Spring Boot in Action Spring Boot in Action
Spring Boot in Action
 
Spring Framework
Spring Framework  Spring Framework
Spring Framework
 
Introduction to Spring Framework
Introduction to Spring FrameworkIntroduction to Spring Framework
Introduction to Spring Framework
 
Spring mvc
Spring mvcSpring mvc
Spring mvc
 
Spring framework core
Spring framework coreSpring framework core
Spring framework core
 
What is Dependency Injection in Spring Boot | Edureka
What is Dependency Injection in Spring Boot | EdurekaWhat is Dependency Injection in Spring Boot | Edureka
What is Dependency Injection in Spring Boot | Edureka
 
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
 

En vedette

Inversion of Control and Dependency Injection
Inversion of Control and Dependency InjectionInversion of Control and Dependency Injection
Inversion of Control and Dependency InjectionDinesh Sharma
 
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 PracticeLars-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 InjectionTheo Jungeblut
 
Dependency Injection in .NET
Dependency Injection in .NETDependency Injection in .NET
Dependency Injection in .NETRemik Koczapski
 
Dependency injection for beginners
Dependency injection for beginnersDependency injection for beginners
Dependency injection for beginnersBhushan 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
 
Introduction to Spring's Dependency Injection
Introduction to Spring's Dependency InjectionIntroduction to Spring's Dependency Injection
Introduction to Spring's Dependency InjectionRichard Paul
 
Dependency Injection in Laravel
Dependency Injection in LaravelDependency Injection in Laravel
Dependency Injection in LaravelHAO-WEN ZHANG
 
Dependency Injection And Ioc Containers
Dependency Injection And Ioc ContainersDependency Injection And Ioc Containers
Dependency Injection And Ioc ContainersTim 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 ControlArjun Thakur
 
Functional programming in C#
Functional programming in C#Functional programming in C#
Functional programming in C#Thomas Jaskula
 
Dependency injection and inversion
Dependency injection and inversionDependency injection and inversion
Dependency injection and inversionchhabraravish23
 
Dependency injection with Symfony 2
Dependency injection with Symfony 2Dependency injection with Symfony 2
Dependency injection with Symfony 2cammanderson
 
MVVM - Model View ViewModel
MVVM - Model View ViewModelMVVM - Model View ViewModel
MVVM - Model View ViewModelDareen 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 DAOAnushaNaidu
 

En vedette (20)

Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 
Inversion of Control and Dependency Injection
Inversion of Control and Dependency InjectionInversion of Control and Dependency Injection
Inversion of Control and 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
 
Introduction to Spring's Dependency Injection
Introduction to Spring's Dependency InjectionIntroduction to Spring's Dependency Injection
Introduction to Spring's Dependency Injection
 
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 and inversion
Dependency injection and inversionDependency injection and inversion
Dependency injection and inversion
 
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
 

Similaire à 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 systempranoy_seenu
 
Apex Enterprise Patterns: Building Strong Foundations
Apex Enterprise Patterns: Building Strong FoundationsApex Enterprise Patterns: Building Strong Foundations
Apex Enterprise Patterns: Building Strong FoundationsSalesforce Developers
 
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 ProgrammingEd Seidewitz
 
Redux. From twitter hype to production
Redux. From twitter hype to productionRedux. From twitter hype to production
Redux. From twitter hype to productionJenya Terpil
 
Redux. From twitter hype to production
Redux. From twitter hype to productionRedux. From twitter hype to production
Redux. From twitter hype to productionFDConf
 
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 Patterngoodfriday
 
Paul Lammertsma: Account manager & sync
Paul Lammertsma: Account manager & syncPaul Lammertsma: Account manager & sync
Paul Lammertsma: Account manager & syncmdevtalk
 
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 orgAbbyWhyte974
 
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 orgMartineMccracken314
 
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 storyAlessandro 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 JavaGiovane Liberato
 

Similaire à 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
 

Dernier

5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...OnePlan Solutions
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfCionsystems
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
Clustering techniques data mining book ....
Clustering techniques data mining book ....Clustering techniques data mining book ....
Clustering techniques data mining book ....ShaimaaMohamedGalal
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsAndolasoft Inc
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️anilsa9823
 

Dernier (20)

Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdf
 
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
Clustering techniques data mining book ....
Clustering techniques data mining book ....Clustering techniques data mining book ....
Clustering techniques data mining book ....
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
 

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

Notes de l'éditeur

  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..