Getting started with Dependency Injection. Rob Allen May 2015

Similar documents
Introducing Dependency Injection. Rob Allen November 2013

Introducing Dependency Injection. Rob Allen September 2013

Dependency Injection Container Documentation

Design for Testability. Dave Liddament (Director and developer at Lamp Bristol Limited)

Embrace Factories Factories. By Rob Gonda

CS 520/620 Advanced Software Engineering Spring February 11, 2016

DI Why? Getting a Grip on Dependency Injection. Jeremy Clark

James Cowie Software Engineer Session

Inversion of Control and Dependency Injection. Erik Dörnenburg, ThoughtWorks Inc.

DEV2QA PDT 1.1. Feature Name : Code Completion Module name : PHPCompletionEngine

SOLID Principles. Equuleus Technologies. Optional Subheading October 19, 2016

Dependency Injection and the art of services and containers. With <3 from KnpUniversity

Silex and Twig. Jon Ginn

SPRING MOCK TEST SPRING MOCK TEST I

Backend Web Frameworks

Services in Joomla 4. Allon Moritz J and Beyond 13. May 2018

Bldr.io Documentation

Magento Technical Guidelines

Chapter 5 Object-Oriented Programming

Design Patterns. CSC207 Winter 2017

Design Patterns. CSC207 Fall 2017

1 Software Architecture

Agile Architecture. The Why, the What and the How

Chris Donnan & Solomon Duskis

SYMFONY2 WEB FRAMEWORK

OSGi on the Server. Martin Lippert (it-agile GmbH)

Application Architectures, Design Patterns

The de constructed. Magento module

Import Statements, Instance Members, and the Default Constructor

Dependency Injection and Spring. INF5750/ Lecture 2 (Part II)

Recap: Pointers. int* int& *p &i &*&* ** * * * * IFMP 18, M. Schwerhoff

Zend Framework 2.0 is coming! Rob Allen

Design Pattern. CMPSC 487 Lecture 10 Topics: Design Patterns: Elements of Reusable Object-Oriented Software (Gamma, et al.)

Introduction of Laravel and creating a customized framework out of its packages

Dependency Inversion, Dependency Injection and Inversion of Control. Dependency Inversion Principle by Robert Martin of Agile Fame

Chapter 15: Object Oriented Programming

CS 520/620 Advanced Software Engineering Fall September 27, 2016

Building Websites with Zend Expressive 3

Symfony is based on the classic web design pattern called the MVC pattern

Unit 1 3 Dependency Injection & Inversion of Control

Dependency Injection with Guice

Symfony Doctrine Build Schema From Existing Database

Design patterns using Spring and Guice

Using Design Patterns in Java Application Development

CS 292 Software Development

Object Oriented Concepts. Produced by. Introduction to the Java Programming Language. Eamonn de Leastar

Lessons Learned. Johnny Bigert, Ph.D., Skype/Microsoft October 26, 2011

Hey there, I m (name) and today I m gonna talk to you about rate of change and slope.

G52CPP C++ Programming Lecture 13

MVC / MVP Reid Holmes

Program to an Interface (a.k.a. - P2I) Not an Implementation

Zend Framework 2 Patterns

Introducing the Spring framework

Program to an Interface, Not an Implementation

CS111: PROGRAMMING LANGUAGE II

Clean Code in Small Companies

With great power comes great responsibility

Dependency Injection with ObjectPoolManager

Creating Models. Rob Allen, July 2014

Socket attaches to a Ratchet. 2) Bridge Decouple an abstraction from its implementation so that the two can vary independently.

OO and Ahh! An Introduction to Object Oriented Programming With PHP. Division 1 Systems. John Valance. Copyright John Valance Division 1 Systems

03 Model-View-ViewModel. Ben Riga

Bernard. Release latest

MVC / MVP Mei Nagappan

Programming for Engineers in Python

Laravel: From Apprentice To Artisan

Build Testable Client and Service Applications

Spring Interview Questions

CS 370 The Pseudocode Programming Process D R. M I C H A E L J. R E A L E F A L L

Chapter Two Bonus Lesson: JavaDoc

Web Application Design. Husni Husni.trunojoyo.ac.id

Effects of Dependency Injection on Maintainability. Kate Razina

Design Patterns. CSC207 Fall 2017

CS342: Software Design. November 21, 2017

Concepts of Object-Oriented Programming. Richard Berger Johannes Kepler University Linz

