430 likes | 596 Views
Inversion Of Control & Dependency Injection. Break Apart The Dependencies. Oren Eini Senior Developer We! Consulting Group http://www.ayende.com/Blog/. Who wants to try to move that?. What can we do about it?. Who am I and what I do?. Senior Developer at We!
E N D
Inversion Of Control& Dependency Injection Break Apart The Dependencies Oren Eini Senior Developer We! Consulting Group http://www.ayende.com/Blog/
Who am I and what I do? • Senior Developer at We! • Mostly dealing with complex business applications • 100% of current projects using IoC • Blogger - ~95,000 visits / month • Object Relational Mapping • Inversion Of Control • Model View Controller architectures for the web • Various Development topics LazyDeveloper
What it is – Architecture? • Decreased Coupling • Greater Flexibility • Separation of Concerns • Interface Driven Design • Dependency Management (via Dependency Injection or Service Lookup) • Component Oriented Programming
What is it – Technology? • (Very) smart factory • Automatic resolving and injection of dependencies
A bit about terminology • Container • Service / Component • Inversion of Control • Dependency Injection
What is the problem we are trying to solve? • To understand the solution, we need to understand what the problem is…
Client Code Customercustomer = newCustomer("Fred"); CoupledPizzaPlacepizzaPlace = newCoupledPizzaPlace(); pizzaPlace.MakeOrder(customer,3);
Clerk knows about cook • Deliveries service knows about clerk • Cook knows about clerk Coupled Pizza Place Help the cook trade jobs. Help the clerk take vacation.
Just put some interfaces… Decoupled Pizza Place
Decoupled Client Code Ovenoven = newOven(); MakePizzaCooktakePizzaFromOvenCook = newMakePizzaCook(oven); OrdersClerkordersClerk = newOrdersClerk(takePizzaFromOvenCook); MakeDevliveriesServicemakeDevliveriesService = newMakeDevliveriesService(ordersClerk); TakePizzaFromOvenCookmakePizzaCook = newTakePizzaFromOvenCook(oven, ordersClerk); DecoupledPizzaPlacepizzaPlace = newDecoupledPizzaPlace(takePizzaFromOvenCook, ordersClerk, makeDevliveriesService, makePizzaCook); Customercustomer = newCustomer("Fred"); pizzaPlace.MakeOrder(customer,3);
Into Factory Method DecoupledPizzaPlacepizzaPlace = DecoupledPizzaPlace.Create(); Customercustomer = newCustomer("Fred"); pizzaPlace.MakeOrder(customer, 3); Did we really lower the cost of change?
IoC Client Code When Application Starts IoC.Initialize(newRhinoContainer("Pizza.boo")); Customercustomer = newCustomer("Fred"); IoCPizzaPlacepizzaPlace = IoC.Resolve<IoCPizzaPlace>(); pizzaPlace.MakeOrder(customer, 3); pizzaPlace.DoWork(); Configuration(later)
Configuring IoC: Using DSL Yes, you can do it with XML as well… Component("sara", IClerk, OrdersClerk) Component("nissim", ICook, MakePizzaCook) Component("moshe", IMakeDeliveries, MakeDeliveriesService) Component("nir", ICook, TakePizzaFromOvenCook) Component("oven", Oven) Component("pizza", IoCPizzaPlace, secondCook: @nir)
IoC.Resolve<IoCPizzaPlace>(); IClerk ICook √ √ √ √ ICook √ √ IMakeDeliveries √ IClerk √ √ IClerk √ Second Cook ICook √ √ Oven √
Inversion Of Control Container • All the services in theapplication are registered in the container. • Single point of access to all the services in the application. • Automatically resolves all the dependencies of services registered with the container. • Neither the client nor the service are tied to the dependencies.
Benefits of IoC • Dependencies are managed for you. • Highly focused objects (single responsibility, separation of concerns). • Testability. • Objects are not coupled directly to environment resources or other unintended implementations
Flexibility… , cook: @nir); TempClerk ); cook: @nir, secondCook: @nissim) Component("sara", IClerk, OrdersClerk) Component("nissim", ICook, MakePizzaCook) Component("moshe", IMakeDeliveries, MakeDeliveriesService) Component("nir", ICook, TakePizzaFromOvenCook) Component("oven", Oven) Component("pizza", IoCPizzaPlace, secondCook: @nir);
And in the real world… • Changing the payment service: PayPal Credit Card • Changing the delivery service: UPS FedEx • Changing a database • Replacing validation rules
Implementations In .Net • Castle Windsor • Spring .Net • Structure Map • Object Builder
Generic Services Usage: //from database IoC.Resolve<IRepository<Customer>>.Get(1337); //from active directory IoC.Resolve<IRepository<User>>.Get(42);
Configuration Component("users_repository",IRepository of User, ActiveDirectoryRepository) Component("database_repository", IRepository, NHibernateRepository)
Generic Specialization Usage: IoC.Resolve<IRepository<User>>.Get(5); IoC.Resolve<IRepository<Customer>>.Get(15);
Configuration Component("logging_users_repository",IRepository of User, LoggingDecorator of User, inner: @users_repository) Component("logging_ database _repository",IRepository, LoggingDecorator, inner: @database_repository) Component("users_repository",IRepository of User, ActiveDirectoryRepository) Component("database_repository", IRepository, NHibernateRepository)
Other uses of Inversion of Control Containers • Manage lifetime of services (singleton, transient, per request, etc). • Aspect Oriented Programming • Decorators
Pros • Simpler Architecture • Reduced cost of change • Encourage best practices • Interface driven design and component oriented programming • Less work • More smarts from the framework
Cons • Need to learn • Higher level of abstraction • Misuse of architecture
Resources • Inversion of Control Containers and the Dependency Injection pattern – Martin Fowler • The Dependency Injection Principal - Robert C. Martin • Inversion of Control and Dependency Injection: Working with Windsor Container – Oren Eini
Questions? Come to meet me at theArchitecture & Developers Panels or visit my blog: http://www.ayende.com/Blog
המשוב שלכם חשוב לנו! { לא לשכוח למלא משוב מסכם על כל היום! }