SlideShare uma empresa Scribd logo
1 de 53
Baixar para ler offline
Singletons in
Why they are bad and how you can eliminate
       them from your applications
Gordon Oheim
   @go_oh
a.k.a.
The GoF Book
Singleton
Creational Pattern
„control when and how objects are
            created“
“Ensure a class has only one
instance, and provide a global
     access point to it.”
Singleton
          Singleton

- instance : Singleton
- instance : Singleton

+
+   getInstance()
    getInstance()   :
                    :   Singleton
                        Singleton
-
-   __construct()
    __construct()   :
                    :   void
                        void
-
-   __clone()
    __clone()       :
                    :   void
                        void
-
-   __wakeup()
    __wakeup()      :
                    :   void
                        void
class Singleton
…
    public static function getInstance()
    {
        if (!isset(self::$instance)) {
            self::$instance = new self;
        }
        return self::$instance;
    }
}
abstract class Singleton
…
    public static function getInstance()
    {
        return isset(static::$instance)
            ? static::$instance
            : static::$instance = new static;
    }
    final private function __construct()
    {
        static::init();
    }
    protected function init() {}
}

class A extends Singleton {
    protected static $instance;
}
trait Singleton
…
    protected static $instance;
    final public static function getInstance()
    {
        return isset(static::$instance)
            ? static::$instance
            : static::$instance = new static;
    }
    final private function __construct() {
        static::init();
    }
    protected function init() {}
}

class A {
    use Singleton;
}
„Nobody should need a mechanism to make
  it as easy as pie to clutter the code base
              with singletons“

          - Sebastian Bergmann
Testing Singletons
„In my stilted view of the universe anything that
impedes testing is something to be avoided. There
 are those who don't agree with this view, but I'll
   pit my defect rates against theirs any time.“

        - Robert „Uncle Bob“ C. Martin
class TableDataGateway
…
    public function __construct()
    {
        $this->db = Db::getInstance();
    }
    public insert(array $data)
    {
        $this->db->sql('INSERT …', $data);
    }
}
class TableDataGatewayTest extends PHPUnit…
    /**
     * @dataProvider provideInsertData
     */
    public function testInsertCallsDbWithData($data)
    {
        $gateway = new TableDataGateway;
        $gateway->insert($data);
        $this->assertSame(
            $data,
            $gateway->findById($data['id'])
        );
    }
}
throws LogicException:
No key found for 'pdo' in Registry
class Db extends Singleton
…
    protected function init()
    {
        $this->logger = Logger::getInstance();
        $this->pdo = new PDO(Registry::get('pdo'));
    }
    public sql($query, $data)
    {
        $this->logger->log(printf(
        'Executed %s with %s',
            $query,
            implode(',', $data)
        ));
        $sth = $this->pdo->prepare($query);
        return $sth->execute($data);
    }
}
Singletons are pathological liars
          - Miško Hevery
class TableDataGatewayTest extends PHPUnit…
    /**
     * @dataProvider provideInsertData
     */
    public function testInsertCallsDbWithData($data)
    {
        Registry::set('pdo', array('…'));
        Registry::set('log', '/dev/null');
        $gateway = new TableDataGateway;
        $gateway->insert($data);
        $this->assertSame(
            $data,
            $gateway->findById($data['id'])
        );
    }
}
Your tests are not isolated.
    You still need a real database.
No easy way to mock the Db Singleton.
„The real problem with Singletons is that they
give you such a good excuse not to think carefully
  about the appropriate visibility of an object.“

                   - Kent Beck
Hard to change code
  manifests itself in a cascade of
subsequent changes in dependent
               code
Fragile code
breaks in many places when you
     change just one place
Non-reusable code
   is code that you cannot reuse in
another project because it contains too
         much extra baggage
S.O.L.I.D.
Single Responsibility Principle

A class should have one, and only one,
           reason to change.
Open Closed Principle

You should be able to extend a classes
   behavior, without modifying it.
Liskov Substitution Principle