Software Design and Analysis for Engineers

Packaging and Deploying Java Based Solutions to WebSphere Message Broker V7

Friendship in Service of Testing

Introduction to Testing and Maintainable code

Sitesbay.com. A Perfect Place for All Tutorials Resources. Java Projects C C++ DS Interview Questions JavaScript

Design Patterns. Dependency Injection. Oliver Haase

Applying Some Gang of Four Design Patterns CSSE 574: Session 5, Part 3

CSE 341: Programming Languages

Inyección de Dependencias en el Lenguaje de Programación Go

Tecniche di Progettazione: Design Patterns

Design Patterns #3. Reid Holmes. Material and some slide content from: - GoF Design Patterns Book - Head First Design Patterns

MATE: A Flex Framework Extreme Makeover

An Introduction to Patterns

Apache Felix. Richard S. Hall. A Standard Plugin Model for Apache. Atlanta, Georgia U.S.A. November 13th, 2007

Modellistica Medica. Maria Grazia Pia, INFN Genova. Scuola di Specializzazione in Fisica Sanitaria Genova Anno Accademico

COURSE 2 DESIGN PATTERNS

Expert Guidance on Migrating from Magento 1 to Magento 2

8 Designing classes. Main concepts to be covered. Software changes. Change or die. The Zuul Classes. World of Zuul

Implementing MVVM in Real World ArcGIS Server Silverlight Applications. Brandon Copeland LJA Engineering, Inc.

Building a mobile enterprise application with Xamarin.Forms, Docker, MVVM and.net Core. Gill

Hovedopgave. Bringing a Legacy System under Test Control. Master i informationsteknologi Linien i softwarekonstruktion

Designing the M in MVC

Notes on Chapter Three

CHAPTER 6: CREATIONAL DESIGN PATTERNS

Lecture 4: Memory Management & The Programming Interface

Transcription:

Getting started with Dependency Injection Rob Allen May 2015

Dependency Injection enables loose coupling and loose coupling makes code more maintainable Mark Seemann

We're actually talking about loose coupling today

Coupling

Benefits of loose coupling Maintainability - Classes are more clearly defined Extensibility - easy to recompose application Testability - isolate what you re testing

A worked example Class A needs class B in order to work. class Letter { protected $paper; } public function construct() { $this->paper = new WritingPaper(); } // usage: $letter = new Letter(); $letter->write("dear John,...");

Pros and cons: Pros: Very simple to use Cons: Tight coupling Cannot test Letter in isolation Cannot change $paper

How do we change the paper size? How do we change the type of paper?

Method parameters? class Letter { protected $paper; } public function construct($size) { $this->paper = new WritingPaper($size); } // usage: $letter = new Letter('A4'); $letter->write("dear John,...");

Use a Registry? class Letter { protected $paper; } public function write($text) { $paper = Zend_Registry::get('paper'); return $paper->placewords($text); }

Use a Registry? // usage: Zend_Registry::set('paper', new AirmailPaper('A4')); $letter = new Letter(); $letter->write("dear John,...");

Inject the dependency!

Injection class Letter { protected $paper; } public function construct($paper) { $this->paper = $paper; }

Injection // usage: $letter = new Letter(new WritingPaper('A4')); $letter->write("dear John,...");

This is also known as Inversion of Control

Pros and cons: Pros: Decoupled $paper from Letter: Can change the type of paper Natural configuration of the Paper object Can test Letter independently Cons: Burden of construction of $paper is on the user

Dependency Injection That s it; we re done!

Types of injection Constructor injection: $letter = new Letter($paper); Setter injection: $letter = new Letter(); $letter->setpaper($paper); Property injection: $letter = new Letter(); $letter->paper = $paper; Interface injection: interface InjectPaper { public function injectpaper($paper); } $letter = $container->get('letter'); // container automatically calls // injectpaper() if Letter implements // InjectPaper

Note Too many constructor parameters is a code smell Two-phase construction is Bad(TM)

Rules of thumb Limit the scope of any given object Depend on interfaces Use constructor injection

How about usage? $paper = new AirmailPaper('A4'); $envelope = new Envelope('DL'); $letter = new Letter($paper, $envelope); $letter->write("dear John,..."); Setup of dependencies gets tedious quickly

Dependency Injection Container An object that handles the creation of objects and their dependencies Dependency resolution can be automatic or configured DICs are optional

