SlideShare a Scribd company logo
1 of 28
Download to read offline
Migrating to
Dependency Injection
@josh_adell
www.servicetrade.com
blog.everymansoftware.com
github.com/jadell/neo4jphp
https://joind.in/10419
Legacy Code

Began with PHP 5.0 (now 5.3)
~80k LoC
Mixed PHP & HTML
3 x functions.php with ~9k LoC each
magic_quotes AND register_globals
No abstract classes or interfaces
Tightly coupled components
No tests
class UserRepository {
public function findUser($id) {
$db = new Database(/* connection params*/);
$userInfo = $db->query(/* User query with $id */);
$user = new User();
$user->setProperties($userInfo);
return $user;
}
}
========================================================
class UserController {
public function getUser() {
$repo = new UserRepository();
return $repo->findUser($_GET['id']);
}
}
Dependency Injection (DI)
Components should not
create the other components
on which they depend.
Injector injects Dependencies into Consumers
class PageController {
public function __construct(
Database $db) {
$this->repo = new Repository($db);
}
}
========================================================
class PageController {
public function __construct(
Repository $repo) {
$this->repo = $repo;
}
}
DI Container

Wires objects together
I like Pimple: http://pimple.sensiolabs.org/
Parameters
Services / Shared Objects
Factory Services
Factory Callbacks
$di = new Pimple();
// Parameters
$di['dbHost'] = "localhost";
$di['dbUser'] = "username";
$di['dbPass'] = "password";
// Services / Shared Objects
$di['database'] = function ($di) {
return new Database($di['dbHost'], $di['dbUser'], $di
['dbPass']);
};
$di['userRepository'] = function ($di) {
return new UserRepository($di['database]);
};
// Factory Services
$di['user'] = $di->factory(function () {
return new User();
});
// Factory Callbacks
$di['userFactory'] = $di->protect(function ($name) {
return new User($name);
});
Re-architect the application
so that object instantiation
only occurs in the DI Container.
Re-architect the application
so the DI Container
is only referenced from the DI Container.
Why Bother?

Testing / Quality
Maintenance
Extensibility
Flexibility
One Step at a Time
1.
2.
3.

Create a DI factory method for the class
Replace "new" with calls to the DI factory method
a.
b.

Move all shared objects to the constructor
Move all factory creations to anonymous function in the constructor

a.
b.

Pass in shared objects from the DI Container
Pass in factories callbacks from the DI Container

4.

Repeat from Step 1 for all classes
class UserRepository {
public function findUser($id) {
$db = new Database(/* connection params*/);
$userInfo = $db->query(/* User query with $id */);
$user = new User();
$user->setProperties($userInfo);
return $user;
}
}
========================================================
class UserController {
public function getUser() {
$repo = new UserRepository();
return $repo->findUser($_GET['id']);
}
}
Step #1: DI Container method
$di['userRepository'] = function () {
return new UserRepository();
};
Step #2: Replace “new”
class UserController {
public function getUser() {
global $di;
$repo = $di['userRepository'];
return $repo->findUser($_GET['id']);
}
}
Step #3a: Move shared objects
class UserRepository {
public function __construct() {
$this->db = new Database(/* connection params*/);
}
public function findUser($id) {
$userInfo = $this->db->query(/* User query with $id */);
$user = new User();
$user->setProperties($userInfo);
return $user;
}
}
Step #3b: Move factory creation
class UserRepository {
public function __construct() {
$this->db = new Database(/* connection params*/);
$this->userFactory = function () {
return new User();
};
}
public function findUser($id) {
$userInfo = $this->db->query(/* User query with $id */);
$user = call_user_func($this->userFactory);
$user->setProperties($userInfo);
return $user;
}
}
Step #4a: Pass in shared objects
$di['database'] = function () {
return new Database();
};
$di['userRepository'] = function (
$di) {
return new UserRepository(
$di['database']);
};
========================================================
class UserRepository {
public function __construct(
Database $db) {
$this->db = $db;
$this->userFactory = function () {
return new User();
};
}
// ...
Step #4b: Pass in factory callbacks
$di['userFactory'] = $di->protect(function () {
return new User();
});
$di['userRepository'] = function ($di) {
return new UserRepository($di['database'], $di['userFactory']);
};
========================================================
class UserRepository {
public function __construct(Database $db, callable $userFactory) {
$this->db = $db;
$this->userFactory = $userFactory;
}
// ...
Done with UserRepository!
class UserRepository {
public function __construct(Database $db, callable $userFactory) {
$this->db = $db;
$this->userFactory = $userFactory;
}
public function findUser($id) {
$userInfo = $this->db->query(/* User query with $id */);
$user = call_user_func($this->userFactory);
$user->setProperties($userInfo);
return $user;
}
}
Repeat for UserController
$di['userController'] = function ($di) {
return new UserController($di['userRepository']);
};
========================================================

class UserController {
public function __construct(UserRepository $repo) {
$this->userRepo = $repo;
}
public function getUser() {
global $di;
$repo = $di['userRepository'];
return $this->userRepo->findUser($_GET['id']);
}
}
That seems like a lot of steps
New Requirement

Every time a user submits a report,
send an email.
Setup Event Publisher
class User {
public function __construct(
EventEmitter $ee) {
$this->event = $ee;
}
public function submitReport(Report $report) {
// ...
$this->event->publish('newReport', $this, $report);
}
}
Setup Event Subscribers
$di['eventEmitter'] = function () {
return new EventEmitter();
};
$di['emailService'] = function ($di) {
return new EmailService();
};
$di['userFactory'] = $di->protect(function () use ($di)) {
$di['eventEmitter']->subscribe('newReport', $di['emailService']);
return new User($di['eventEmitter']);
});
I have to admit, it's getting better
Questions?
class Presentation {
public function __construct(Presenter $presenter) {
$this->presenter = $presenter;
}
public function askQuestion(Question $question) {
return $this->presenter->answer($question);
}
}
@josh_adell
www.servicetrade.com
blog.everymansoftware.com
github.com/jadell/neo4jphp
http://pimple.sensiolabs.org/
http://martinfowler.com/articles/injection.html

https://joind.in/10419

More Related Content

What's hot

Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in actionJace Ju
 
Php unit the-mostunknownparts
Php unit the-mostunknownpartsPhp unit the-mostunknownparts
Php unit the-mostunknownpartsBastian Feder
 
購物車程式架構簡介
購物車程式架構簡介購物車程式架構簡介
購物車程式架構簡介Jace Ju
 
Injection de dépendances dans Symfony >= 3.3
Injection de dépendances dans Symfony >= 3.3Injection de dépendances dans Symfony >= 3.3
Injection de dépendances dans Symfony >= 3.3Vladyslav Riabchenko
 
Chaining and function composition with lodash / underscore
Chaining and function composition with lodash / underscoreChaining and function composition with lodash / underscore
Chaining and function composition with lodash / underscoreNicolas Carlo
 
Impact of the New ORM on Your Modules
Impact of the New ORM on Your ModulesImpact of the New ORM on Your Modules
Impact of the New ORM on Your ModulesOdoo
 
Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015Konstantin Kudryashov
 
Persistent Memoization with HTML5 indexedDB and jQuery Promises
Persistent Memoization with HTML5 indexedDB and jQuery PromisesPersistent Memoization with HTML5 indexedDB and jQuery Promises
Persistent Memoization with HTML5 indexedDB and jQuery PromisesRay Bellis
 
Object-oriented Javascript
Object-oriented JavascriptObject-oriented Javascript
Object-oriented JavascriptDaniel Ku
 
JavaScript Fundamentals with Angular and Lodash
JavaScript Fundamentals with Angular and LodashJavaScript Fundamentals with Angular and Lodash
JavaScript Fundamentals with Angular and LodashBret Little
 
50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 MinutesAzim Kurt
 

What's hot (20)

Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in action
 
Php unit the-mostunknownparts
Php unit the-mostunknownpartsPhp unit the-mostunknownparts
Php unit the-mostunknownparts
 
購物車程式架構簡介
購物車程式架構簡介購物車程式架構簡介
購物車程式架構簡介
 
Injection de dépendances dans Symfony >= 3.3
Injection de dépendances dans Symfony >= 3.3Injection de dépendances dans Symfony >= 3.3
Injection de dépendances dans Symfony >= 3.3
 
Min-Maxing Software Costs
Min-Maxing Software CostsMin-Maxing Software Costs
Min-Maxing Software Costs
 
SOLID PRINCIPLES
SOLID PRINCIPLESSOLID PRINCIPLES
SOLID PRINCIPLES
 
Drupal7 dbtng
Drupal7  dbtngDrupal7  dbtng
Drupal7 dbtng
 
Chaining and function composition with lodash / underscore
Chaining and function composition with lodash / underscoreChaining and function composition with lodash / underscore
Chaining and function composition with lodash / underscore
 
Wakanday JS201 Best Practices
Wakanday JS201 Best PracticesWakanday JS201 Best Practices
Wakanday JS201 Best Practices
 
Design Patterns
Design PatternsDesign Patterns
Design Patterns
 
Impact of the New ORM on Your Modules
Impact of the New ORM on Your ModulesImpact of the New ORM on Your Modules
Impact of the New ORM on Your Modules
 
Sqlite perl
Sqlite perlSqlite perl
Sqlite perl
 
Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015
 
Persistent Memoization with HTML5 indexedDB and jQuery Promises
Persistent Memoization with HTML5 indexedDB and jQuery PromisesPersistent Memoization with HTML5 indexedDB and jQuery Promises
Persistent Memoization with HTML5 indexedDB and jQuery Promises
 
Polyglot parallelism
Polyglot parallelismPolyglot parallelism
Polyglot parallelism
 
Object-oriented Javascript
Object-oriented JavascriptObject-oriented Javascript
Object-oriented Javascript
 
JavaScript Fundamentals with Angular and Lodash
JavaScript Fundamentals with Angular and LodashJavaScript Fundamentals with Angular and Lodash
JavaScript Fundamentals with Angular and Lodash
 
50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes
 
Lodash js
Lodash jsLodash js
Lodash js
 
Unittests für Dummies
Unittests für DummiesUnittests für Dummies
Unittests für Dummies
 

Similar to Migrating to dependency injection

ZF2 for the ZF1 Developer
ZF2 for the ZF1 DeveloperZF2 for the ZF1 Developer
ZF2 for the ZF1 DeveloperGary Hockin
 
PHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodePHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodeSWIFTotter Solutions
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For BeginnersJonathan Wage
 
Drupal 8 Services And Dependency Injection
Drupal 8 Services And Dependency InjectionDrupal 8 Services And Dependency Injection
Drupal 8 Services And Dependency InjectionPhilip Norton
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony AppsKris Wallsmith
 
Dependency injection in Drupal 8
Dependency injection in Drupal 8Dependency injection in Drupal 8
Dependency injection in Drupal 8Alexei Gorobets
 
Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...go_oh
 
Easy rest service using PHP reflection api
Easy rest service using PHP reflection apiEasy rest service using PHP reflection api
Easy rest service using PHP reflection apiMatthieu Aubry
 
Dependency Injection and Pimple
Dependency Injection and PimpleDependency Injection and Pimple
Dependency Injection and PimpleDQNEO
 
Как получить чёрный пояс по WordPress? v2.0
Как получить чёрный пояс по WordPress? v2.0Как получить чёрный пояс по WordPress? v2.0
Как получить чёрный пояс по WordPress? v2.0Yevhen Kotelnytskyi
 
PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolvePHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolveXSolve
 
PHP 5.3 Overview
PHP 5.3 OverviewPHP 5.3 Overview
PHP 5.3 Overviewjsmith92
 
Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosDivante
 
Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Jeff Carouth
 
Laravel Design Patterns
Laravel Design PatternsLaravel Design Patterns
Laravel Design PatternsBobby Bouwmann
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf Conference
 
laravel tricks in 50minutes
laravel tricks in 50minuteslaravel tricks in 50minutes
laravel tricks in 50minutesBarang CK
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Developmentjsmith92
 
Михаил Крайнюк - Form API + Drupal 8: Form and AJAX
Михаил Крайнюк - Form API + Drupal 8: Form and AJAXМихаил Крайнюк - Form API + Drupal 8: Form and AJAX
Михаил Крайнюк - Form API + Drupal 8: Form and AJAXDrupalSib
 
Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Fabien Potencier
 

Similar to Migrating to dependency injection (20)

ZF2 for the ZF1 Developer
ZF2 for the ZF1 DeveloperZF2 for the ZF1 Developer
ZF2 for the ZF1 Developer
 
PHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodePHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better Code
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
Drupal 8 Services And Dependency Injection
Drupal 8 Services And Dependency InjectionDrupal 8 Services And Dependency Injection
Drupal 8 Services And Dependency Injection
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony Apps
 
Dependency injection in Drupal 8
Dependency injection in Drupal 8Dependency injection in Drupal 8
Dependency injection in Drupal 8
 
Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...
 
Easy rest service using PHP reflection api
Easy rest service using PHP reflection apiEasy rest service using PHP reflection api
Easy rest service using PHP reflection api
 
Dependency Injection and Pimple
Dependency Injection and PimpleDependency Injection and Pimple
Dependency Injection and Pimple
 
Как получить чёрный пояс по WordPress? v2.0
Как получить чёрный пояс по WordPress? v2.0Как получить чёрный пояс по WordPress? v2.0
Как получить чёрный пояс по WordPress? v2.0
 
PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolvePHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolve
 
PHP 5.3 Overview
PHP 5.3 OverviewPHP 5.3 Overview
PHP 5.3 Overview
 
Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenarios
 
Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4
 
Laravel Design Patterns
Laravel Design PatternsLaravel Design Patterns
Laravel Design Patterns
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
 
laravel tricks in 50minutes
laravel tricks in 50minuteslaravel tricks in 50minutes
laravel tricks in 50minutes
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Development
 
Михаил Крайнюк - Form API + Drupal 8: Form and AJAX
Михаил Крайнюк - Form API + Drupal 8: Form and AJAXМихаил Крайнюк - Form API + Drupal 8: Form and AJAX
Михаил Крайнюк - Form API + Drupal 8: Form and AJAX
 
Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Dependency injection-zendcon-2010
Dependency injection-zendcon-2010
 

Recently uploaded

Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Orbitshub
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodJuan lago vázquez
 
Stronger Together: Developing an Organizational Strategy for Accessible Desig...
Stronger Together: Developing an Organizational Strategy for Accessible Desig...Stronger Together: Developing an Organizational Strategy for Accessible Desig...
Stronger Together: Developing an Organizational Strategy for Accessible Desig...caitlingebhard1
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxRemote DBA Services
 
Introduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDMIntroduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDMKumar Satyam
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontologyjohnbeverley2021
 
Modernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using BallerinaModernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using BallerinaWSO2
 
Simplifying Mobile A11y Presentation.pptx
Simplifying Mobile A11y Presentation.pptxSimplifying Mobile A11y Presentation.pptx
Simplifying Mobile A11y Presentation.pptxMarkSteadman7
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdfSandro Moreira
 
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)Samir Dash
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDropbox
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Victor Rentea
 
Less Is More: Utilizing Ballerina to Architect a Cloud Data Platform
Less Is More: Utilizing Ballerina to Architect a Cloud Data PlatformLess Is More: Utilizing Ballerina to Architect a Cloud Data Platform
Less Is More: Utilizing Ballerina to Architect a Cloud Data PlatformWSO2
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyKhushali Kathiriya
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityWSO2
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusZilliz
 

Recently uploaded (20)

Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Stronger Together: Developing an Organizational Strategy for Accessible Desig...
Stronger Together: Developing an Organizational Strategy for Accessible Desig...Stronger Together: Developing an Organizational Strategy for Accessible Desig...
Stronger Together: Developing an Organizational Strategy for Accessible Desig...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
 
Introduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDMIntroduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDM
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontology
 
Modernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using BallerinaModernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using Ballerina
 
Simplifying Mobile A11y Presentation.pptx
Simplifying Mobile A11y Presentation.pptxSimplifying Mobile A11y Presentation.pptx
Simplifying Mobile A11y Presentation.pptx
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
Less Is More: Utilizing Ballerina to Architect a Cloud Data Platform
Less Is More: Utilizing Ballerina to Architect a Cloud Data PlatformLess Is More: Utilizing Ballerina to Architect a Cloud Data Platform
Less Is More: Utilizing Ballerina to Architect a Cloud Data Platform
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 

Migrating to dependency injection

  • 3. Legacy Code Began with PHP 5.0 (now 5.3) ~80k LoC Mixed PHP & HTML 3 x functions.php with ~9k LoC each magic_quotes AND register_globals No abstract classes or interfaces Tightly coupled components No tests
  • 4. class UserRepository { public function findUser($id) { $db = new Database(/* connection params*/); $userInfo = $db->query(/* User query with $id */); $user = new User(); $user->setProperties($userInfo); return $user; } } ======================================================== class UserController { public function getUser() { $repo = new UserRepository(); return $repo->findUser($_GET['id']); } }
  • 5. Dependency Injection (DI) Components should not create the other components on which they depend. Injector injects Dependencies into Consumers
  • 6. class PageController { public function __construct( Database $db) { $this->repo = new Repository($db); } } ======================================================== class PageController { public function __construct( Repository $repo) { $this->repo = $repo; } }
  • 7. DI Container Wires objects together I like Pimple: http://pimple.sensiolabs.org/ Parameters Services / Shared Objects Factory Services Factory Callbacks
  • 8. $di = new Pimple(); // Parameters $di['dbHost'] = "localhost"; $di['dbUser'] = "username"; $di['dbPass'] = "password"; // Services / Shared Objects $di['database'] = function ($di) { return new Database($di['dbHost'], $di['dbUser'], $di ['dbPass']); }; $di['userRepository'] = function ($di) { return new UserRepository($di['database]); };
  • 9. // Factory Services $di['user'] = $di->factory(function () { return new User(); }); // Factory Callbacks $di['userFactory'] = $di->protect(function ($name) { return new User($name); });
  • 10. Re-architect the application so that object instantiation only occurs in the DI Container. Re-architect the application so the DI Container is only referenced from the DI Container.
  • 11. Why Bother? Testing / Quality Maintenance Extensibility Flexibility
  • 12. One Step at a Time 1. 2. 3. Create a DI factory method for the class Replace "new" with calls to the DI factory method a. b. Move all shared objects to the constructor Move all factory creations to anonymous function in the constructor a. b. Pass in shared objects from the DI Container Pass in factories callbacks from the DI Container 4. Repeat from Step 1 for all classes
  • 13. class UserRepository { public function findUser($id) { $db = new Database(/* connection params*/); $userInfo = $db->query(/* User query with $id */); $user = new User(); $user->setProperties($userInfo); return $user; } } ======================================================== class UserController { public function getUser() { $repo = new UserRepository(); return $repo->findUser($_GET['id']); } }
  • 14. Step #1: DI Container method $di['userRepository'] = function () { return new UserRepository(); };
  • 15. Step #2: Replace “new” class UserController { public function getUser() { global $di; $repo = $di['userRepository']; return $repo->findUser($_GET['id']); } }
  • 16. Step #3a: Move shared objects class UserRepository { public function __construct() { $this->db = new Database(/* connection params*/); } public function findUser($id) { $userInfo = $this->db->query(/* User query with $id */); $user = new User(); $user->setProperties($userInfo); return $user; } }
  • 17. Step #3b: Move factory creation class UserRepository { public function __construct() { $this->db = new Database(/* connection params*/); $this->userFactory = function () { return new User(); }; } public function findUser($id) { $userInfo = $this->db->query(/* User query with $id */); $user = call_user_func($this->userFactory); $user->setProperties($userInfo); return $user; } }
  • 18. Step #4a: Pass in shared objects $di['database'] = function () { return new Database(); }; $di['userRepository'] = function ( $di) { return new UserRepository( $di['database']); }; ======================================================== class UserRepository { public function __construct( Database $db) { $this->db = $db; $this->userFactory = function () { return new User(); }; } // ...
  • 19. Step #4b: Pass in factory callbacks $di['userFactory'] = $di->protect(function () { return new User(); }); $di['userRepository'] = function ($di) { return new UserRepository($di['database'], $di['userFactory']); }; ======================================================== class UserRepository { public function __construct(Database $db, callable $userFactory) { $this->db = $db; $this->userFactory = $userFactory; } // ...
  • 20. Done with UserRepository! class UserRepository { public function __construct(Database $db, callable $userFactory) { $this->db = $db; $this->userFactory = $userFactory; } public function findUser($id) { $userInfo = $this->db->query(/* User query with $id */); $user = call_user_func($this->userFactory); $user->setProperties($userInfo); return $user; } }
  • 21. Repeat for UserController $di['userController'] = function ($di) { return new UserController($di['userRepository']); }; ======================================================== class UserController { public function __construct(UserRepository $repo) { $this->userRepo = $repo; } public function getUser() { global $di; $repo = $di['userRepository']; return $this->userRepo->findUser($_GET['id']); } }
  • 22. That seems like a lot of steps
  • 23. New Requirement Every time a user submits a report, send an email.
  • 24. Setup Event Publisher class User { public function __construct( EventEmitter $ee) { $this->event = $ee; } public function submitReport(Report $report) { // ... $this->event->publish('newReport', $this, $report); } }
  • 25. Setup Event Subscribers $di['eventEmitter'] = function () { return new EventEmitter(); }; $di['emailService'] = function ($di) { return new EmailService(); }; $di['userFactory'] = $di->protect(function () use ($di)) { $di['eventEmitter']->subscribe('newReport', $di['emailService']); return new User($di['eventEmitter']); });
  • 26. I have to admit, it's getting better
  • 27. Questions? class Presentation { public function __construct(Presenter $presenter) { $this->presenter = $presenter; } public function askQuestion(Question $question) { return $this->presenter->answer($question); } }