Derived classes must be substitutable
       for their base classes.
Interface Segregation Principle

Make fine grained interfaces that are client
                specific.
Dependency Inversion Principle
Depend on abstractions, not on concretions.
Solid Singleton?
SRP Violation

 Creation Logic + Business Logic
      = 2 reasons to change

Mitigated by using Abstract Singletons

 But responsibilities are still strongly
     coupled through inheritance
OCP Violation

In PHP < 5.2 Singletons are closed for extending

 Boilerplate code has to be removed when no
                longer needed
DIP Violation

  Global access breaks encapsulation

         Hides dependencies

Adds concrete dependencies into Clients

            Signature lies
Singletons in the Wild
Config              FooController
                                 Response
    FrontController
ThatService
       Request                Cache
                   Database
 Application              BarController
        Registry         Logger
   ThisService
                 Bootstrap            Acl
Config              FooController
                                 Response
    FrontController
ThatService
       Request                Cache
                   Database
 Application              BarController
        Registry         Logger
   ThisService
                 Bootstrap            Acl
Recap:
 “Ensure a class has only one
instance, and provide a global
     access point to it.”
„So much of the Singleton pattern is about
 coaxing language protection mechanisms into
protecting this one aspect: singularity. I guess it
is important, but it seems to have grown out of
                  proportion.“

              - Ward Cunningham
You do not need to ensure singularity
when you are going to instantiate the
     object only once anyway.
You do not need to provide a Global
Access Point when you can inject the
              object.
class TableDataGateway
…
    public function __construct()
    {
        $this->db = Db::getInstance();
    }
}

class Db extends Singleton
…
    protected function init()
    {
        $this->logger = Logger::getInstance();
        $this->pdo = new PDO(Registry::get('pdo'));
    }
}
class TableDataGateway
…
    public function __construct(Db $db)
    {
        $this->db = $db;
    }
}

class Db
…
    public function __construct(PDO $pdo, Log $logger)
    {
        $this->logger = $logger;
        $this->pdo = $pdo;
    }
}
But then I have to push dependencies all
  the way through my object graph?!
Recap:
       Creational Pattern
„control when and how objects are
            created“
Use Builders and Factories to
 create Collaborator Graphs
class UserControllerBuilder
{
    public function build($config)
    {
        $log = new Log($config['log']);
        $pdo = new PDO($config['…']);
        $db = new Db($pdo, $log);
        $tdg = new TableDataGateway($db);
        return new UserController($tdg);
    }
}
class UserControllerBuilder
{
    public function build($config)
    {
        $log = new Log($config['log']);
        $pdo = new PDO($config['…']);
   ??? $db = new Db($pdo, $log);
        $tdg = new TableDataGateway($db);
        return new UserController($tdg);
    }
}
class UserControllerBuilder
{
    public function build($config)
    {
        $db = new LogDecorator(
            new PDO($config['…']);
            new Log($config['log']);
        );
        $tdg = new TableDataGateway($db);
        return new UserController($tdg);
    }
}
// index.php
include '/path/to/autoload.php';
$config = new Config('/path/to/config.ini');
$router = new Router(
    array(
      '/user/{id}' => function() use ($config)
      {
        $builder = new UserControllerBuilder;
        return $builder->build($config);
      }
    )
);
$router->route(
    new Request($_GET, $_POST, $_SERVER),
    new Response
);
„Singletons aren't necessary
when you can design or redesign
    to avoid using them.“

        - Joshua Kerievsky
„I'm in favor of dropping Singleton.
 Its use is almost always a design
               smell“

            - Erich Gamma

Mais conteúdo relacionado

Mais procurados

Amazon S3 Best Practice and Tuning for Hadoop/Spark in the Cloud
Amazon S3 Best Practice and Tuning for Hadoop/Spark in the CloudAmazon S3 Best Practice and Tuning for Hadoop/Spark in the Cloud
Amazon S3 Best Practice and Tuning for Hadoop/Spark in the CloudNoritaka Sekiyama
 
