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

IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUK Journal
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
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
 

Recently uploaded (20)

IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
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
 

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); } }