SlideShare ist ein Scribd-Unternehmen logo
1 von 53
Downloaden Sie, um offline zu lesen
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

Weitere ähnliche Inhalte

Was ist angesagt?

Ossec Lightning
Ossec LightningOssec Lightning
Ossec Lightningwremes
 
淺談 Java GC 原理、調教和 新發展
淺談 Java GC 原理、調教和新發展淺談 Java GC 原理、調教和新發展
淺談 Java GC 原理、調教和 新發展Leon Chen
 
Advanced OSSEC Training: Integration Strategies for Open Source Security
Advanced OSSEC Training: Integration Strategies for Open Source SecurityAdvanced OSSEC Training: Integration Strategies for Open Source Security
Advanced OSSEC Training: Integration Strategies for Open Source SecurityAlienVault
 
[若渴計畫] Challenges and Solutions of Window Remote Shellcode
[若渴計畫] Challenges and Solutions of Window Remote Shellcode[若渴計畫] Challenges and Solutions of Window Remote Shellcode
[若渴計畫] Challenges and Solutions of Window Remote ShellcodeAj MaChInE
 
Linea de comandos bioface zem800
Linea de comandos bioface zem800Linea de comandos bioface zem800
Linea de comandos bioface zem800thomaswarnerherrera
 
qemu + gdb: The efficient way to understand/debug Linux kernel code/data stru...
qemu + gdb: The efficient way to understand/debug Linux kernel code/data stru...qemu + gdb: The efficient way to understand/debug Linux kernel code/data stru...
qemu + gdb: The efficient way to understand/debug Linux kernel code/data stru...Adrian Huang
 
Qemu device prototyping
Qemu device prototypingQemu device prototyping
Qemu device prototypingYan Vugenfirer
 
Introduction to EasyBuild: Tutorial Part 1
Introduction to EasyBuild: Tutorial Part 1Introduction to EasyBuild: Tutorial Part 1
Introduction to EasyBuild: Tutorial Part 1inside-BigData.com
 
Container Performance Analysis
Container Performance AnalysisContainer Performance Analysis
Container Performance AnalysisBrendan Gregg
 
AFLGo: Directed Greybox Fuzzing
AFLGo: Directed Greybox FuzzingAFLGo: Directed Greybox Fuzzing
AFLGo: Directed Greybox Fuzzingmboehme
 
DIREITO TRIBUTÁRIO OAB XX ESTRATÉGIA AULA 07
DIREITO TRIBUTÁRIO OAB XX ESTRATÉGIA AULA 07DIREITO TRIBUTÁRIO OAB XX ESTRATÉGIA AULA 07
DIREITO TRIBUTÁRIO OAB XX ESTRATÉGIA AULA 07Esdras Arthur Lopes Pessoa
 
Static partitioning virtualization on RISC-V
Static partitioning virtualization on RISC-VStatic partitioning virtualization on RISC-V
Static partitioning virtualization on RISC-VRISC-V International
 
Fuzzing malware for fun & profit. Applying Coverage-Guided Fuzzing to Find Bu...
Fuzzing malware for fun & profit. Applying Coverage-Guided Fuzzing to Find Bu...Fuzzing malware for fun & profit. Applying Coverage-Guided Fuzzing to Find Bu...
Fuzzing malware for fun & profit. Applying Coverage-Guided Fuzzing to Find Bu...Maksim Shudrak
 