Golang 101
Golang 101Golang 101
Golang 101宇 傅
 
Designing and Implementing a Real-time Data Lake with Dynamically Changing Sc...
Designing and Implementing a Real-time Data Lake with Dynamically Changing Sc...Designing and Implementing a Real-time Data Lake with Dynamically Changing Sc...
Designing and Implementing a Real-time Data Lake with Dynamically Changing Sc...Databricks
 
The Art of Database Experiments – PostgresConf Silicon Valley 2018 / San Jose
The Art of Database Experiments – PostgresConf Silicon Valley 2018 / San JoseThe Art of Database Experiments – PostgresConf Silicon Valley 2018 / San Jose
The Art of Database Experiments – PostgresConf Silicon Valley 2018 / San JoseNikolay Samokhvalov
 
ClickHouse Data Warehouse 101: The First Billion Rows, by Alexander Zaitsev a...
ClickHouse Data Warehouse 101: The First Billion Rows, by Alexander Zaitsev a...ClickHouse Data Warehouse 101: The First Billion Rows, by Alexander Zaitsev a...
ClickHouse Data Warehouse 101: The First Billion Rows, by Alexander Zaitsev a...Altinity Ltd
 
Low latency in java 8 v5
Low latency in java 8 v5Low latency in java 8 v5
Low latency in java 8 v5Peter Lawrey
 
Address Binding Scheme
Address Binding SchemeAddress Binding Scheme
Address Binding SchemeRajesh Piryani
 
Unit II - 3 - Operating System - Process Synchronization
Unit II - 3 - Operating System - Process SynchronizationUnit II - 3 - Operating System - Process Synchronization
Unit II - 3 - Operating System - Process Synchronizationcscarcas
 
Memory safety in rust
Memory safety in rustMemory safety in rust
Memory safety in rustJawahar
 
Big data analytics with Spark & Cassandra
Big data analytics with Spark & Cassandra Big data analytics with Spark & Cassandra
Big data analytics with Spark & Cassandra Matthias Niehoff
 
Etsy Activity Feeds Architecture
Etsy Activity Feeds ArchitectureEtsy Activity Feeds Architecture
Etsy Activity Feeds ArchitectureDan McKinley
 
Thrift vs Protocol Buffers vs Avro - Biased Comparison
Thrift vs Protocol Buffers vs Avro - Biased ComparisonThrift vs Protocol Buffers vs Avro - Biased Comparison
Thrift vs Protocol Buffers vs Avro - Biased ComparisonIgor Anishchenko
 

Mais procurados (20)

Heap Management
Heap ManagementHeap Management
Heap Management
 
Amazon S3 Best Practice and Tuning for Hadoop/Spark in the Cloud
Amazon S3 Best Practice and Tuning for Hadoop/Spark in the CloudAmazon S3 Best Practice and Tuning for Hadoop/Spark in the Cloud
Amazon S3 Best Practice and Tuning for Hadoop/Spark in the Cloud
 
Clustering
ClusteringClustering
Clustering
 
Go lang
Go langGo lang
Go lang
 
Golang 101
Golang 101Golang 101
Golang 101
 
Designing and Implementing a Real-time Data Lake with Dynamically Changing Sc...
Designing and Implementing a Real-time Data Lake with Dynamically Changing Sc...Designing and Implementing a Real-time Data Lake with Dynamically Changing Sc...
Designing and Implementing a Real-time Data Lake with Dynamically Changing Sc...
 
The Art of Database Experiments – PostgresConf Silicon Valley 2018 / San Jose
The Art of Database Experiments – PostgresConf Silicon Valley 2018 / San JoseThe Art of Database Experiments – PostgresConf Silicon Valley 2018 / San Jose
The Art of Database Experiments – PostgresConf Silicon Valley 2018 / San Jose
 
