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