Zend framework 03 - singleton factory data mapper caching logging


Published on

Singleton & Factory, Dependency Injection, Data Mapper, Caching and Logging.

Published in: Technology
  • Be the first to comment

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide
  • Cons: 1. Hides dependencies - A component that uses one or more singletons is hiding crucial information about your dependencies. It doesn’t take long for calls to a singleton to creep through your code base like kudzu, slowly attaching itself to every class in the system. Exposing that dependency forces you to think about it as you use a component. It also makes it more reusable as the caller can understand its requirements and how they might be satisfied. 2. Hard to test - The hidden coupling of users on a singleton makes testing a nightmare as there is no way to mock out or inject a test instance of the singleton. Also, the state of the singleton affects the execution of a suite of tests such that they are not properly isolated from each other. 3. Hard to subclass - Since initialization occurs in a singleton in static code, it is not amenable to subclassing because subclasses inherit the initialization code without the chance to override it. 4. A singleton today is a multiple tomorrow - It’s not at all unusual to discover that you now need 2 or more of something you previously only needed one of. Hard-coding the singleton pattern into your code makes it impossible to satisfy that demand later. Think Upc_Pe_Db class..
  • Zend framework 03 - singleton factory data mapper caching logging

    1. 1. Zend Framework 3. Singleton & Factory, Dependency Injection, Data Mapper, Caching, Logging Tricode Professional Services www.tricode.nl Date: 27-02-2009 Authors: Marcel Blok Patrick van Dissel
    2. 2. Singleton <ul><li>“ Ensure a class only has one instance, and provide a global point of access to it.” </li></ul><ul><li>– GoF </li></ul>
    3. 3. Singleton class Logger { /** * @var Logger */ private static $instance = null; private function __construct () {} private function __clone() {} /** * @return Logger */ public static function getInstance() { if (! self :: $instance instanceof self ) { self :: $instance = new self (); } return self :: $instance ; } } <?php $a = Logger::getInstance(); $a ->methodX(..); $b = Logger::getInstance(); $a ->methodX(..); $a === $b
    4. 4. Singleton <ul><li>Pros: </li></ul><ul><ul><li>There's always only one instance of the class </li></ul></ul><ul><ul><li>Easy to use </li></ul></ul><ul><li>Cons: </li></ul><ul><ul><li>Hides dependencies </li></ul></ul><ul><ul><li>Hard to test </li></ul></ul><ul><ul><li>Hard to subclass </li></ul></ul><ul><ul><li>A singleton today is a multiple tomorrow </li></ul></ul><ul><ul><li>It's a global variable! Globals are bad! So use with caution </li></ul></ul>
    5. 5. Dependency Injection <ul><li>“ Dependency Injection refers to the process of supplying an external dependency to a software component.” </li></ul>
    6. 6. Dependency Injection How can Dependency Injection be applied to the following code? <?php class Book { public function __construct() { $this ->_databaseConnection = new DatabaseConnection(); // or global $databaseConnection ; $this ->_databaseConnection = $databaseConnection ; } }
    7. 7. Dependency Injection <ul><li>What does this mean for your code? </li></ul><ul><ul><li>Enforce that an external dependency is provided to a class. Not instanciated and configured within the class itself </li></ul></ul><ul><ul><li>More reusable code </li></ul></ul><ul><ul><li>More testable code </li></ul></ul>
    8. 8. Dependency Injection How is this? <?php class Book { public function __construct() { } public function setDatabaseConnection( $databaseConnection ) { $this ->_databaseConnection = $databaseConnection ; } } $book = new Book(); $book ->setDatabase( $databaseConnection );
    9. 9. Dependency Injection How is this? <?php class Book { public function __construct( $databaseConnection ) { … } protected function setDatabaseConnection( $databaseConnection ) { $this ->_databaseConnection = $databaseConnection ; } } $book = new Book( $databaseConnection );
    10. 10. Dependency Injection How is this? <?php class Factory { private static $_database; public static function makeBook() { $book = new Book(); $book ->setDatabase( self ::$_database ); // more injection... return $book ; } public static function setup( $database ) { …. } } $book = Factory::makeBook();
    11. 11. Dependency Injection <ul><li>Dependency Injection makes sure classes have: </li></ul><ul><ul><li>High coherence </li></ul></ul><ul><ul><li>Low coupling </li></ul></ul><ul><li>What results in: </li></ul><ul><ul><li>Reduced Dependencies </li></ul></ul><ul><ul><li>Reduced Dependency Carrying </li></ul></ul><ul><ul><li>More Reusable Code </li></ul></ul><ul><ul><li>More Testable Code </li></ul></ul><ul><ul><li>More Readable Code </li></ul></ul>
    12. 12. Dependency Injection <ul><li>Where should objects be instantiating and configured? </li></ul><ul><ul><li>On the highest layer, eg. in the controller or in a factory </li></ul></ul><ul><li>Doesn't that make the controller huge? </li></ul><ul><ul><li>Yes, it makes the controller bigger. But also more in control and without surprises </li></ul></ul>
    13. 13. Factory <ul><li>“ Provide an interface for creating families of related or dependent objects without specifying their concrete classes.” </li></ul><ul><li>– GoF </li></ul>
    14. 14. Factory <ul><li>Benefits: </li></ul><ul><ul><li>A good alternative for the singleton pattern </li></ul></ul><ul><ul><li>Takes care of initiating objects </li></ul></ul><ul><ul><li>Can take care of configuring objects </li></ul></ul>
    15. 15. Factory <?php class Factory { private static $_database; public static function makeBook() { $book = new Book(); $book ->setDatabase( self ::$_database ); // more injection... return $book ; } public static function setup( $database ) { …. } } $book = Factory::makeBook();
    16. 16. Persistency <ul><li>Very good ways to persist objects are nowadays: </li></ul><ul><li>Object-relational DBMS (ORDBMS) </li></ul><ul><li>Object-orientated DBMS (OODBMS) </li></ul><ul><li>Space based architectures (SBA) </li></ul>
    17. 17. Persistency <ul><li>Unfortunately often we have legacy data that is </li></ul><ul><li>stored and structured in: </li></ul><ul><li>RDMS </li></ul><ul><li>XML </li></ul><ul><li>Text files </li></ul><ul><li>Etc. </li></ul>
    18. 18. Object-relational impedance mismatch <ul><li>The biggest challenge in persisting objects to </li></ul><ul><li>relational database management systems is the </li></ul><ul><li>mismatch between objects and tables. </li></ul>
    19. 19. Object-relational impedance mismatch  Database model Object model 
    20. 20. Data mapper Pattern <ul><li>In order to stick to good OO design rules the code </li></ul><ul><li>for the object itself and for the mapping should be </li></ul><ul><li>separated (high cohesion). </li></ul><ul><li>The Mapper should know of the object, the object </li></ul><ul><li>not of the Mapper (low coupling) </li></ul>
    21. 21. Data mapper Pattern
    22. 22. Database connection <ul><li>It is good practice to separate the code for creating the database connection from the Data Mapper (high cohesion) </li></ul>
    23. 23. Database connection Like a singleton
    24. 24. Database connection With a factory
    25. 25. Lazy loading <ul><li>Load the data as late as possible </li></ul><ul><li>Lazy initialization Set initially to null and every request checks this </li></ul><ul><li>Virtual proxy A proxy object with the same interface that loads the requested object </li></ul><ul><li>Ghost Initialize with only ID, load the remainder when needed </li></ul><ul><li>Value holder Use a generic object that handles the lazy loading </li></ul>
    26. 26. Aggressive loading <ul><li>Load all data as soon as the object is instantiated. </li></ul><ul><li>In some cases aggressive loading is more </li></ul><ul><li>appropriate: </li></ul><ul><li>All (or most) data is always needed </li></ul><ul><li>Resource costs are low (time, memory) </li></ul>
    27. 27. Zend_Cache Algorithm: No $data = false ; $data = $cache ->get(‘myKey’); if ( false === $data ) { $data = $db ->fetchOne(...); $cache ->save( $data , ‘myKey’); } echo $data ;
    28. 28. Zend_Cache <ul><li>Frontend: How to cache </li></ul><ul><li>Backend: Where to cache it </li></ul><ul><li>Used by several other components in the framework </li></ul><ul><li>Use caching where possible to limit the number of requests to slow resources, eg. database queries </li></ul>
    29. 29. Zend_Cache <ul><li>Theory: </li></ul><ul><li>Lifetime: every entry in the cache expires at some point </li></ul><ul><li>Commonly used methods: </li></ul><ul><ul><li>get(): returns false when nothing found (a miss) </li></ul></ul><ul><ul><li>save() </li></ul></ul><ul><ul><li>remove() </li></ul></ul>
    30. 30. Zend_Cache: Frontend <ul><li>Different methods of caching: </li></ul><ul><li>Zend_Cache_Core (abstract) </li></ul><ul><li>Zend_Cache_Frontend_Output </li></ul><ul><li>Zend_Cache_Frontend_Function </li></ul><ul><li>Zend_Cache_Frontend_Class </li></ul><ul><li>Zend_Cache_Frontend_File </li></ul><ul><li>Zend_Cache_Frontend_Page </li></ul>
    31. 31. Zend_Cache: Backend <ul><li>Generic interface for different cache backends </li></ul><ul><ul><li>File (on disk) </li></ul></ul><ul><ul><li>Sqlite (database) </li></ul></ul><ul><ul><li>Memcached (in memory, distributed) </li></ul></ul><ul><ul><li>APC (opcode cache) </li></ul></ul><ul><ul><li>Xcache (opcode cache) </li></ul></ul><ul><ul><li>ZendPlatform (disk) </li></ul></ul><ul><ul><li>TwoLevels (combination of two above methods) </li></ul></ul>
    32. 32. Zend_Log $logger = new Zend_Log(); $logger ->log(‘log this message’, Zend_Log::INFO); $logger ->info(‘log this message’);
    33. 33. Zend_Log Log priorities Debug messages 7 Zend_Log::DEBUG Informational messages 6 Zend_Log::INFO Notice: normal but significant conditions 5 Zend_Log::NOTICE Warning: warning conditions 4 Zend_Log::WARN Error: error conditions 3 Zend_Log::ERR Critical: critical conditions 2 Zend_Log::CRIT Alert: action must be taken immediately 1 Zend_Log::ALERT Emergency: system is unusable 0 Zend_Log::EMERGE Usage Value Name
    34. 34. Zend_Log Log writers Discards all log messages. This can be useful for turning off logging during testing or for disabling logging Zend_Log_writer_Null Sends log messages to the console in the Firebug extension of Firefox Zend_Log_writer_Firebug Stores logs to database records. You need to map the level and messages to two fields within a table Zend_Log_writer_Db Stores logs to files or other streams. The ‘php://output’ stream can be used to display to the output buffer Zend_Log_writer_Stream When to use Name
    35. 35. Zend_Log $logger = new Zend_Log(); // Log Warnings, Notices and Informational messages $writerMessages = new Zend_Log_Writer_Stream ($logsPath . 'messages.log'); $messageFilter1 = new Zend_Log_Filter_Priority(Zend_Log::WARN, '>='); $messageFilter2 = new Zend_Log_Filter_Priority(Zend_Log::INFO, '<='); $writerMessages ->addFilter( $messageFilter1 ); $writerMessages ->addFilter( $messageFilter2 ); $logger ->addWriter( $writerMessages );
    36. 36. References <ul><li>Singleton and Dependency Injection </li></ul><ul><ul><li>http://googletesting.blogspot.com /2008/11/clean-code-talks-global-state-and.html </li></ul></ul><ul><ul><li>http://en.wikipedia.org/wiki/Singleton_pattern </li></ul></ul><ul><ul><li>http://www.potstuck.com/2009/01/08/php-dependency-injection/ </li></ul></ul><ul><li>Anti-Patterns </li></ul><ul><ul><li>http:// en.wikipedia.org/wiki/Anti_pattern </li></ul></ul>