ClickHouse Data Warehouse 101: The First Billion Rows, by Alexander Zaitsev a...
ClickHouse Data Warehouse 101: The First Billion Rows, by Alexander Zaitsev a...ClickHouse Data Warehouse 101: The First Billion Rows, by Alexander Zaitsev a...
ClickHouse Data Warehouse 101: The First Billion Rows, by Alexander Zaitsev a...
 
Backup and-recovery2
Backup and-recovery2Backup and-recovery2
Backup and-recovery2
 
Low latency in java 8 v5
Low latency in java 8 v5Low latency in java 8 v5
Low latency in java 8 v5
 
Address Binding Scheme
Address Binding SchemeAddress Binding Scheme
Address Binding Scheme
 
Hierarchical Clustering
Hierarchical ClusteringHierarchical Clustering
Hierarchical Clustering
 
Unit II - 3 - Operating System - Process Synchronization
Unit II - 3 - Operating System - Process SynchronizationUnit II - 3 - Operating System - Process Synchronization
Unit II - 3 - Operating System - Process Synchronization
 
Memory safety in rust
Memory safety in rustMemory safety in rust
Memory safety in rust
 
Big data analytics with Spark & Cassandra
Big data analytics with Spark & Cassandra Big data analytics with Spark & Cassandra
Big data analytics with Spark & Cassandra
 
System call
System callSystem call
System call
 
Etsy Activity Feeds Architecture
Etsy Activity Feeds ArchitectureEtsy Activity Feeds Architecture
Etsy Activity Feeds Architecture
 
Thrift vs Protocol Buffers vs Avro - Biased Comparison
Thrift vs Protocol Buffers vs Avro - Biased ComparisonThrift vs Protocol Buffers vs Avro - Biased Comparison
Thrift vs Protocol Buffers vs Avro - Biased Comparison
 
3 classification
3  classification3  classification
3 classification
 
Disk Scheduling
Disk SchedulingDisk Scheduling
Disk Scheduling
 

Destaque

Reducing Database Pain & Costs with Postgres
Reducing Database Pain & Costs with PostgresReducing Database Pain & Costs with Postgres
Reducing Database Pain & Costs with PostgresEDB
 
Design Patterns Reconsidered
Design Patterns ReconsideredDesign Patterns Reconsidered
Design Patterns ReconsideredAlex Miller
 
Creating "Secure" PHP Applications, Part 1, Explicit Code & QA
Creating "Secure" PHP Applications, Part 1, Explicit Code & QACreating "Secure" PHP Applications, Part 1, Explicit Code & QA
Creating "Secure" PHP Applications, Part 1, Explicit Code & QAarchwisp
 
Comparing the Multimodal Interaction Technique Design of MINT with NiMMiT
Comparing the Multimodal Interaction Technique Design of MINT with NiMMiTComparing the Multimodal Interaction Technique Design of MINT with NiMMiT
Comparing the Multimodal Interaction Technique Design of MINT with NiMMiTSebastian Feuerstack
 
Lca seminar modified
Lca seminar modifiedLca seminar modified
Lca seminar modifiedInbok Lee
 
Integrating Lucene into a Transactional XML Database
Integrating Lucene into a Transactional XML DatabaseIntegrating Lucene into a Transactional XML Database
Integrating Lucene into a Transactional XML Databaselucenerevolution
 
Gesture-aware remote controls: guidelines and interaction techniques
Gesture-aware remote controls: guidelines and interaction techniquesGesture-aware remote controls: guidelines and interaction techniques
Gesture-aware remote controls: guidelines and interaction techniquesDong-Bach Vo
 
[DL Hacks輪読] Semi-Supervised Learning with Ladder Networks (NIPS2015)
[DL Hacks輪読] Semi-Supervised Learning with Ladder Networks (NIPS2015)[DL Hacks輪読] Semi-Supervised Learning with Ladder Networks (NIPS2015)
[DL Hacks輪読] Semi-Supervised Learning with Ladder Networks (NIPS2015)Yusuke Iwasawa
 