[CB16] Invoke-Obfuscation: PowerShell obFUsk8tion Techniques & How To (Try To...
[CB16] Invoke-Obfuscation: PowerShell obFUsk8tion Techniques & How To (Try To...[CB16] Invoke-Obfuscation: PowerShell obFUsk8tion Techniques & How To (Try To...
[CB16] Invoke-Obfuscation: PowerShell obFUsk8tion Techniques & How To (Try To...CODE BLUE
 

Was ist angesagt? (17)

Ossec Lightning
Ossec LightningOssec Lightning
Ossec Lightning
 
淺談 Java GC 原理、調教和 新發展
淺談 Java GC 原理、調教和新發展淺談 Java GC 原理、調教和新發展
淺談 Java GC 原理、調教和 新發展
 
Advanced OSSEC Training: Integration Strategies for Open Source Security
Advanced OSSEC Training: Integration Strategies for Open Source SecurityAdvanced OSSEC Training: Integration Strategies for Open Source Security
Advanced OSSEC Training: Integration Strategies for Open Source Security
 
Linux Slab Allocator
Linux Slab AllocatorLinux Slab Allocator
Linux Slab Allocator
 
[若渴計畫] Challenges and Solutions of Window Remote Shellcode
[若渴計畫] Challenges and Solutions of Window Remote Shellcode[若渴計畫] Challenges and Solutions of Window Remote Shellcode
[若渴計畫] Challenges and Solutions of Window Remote Shellcode
 
Linea de comandos bioface zem800
Linea de comandos bioface zem800Linea de comandos bioface zem800
Linea de comandos bioface zem800
 
qemu + gdb: The efficient way to understand/debug Linux kernel code/data stru...
qemu + gdb: The efficient way to understand/debug Linux kernel code/data stru...qemu + gdb: The efficient way to understand/debug Linux kernel code/data stru...
qemu + gdb: The efficient way to understand/debug Linux kernel code/data stru...
 
Qemu device prototyping
Qemu device prototypingQemu device prototyping
Qemu device prototyping
 
Introduction to EasyBuild: Tutorial Part 1
Introduction to EasyBuild: Tutorial Part 1Introduction to EasyBuild: Tutorial Part 1
Introduction to EasyBuild: Tutorial Part 1
 
Container Performance Analysis
Container Performance AnalysisContainer Performance Analysis
Container Performance Analysis
 
AFLGo: Directed Greybox Fuzzing
AFLGo: Directed Greybox FuzzingAFLGo: Directed Greybox Fuzzing
AFLGo: Directed Greybox Fuzzing
 
DIREITO TRIBUTÁRIO OAB XX ESTRATÉGIA AULA 07
DIREITO TRIBUTÁRIO OAB XX ESTRATÉGIA AULA 07DIREITO TRIBUTÁRIO OAB XX ESTRATÉGIA AULA 07
DIREITO TRIBUTÁRIO OAB XX ESTRATÉGIA AULA 07
 
Static partitioning virtualization on RISC-V
Static partitioning virtualization on RISC-VStatic partitioning virtualization on RISC-V
Static partitioning virtualization on RISC-V
 
TO Hack an ASP .NET website?
TO Hack an ASP .NET website?  TO Hack an ASP .NET website?
TO Hack an ASP .NET website?
 
Responding to Cobalt Strike
Responding to Cobalt StrikeResponding to Cobalt Strike
Responding to Cobalt Strike
 
Fuzzing malware for fun & profit. Applying Coverage-Guided Fuzzing to Find Bu...
Fuzzing malware for fun & profit. Applying Coverage-Guided Fuzzing to Find Bu...Fuzzing malware for fun & profit. Applying Coverage-Guided Fuzzing to Find Bu...
Fuzzing malware for fun & profit. Applying Coverage-Guided Fuzzing to Find Bu...
 
[CB16] Invoke-Obfuscation: PowerShell obFUsk8tion Techniques & How To (Try To...
[CB16] Invoke-Obfuscation: PowerShell obFUsk8tion Techniques & How To (Try To...[CB16] Invoke-Obfuscation: PowerShell obFUsk8tion Techniques & How To (Try To...
[CB16] Invoke-Obfuscation: PowerShell obFUsk8tion Techniques & How To (Try To...
 

Andere mochten auch

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
 

Andere mochten auch (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...
 

Ähnlich wie 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
 

Ähnlich wie 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
 

Kürzlich hochgeladen

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
 
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
 
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
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
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
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
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
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAndrey Devyatkin
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century educationjfdjdjcjdnsjd
 
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
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 
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
 
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
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...apidays
 
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
 

Kürzlich hochgeladen (20)

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
 
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...
 
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
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
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
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
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
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
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
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
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...
 
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
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
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)
 

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