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

Destaque

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
 
PHP 7 – What changed internally? (PHP Barcelona 2015)
PHP 7 – What changed internally? (PHP Barcelona 2015)PHP 7 – What changed internally? (PHP Barcelona 2015)
PHP 7 – What changed internally? (PHP Barcelona 2015)Nikita Popov
 
Biomolecular interaction analysis (BIA) techniques
Biomolecular interaction analysis (BIA) techniquesBiomolecular interaction analysis (BIA) techniques
Biomolecular interaction analysis (BIA) techniquesN Poorin
 
HTTP cookie hijacking in the wild: security and privacy implications
HTTP cookie hijacking in the wild: security and privacy implicationsHTTP cookie hijacking in the wild: security and privacy implications
HTTP cookie hijacking in the wild: security and privacy implicationsPriyanka Aash
 
LCA and RMQ ~簡潔もあるよ!~
LCA and RMQ ~簡潔もあるよ!~LCA and RMQ ~簡潔もあるよ!~
LCA and RMQ ~簡潔もあるよ!~Yuma Inoue
 

Destaque (19)

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...
 
PHP 7 – What changed internally? (PHP Barcelona 2015)
PHP 7 – What changed internally? (PHP Barcelona 2015)PHP 7 – What changed internally? (PHP Barcelona 2015)
PHP 7 – What changed internally? (PHP Barcelona 2015)
 
Biomolecular interaction analysis (BIA) techniques
Biomolecular interaction analysis (BIA) techniquesBiomolecular interaction analysis (BIA) techniques
Biomolecular interaction analysis (BIA) techniques
 
HTTP cookie hijacking in the wild: security and privacy implications
HTTP cookie hijacking in the wild: security and privacy implicationsHTTP cookie hijacking in the wild: security and privacy implications
HTTP cookie hijacking in the wild: security and privacy implications
 
LCA and RMQ ~簡潔もあるよ!~
LCA and RMQ ~簡潔もあるよ!~LCA and RMQ ~簡潔もあるよ!~
LCA and RMQ ~簡潔もあるよ!~
 

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

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
 
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
 
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
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
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
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfhans926745
 
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
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 
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
 
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
 
🐬 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
 
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
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilV3cube
 
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
 
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
 
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
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessPixlogix Infotech
 
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
 

Último (20)

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
 
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...
 
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
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
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
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
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
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
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
 
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
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
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
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
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...
 
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
 
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
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
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
 

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