Object Relational Mapping in PHP
Object Relational Mapping in PHPObject Relational Mapping in PHP
Object Relational Mapping in PHPRob Knight
 
Masterizing php data structure 102
Masterizing php data structure 102Masterizing php data structure 102
Masterizing php data structure 102Patrick Allaert
 
Building and deploying PHP applications with Phing
Building and deploying PHP applications with PhingBuilding and deploying PHP applications with Phing
Building and deploying PHP applications with PhingMichiel Rook
 
Semi supervised learning
Semi supervised learningSemi supervised learning
Semi supervised learningAhmed Taha
 
Extending Word2Vec for Performance and Semi-Supervised Learning-(Michael Mala...
Extending Word2Vec for Performance and Semi-Supervised Learning-(Michael Mala...Extending Word2Vec for Performance and Semi-Supervised Learning-(Michael Mala...
Extending Word2Vec for Performance and Semi-Supervised Learning-(Michael Mala...Spark Summit
 

Destaque (20)

Why do I love and hate php?
Why do I love and hate php?Why do I love and hate php?
Why do I love and hate php?
 
Reducing Database Pain & Costs with Postgres
Reducing Database Pain & Costs with PostgresReducing Database Pain & Costs with Postgres
Reducing Database Pain & Costs with Postgres
 
Design Patterns Reconsidered
Design Patterns ReconsideredDesign Patterns Reconsidered
Design Patterns Reconsidered
 
Creating "Secure" PHP Applications, Part 1, Explicit Code & QA
Creating "Secure" PHP Applications, Part 1, Explicit Code & QACreating "Secure" PHP Applications, Part 1, Explicit Code & QA
Creating "Secure" PHP Applications, Part 1, Explicit Code & QA
 
Fiksu Facebook report
Fiksu Facebook reportFiksu Facebook report
Fiksu Facebook report
 
Comparing the Multimodal Interaction Technique Design of MINT with NiMMiT
Comparing the Multimodal Interaction Technique Design of MINT with NiMMiTComparing the Multimodal Interaction Technique Design of MINT with NiMMiT
Comparing the Multimodal Interaction Technique Design of MINT with NiMMiT
 
Encoding survey
Encoding surveyEncoding survey
Encoding survey
 
Lca seminar modified
Lca seminar modifiedLca seminar modified
Lca seminar modified
 
Integrating Lucene into a Transactional XML Database
Integrating Lucene into a Transactional XML DatabaseIntegrating Lucene into a Transactional XML Database
Integrating Lucene into a Transactional XML Database
 
Gesture-aware remote controls: guidelines and interaction techniques
Gesture-aware remote controls: guidelines and interaction techniquesGesture-aware remote controls: guidelines and interaction techniques
Gesture-aware remote controls: guidelines and interaction techniques
 
Xml databases
Xml databasesXml databases
Xml databases
 
Algorithms and Data Structures~hmftj
Algorithms and Data Structures~hmftjAlgorithms and Data Structures~hmftj
Algorithms and Data Structures~hmftj
 
XML In My Database!
XML In My Database!XML In My Database!
XML In My Database!
 
[DL Hacks輪読] Semi-Supervised Learning with Ladder Networks (NIPS2015)
[DL Hacks輪読] Semi-Supervised Learning with Ladder Networks (NIPS2015)[DL Hacks輪読] Semi-Supervised Learning with Ladder Networks (NIPS2015)
[DL Hacks輪読] Semi-Supervised Learning with Ladder Networks (NIPS2015)
 
XML Databases
XML DatabasesXML Databases
XML Databases
 
Object Relational Mapping in PHP
Object Relational Mapping in PHPObject Relational Mapping in PHP
Object Relational Mapping in PHP
 
Masterizing php data structure 102
Masterizing php data structure 102Masterizing php data structure 102
Masterizing php data structure 102
 
Building and deploying PHP applications with Phing
Building and deploying PHP applications with PhingBuilding and deploying PHP applications with Phing
Building and deploying PHP applications with Phing
 
Semi supervised learning
Semi supervised learningSemi supervised learning
Semi supervised learning
 
Extending Word2Vec for Performance and Semi-Supervised Learning-(Michael Mala...
Extending Word2Vec for Performance and Semi-Supervised Learning-(Michael Mala...Extending Word2Vec for Performance and Semi-Supervised Learning-(Michael Mala...
Extending Word2Vec for Performance and Semi-Supervised Learning-(Michael Mala...
 

Semelhante a Singletons in PHP - Why they are bad and how you can eliminate them from your applications

Zend framework 03 - singleton factory data mapper caching logging
Zend framework 03 - singleton factory data mapper caching loggingZend framework 03 - singleton factory data mapper caching logging
Zend framework 03 - singleton factory data mapper caching loggingTricode (part of Dept)
 
The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016Kacper Gunia
 
Symfony2 - from the trenches
Symfony2 - from the trenchesSymfony2 - from the trenches
Symfony2 - from the trenchesLukas Smith
 
Lithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate FrameworksLithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate FrameworksNate Abele
 
Symfony2 from the Trenches
Symfony2 from the TrenchesSymfony2 from the Trenches
Symfony2 from the TrenchesJonathan Wage
 
Dependency Inversion and Dependency Injection in PHP
Dependency Inversion and Dependency Injection in PHPDependency Inversion and Dependency Injection in PHP
Dependency Inversion and Dependency Injection in PHPmtoppa
 
Building Testable PHP Applications
Building Testable PHP ApplicationsBuilding Testable PHP Applications
Building Testable PHP Applicationschartjes
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICKonstantin Kudryashov
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony AppsKris Wallsmith
 
Backbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVCBackbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVCpootsbook
 
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
 
Dependency injection in Drupal 8
Dependency injection in Drupal 8Dependency injection in Drupal 8
Dependency injection in Drupal 8Alexei Gorobets
 
[Srijan Wednesday Webinars] Ruling Drupal 8 with #d8rules
[Srijan Wednesday Webinars] Ruling Drupal 8 with #d8rules[Srijan Wednesday Webinars] Ruling Drupal 8 with #d8rules
[Srijan Wednesday Webinars] Ruling Drupal 8 with #d8rulesSrijan Technologies
 
Backbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The BrowserBackbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The BrowserHoward Lewis Ship
 
Migrating to dependency injection
Migrating to dependency injectionMigrating to dependency injection
Migrating to dependency injectionJosh Adell
 
Teste de Integração com DbUnit e jIntegrity
Teste de Integração com DbUnit e jIntegrityTeste de Integração com DbUnit e jIntegrity
Teste de Integração com DbUnit e jIntegrityWashington Botelho
 

Semelhante a Singletons in PHP - Why they are bad and how you can eliminate them from your applications (20)

Zend framework 03 - singleton factory data mapper caching logging
Zend framework 03 - singleton factory data mapper caching loggingZend framework 03 - singleton factory data mapper caching logging
Zend framework 03 - singleton factory data mapper caching logging
 
The IoC Hydra
The IoC HydraThe IoC Hydra
The IoC Hydra
 
The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016
 
Symfony2 - from the trenches
Symfony2 - from the trenchesSymfony2 - from the trenches
Symfony2 - from the trenches
 
Lithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate FrameworksLithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate Frameworks
 
Symfony2 from the Trenches
Symfony2 from the TrenchesSymfony2 from the Trenches
Symfony2 from the Trenches
 
Dependency Inversion and Dependency Injection in PHP
Dependency Inversion and Dependency Injection in PHPDependency Inversion and Dependency Injection in PHP
Dependency Inversion and Dependency Injection in PHP
 
Building Testable PHP Applications
Building Testable PHP ApplicationsBuilding Testable PHP Applications
Building Testable PHP Applications
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DIC
 
Unittests für Dummies
Unittests für DummiesUnittests für Dummies
Unittests für Dummies
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony Apps
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 
Backbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVCBackbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVC
 
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
 
Dependency injection in Drupal 8
Dependency injection in Drupal 8Dependency injection in Drupal 8
Dependency injection in Drupal 8
 
[Srijan Wednesday Webinars] Ruling Drupal 8 with #d8rules
[Srijan Wednesday Webinars] Ruling Drupal 8 with #d8rules[Srijan Wednesday Webinars] Ruling Drupal 8 with #d8rules
[Srijan Wednesday Webinars] Ruling Drupal 8 with #d8rules
 
Backbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The BrowserBackbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The Browser
 
Migrating to dependency injection
Migrating to dependency injectionMigrating to dependency injection
Migrating to dependency injection
 
Teste de Integração com DbUnit e jIntegrity
Teste de Integração com DbUnit e jIntegrityTeste de Integração com DbUnit e jIntegrity
Teste de Integração com DbUnit e jIntegrity
 
Design patterns in PHP
Design patterns in PHPDesign patterns in PHP
Design patterns in PHP
 

Último

Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
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
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdfChristopherTHyatt
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
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
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
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
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
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
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
🐬 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
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
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
 
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
 

Último (20)

Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
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
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdf
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
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
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
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
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
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
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
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
 
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
 

Singletons in PHP - Why they are bad and how you can eliminate them from your applications

  • 1. Singletons in Why they are bad and how you can eliminate them from your applications
  • 2. Gordon Oheim @go_oh
  • 3.
  • 6. Creational Pattern „control when and how objects are created“
  • 7. “Ensure a class has only one instance, and provide a global access point to it.”
  • 8. Singleton Singleton - instance : Singleton - instance : Singleton + + getInstance() getInstance() : : Singleton Singleton - - __construct() __construct() : : void void - - __clone() __clone() : : void void - - __wakeup() __wakeup() : : void void
  • 9. class Singleton … public static function getInstance() { if (!isset(self::$instance)) { self::$instance = new self; } return self::$instance; } }
  • 10. abstract class Singleton … public static function getInstance() { return isset(static::$instance) ? static::$instance : static::$instance = new static; } final private function __construct() { static::init(); } protected function init() {} } class A extends Singleton { protected static $instance; }
  • 11. trait Singleton … protected static $instance; final public static function getInstance() { return isset(static::$instance) ? static::$instance : static::$instance = new static; } final private function __construct() { static::init(); } protected function init() {} } class A { use Singleton; }
  • 12. „Nobody should need a mechanism to make it as easy as pie to clutter the code base with singletons“ - Sebastian Bergmann
  • 14. „In my stilted view of the universe anything that impedes testing is something to be avoided. There are those who don't agree with this view, but I'll pit my defect rates against theirs any time.“ - Robert „Uncle Bob“ C. Martin
  • 15. class TableDataGateway … public function __construct() { $this->db = Db::getInstance(); } public insert(array $data) { $this->db->sql('INSERT …', $data); } }
  • 16. class TableDataGatewayTest extends PHPUnit… /** * @dataProvider provideInsertData */ public function testInsertCallsDbWithData($data) { $gateway = new TableDataGateway; $gateway->insert($data); $this->assertSame( $data, $gateway->findById($data['id']) ); } }
  • 17. throws LogicException: No key found for 'pdo' in Registry
  • 18. class Db extends Singleton … protected function init() { $this->logger = Logger::getInstance(); $this->pdo = new PDO(Registry::get('pdo')); } public sql($query, $data) { $this->logger->log(printf( 'Executed %s with %s', $query, implode(',', $data) )); $sth = $this->pdo->prepare($query); return $sth->execute($data); } }
  • 19. Singletons are pathological liars - Miško Hevery
  • 20. class TableDataGatewayTest extends PHPUnit… /** * @dataProvider provideInsertData */ public function testInsertCallsDbWithData($data) { Registry::set('pdo', array('…')); Registry::set('log', '/dev/null'); $gateway = new TableDataGateway; $gateway->insert($data); $this->assertSame( $data, $gateway->findById($data['id']) ); } }
  • 21. Your tests are not isolated. You still need a real database. No easy way to mock the Db Singleton.
  • 22. „The real problem with Singletons is that they give you such a good excuse not to think carefully about the appropriate visibility of an object.“ - Kent Beck
  • 23. Hard to change code manifests itself in a cascade of subsequent changes in dependent code
  • 24. Fragile code breaks in many places when you change just one place
  • 25. Non-reusable code is code that you cannot reuse in another project because it contains too much extra baggage
  • 27. Single Responsibility Principle A class should have one, and only one, reason to change.
  • 28. Open Closed Principle You should be able to extend a classes behavior, without modifying it.
  • 29. Liskov Substitution Principle Derived classes must be substitutable for their base classes.
  • 30. Interface Segregation Principle Make fine grained interfaces that are client specific.
  • 31. Dependency Inversion Principle Depend on abstractions, not on concretions.
  • 33. SRP Violation Creation Logic + Business Logic = 2 reasons to change Mitigated by using Abstract Singletons But responsibilities are still strongly coupled through inheritance
  • 34. OCP Violation In PHP < 5.2 Singletons are closed for extending Boilerplate code has to be removed when no longer needed
  • 35. DIP Violation Global access breaks encapsulation Hides dependencies Adds concrete dependencies into Clients Signature lies
  • 37. Config FooController Response FrontController ThatService Request Cache Database Application BarController Registry Logger ThisService Bootstrap Acl
  • 38. Config FooController Response FrontController ThatService Request Cache Database Application BarController Registry Logger ThisService Bootstrap Acl
  • 39. Recap: “Ensure a class has only one instance, and provide a global access point to it.”
  • 40. „So much of the Singleton pattern is about coaxing language protection mechanisms into protecting this one aspect: singularity. I guess it is important, but it seems to have grown out of proportion.“ - Ward Cunningham
  • 41. You do not need to ensure singularity when you are going to instantiate the object only once anyway.
  • 42. You do not need to provide a Global Access Point when you can inject the object.
  • 43. class TableDataGateway … public function __construct() { $this->db = Db::getInstance(); } } class Db extends Singleton … protected function init() { $this->logger = Logger::getInstance(); $this->pdo = new PDO(Registry::get('pdo')); } }
  • 44. class TableDataGateway … public function __construct(Db $db) { $this->db = $db; } } class Db … public function __construct(PDO $pdo, Log $logger) { $this->logger = $logger; $this->pdo = $pdo; } }
  • 45. But then I have to push dependencies all the way through my object graph?!
  • 46. Recap: Creational Pattern „control when and how objects are created“
  • 47. Use Builders and Factories to create Collaborator Graphs
  • 48. class UserControllerBuilder { public function build($config) { $log = new Log($config['log']); $pdo = new PDO($config['…']); $db = new Db($pdo, $log); $tdg = new TableDataGateway($db); return new UserController($tdg); } }
  • 49. class UserControllerBuilder { public function build($config) { $log = new Log($config['log']); $pdo = new PDO($config['…']); ??? $db = new Db($pdo, $log); $tdg = new TableDataGateway($db); return new UserController($tdg); } }
  • 50. class UserControllerBuilder { public function build($config) { $db = new LogDecorator( new PDO($config['…']); new Log($config['log']); ); $tdg = new TableDataGateway($db); return new UserController($tdg); } }
  • 51. // index.php include '/path/to/autoload.php'; $config = new Config('/path/to/config.ini'); $router = new Router( array( '/user/{id}' => function() use ($config) { $builder = new UserControllerBuilder; return $builder->build($config); } ) ); $router->route( new Request($_GET, $_POST, $_SERVER), new Response );
  • 52. „Singletons aren't necessary when you can design or redesign to avoid using them.“ - Joshua Kerievsky
  • 53. „I'm in favor of dropping Singleton. Its use is almost always a design smell“ - Erich Gamma