Write a simple container class LetterContainer { public function getletter() { $paper = new AirmailPaper('A4'); $envelope = new Envelope('DL'); $letter = new Letter($paper, $envelope); } } return $letter;

Usage $container = new LetterContainer() $letter = $container->getletter();

Handle configuration class LetterContainer { protected $params; public function construct(array $params) { $this->params = $params; }

cont public function getletter() { $paper = new AirmailPaper( $this->params['paper.size']); $envelope = new Envelope( $this->params['envelope.size']); $letter = new Letter($paper, $envelope); } } return $letter;

Usage // usage: $container = new LetterContainer(array( 'paper.size' => 'A4', 'envelope.size' => 'DL', )) $letter = $container->getletter(); Now, it s easy to change parameters of the dependent objects

Shared objects class LetterContainer { protected $shared; public function getletter() { if (!isset(self::$shared['letter'])) { //... create $letter as before... self::$shared['letter'] = $letter; } return self::$shared['letter']; } //...

Dependency Injection Container Creates objects on demand Manages construction of an object s dependencies Separates of configuration from construction Can allow for shared objects However: Writing and maintaining a container class by hand is tedious!

Available DICs Don t reinvent the wheel Aura.Di - part of Aura Container - part of The League Dice by Tom Butler Illuminate Container - part of Laravel PHP-DI by Matthieu Napoli Pimple by Fabien Potencier Service Container - part of Symfony2 Zend\Di & Zend\ServiceManager - part of ZF 2

Pimple Easy to use Small: only 179 lines of PHP Configured manually

Pimple $container = new Pimple(); $container['letter'] = function ($c) { $paper = new AirmailPaper('A4'); $envelope = new Envelope('DL'); }; $letter = new Letter($paper, $envelope); return $letter;

Pimple usage $container = new Pimple(); $letter = $container['letter'];

More typically $container = new Pimple(); $container['paper.size'] = 'A4'; $container['envelope.size'] = 'DL'; $container['paper'] = function ($c) { $size = $c['paper.size']; return new AirmailPaper($size); }; $container['envelope'] = function ($c) { $size = $c['envelope.size']; return new Envelope($size); };

cont $container['letter'] = function ($c) { $paper = $c['paper']; $envelope = $c['envelope']; return new Letter($paper, $envelope); }; Usage is identical: $container = new Pimple(); $letter = $container['letter'];

Too much PHP?! Symfony s Container supports YAML!

services.yml parameters: paper.size: A4 services: paper: class: AirmailPaper arguments: ["%paper.size%"] letter: class: Letter arguments: ["@paper"]

Usage use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; // configure container $container = new ContainerBuilder(); $locator = new FileLocator( DIR ); $loader = new YamlFileLoader($container, $locator); $loader->load('services.yml'); // Retrieve from container $letter = $container->get(letter');

Recommendation Hold configuration separately Create each each object separately

Automatic resolution class Letter { protected $paper; } public function construct(airmailpaper $paper) { $this->paper = $paper; }

Automatic resolution $di = new Zend\Di\Di(); $letter = $di->get('letter'); var_dump($letter); Output: class Letter#18 (2) { protected $paper => class AirmailPaper#17 (1) { private $size => string(2) "A4" } }

Zend\Di configuration via instancemanager: $im = $di->instancemanager(); $im->setparameters('airmailpaper', ['size' => 'A4']); $letter = $di->get('letter'); when retrieving: $letter = $di->get('letter', array('size' => 'A4'));

Interface dependencies class AirmailPaper implements PaperInterface { /* */} class Letter { function construct(paperinterface $paper)) { /* */} } $di = new Zend\Di\Di(); $im = $di->instancemanager(); $im->setparameters('airmailpaper', ['size' => 'A4']); $im->addtypepreference('paperinterface', 'AirmailPaper'); $letter = $di->get('letter');

Note Automatic resolution can be much slower Magic is happening! There s a reason that most DICs are configured.

A note on Service Location

Service Location class Letter { protected $paper; } public function construct($locator) { $this->paper = $locator->get('paper'); }

Service Location Component pulls its dependencies in when it needs them Still decouples concrete implementation of Paper from Letter however Hidden dependencies! Who knows what is being used? Makes testing harder

Recap Dependency injection promotes: Loose coupling Separation of configuration from construction from usage Easier testing

Dependency Injection is a 25-dollar term for a 5-cent concept. James Shore

Thank you! https://m.joind.in/talk/3d82c Rob Allen - http://akrabat.com - @akrabat