SlideShare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our User Agreement and Privacy Policy.
SlideShare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our Privacy Policy and User Agreement for details.
Successfully reported this slideshow.
Activate your 14 day free trial to unlock unlimited reading.
Lithium: The Framework for People Who Hate Frameworks, Tokyo Edition
32.
Dependency Injection
• Fixes the problem of static dependencies
• Ignores the problem of static relationships
• Same methods called on injected classes
• No way to introduce new relationships
• Higher overhead, more boilerplate code
33.
Dependency Injection
• Various attempts at making DI work better:
• DI Container
• Using dynamic nature of PHP to your
advantage.
34.
Coupling should be in
proportion to domain
relevance.
43.
Design patterns
• Each pattern is only useful in a limited
context
• Layering many design patterns on top of
each other often indicates poor design
choices
• Mis-application arises from trying to run
before you can walk
44.
Tools do not mean...
...you can build a house.
48.
Aspect-Oriented Design
• Separation of concerns
• Domain classes should not know or care about cross-
cutting concerns
• Examples:
• Caching
• Logging
• Access Control, etc.
49.
Functional Programming
• Only possible when functions are first-class
citizens
• Referential transparency
• Functional purity
50.
Referential transparency is not...
$this date()
$_*
51.
Referential transparency is not...
$this date()
$_*
56.
<?php
namespace applicationbar;
use lithiumutilString;
use lithiumutilCollection;
class Foo extends lithiumcoreObject {
protected $_classes = array(
'cache' => 'lithiumstorageCache',
'logger' => 'lithiumanalysisLogger'
);
public function __construct(array $config = array()) {
// ...
}
protected function _init() {
// ...
}
}
?>
57.
public function __construct(array $config = array())
<?php
public function __construct(array $config = array())
namespace applicationbar;
public function __construct(array $config = array())
use public function __construct(array $config = array())
lithiumutilString;
use lithiumutilCollection;
public function __construct(array $config = array())
class Foo extends lithiumcoreObject {
public function __construct(array $config = array())
protected $_classes = array(
public function'lithiumstorageCache', = array())
'cache' => __construct(array $config
'logger' => 'lithiumanalysisLogger'
public function __construct(array $config = array())
);
public function __construct(array $config = array()) {
// ...
}
public function __construct(array $config = array())
protected function _init() {
public function __construct(array $config = array())
// ...
}
public function __construct(array $config = array())
}
public function __construct(array $config = array())
?>
public function __construct(array $config = array())
58.
<?php
namespace applicationbar;
use lithiumutilString;
use lithiumutilCollection;
class Foo extends lithiumcoreObject {
protected $_classes = array(
'cache' => 'lithiumstorageCache',
'logger' => 'lithiumanalysisLogger'
);
public function __construct(array $config = array()) {
// ...
}
protected function _init() {
// ...
}
}
?>
59.
<?php
<?php
namespace applicationbar;
class Foo extends lithiumcoreObject
use lithiumutilString; {
use lithiumutilCollection;
protected function _init() {
class Foo extends lithiumcoreObject {
$or = $some->highOverHead($operation);
$or()->otherwise(HARD_TO_TEST)->code();
protected $_classes = array(
'cache' => 'lithiumstorageCache',
}
'logger' => 'lithiumanalysisLogger'
}
);
?>
public function __construct(array $config = array()) {
// ...
}
protected function _init() {
// ...
2
}
}
?>
60.
<?php
<?php
namespace applicationbar;
class Foo extends lithiumcoreObject
use lithiumutilString; {
use lithiumutilCollection;
protected function _init() {
class Foo extends lithiumcoreObject {
$or = $some->highOverHead($operation);
$or()->otherwise(HARD_TO_TEST)->code();
protected $_classes = array(
'cache' => 'lithiumstorageCache',
}
'logger' => 'lithiumanalysisLogger'
}
);
?>
public function __construct(array $config = array()) {
// ...
}
protected function _init() {
// ...
2
}
}
$foo = new Foo(array('init' => false));
?>
61.
<?php
namespace applicationbar;
use lithiumutilString;
use lithiumutilCollection;
class Foo extends lithiumcoreObject {
protected $_classes = array(
'cache' => 'lithiumstorageCache',
'logger' => 'lithiumanalysisLogger'
);
public function __construct(array $config = array()) {
// ...
}
protected function _init() {
// ...
}
}
?>
62.
<?php
namespace applicationbar; 3
use lithiumutilString;
use lithiumutilCollection;
new applicationbarFoo();
// loads app/bar/Foo.php
class Foo extends lithiumcoreObject {
protected $_classes = array(
'cache' => 'lithiumstorageCache',
'logger' => 'lithiumanalysisLogger'
);
public function __construct(array $config = array()) {
// ...
}
protected function _init() {
// ...
}
}
?>
63.
<?php
namespace applicationbar;
4
use lithiumutilString;
use lithiumutilCollection;
class Foo extends lithiumcoreObject {
protected $_classes = array(
'cache' => 'lithiumstorageCache',
'logger' => 'lithiumanalysisLogger'
);
public function __construct(array $config = array()) {
// ...
}
protected function _init() {
// ...
}
}
?>
64.
<?php
namespace applicationbar;
use lithiumutilString;
use lithiumutilCollection;
class Foo extends lithiumcoreObject {
protected $_classes = array(
'cache' => 'lithiumstorageCache',
'logger' => 'lithiumanalysisLogger' 5
);
public function __construct(array $config = array()) {
// ...
}
protected function _init() {
// ... = $this->_classes['cache'];
$cache
} $cache::write(__CLASS__, $this->_someGeneratedValue());
} }
}
?>
?>
65.
<?php
namespace applicationbar;
use lithiumutilString;
use lithiumutilCollection;
class Foo extends lithiumcoreObject {
protected $_classes = array(
'cache' => 'lithiumstorageCache',
'logger' => 'lithiumanalysisLogger' 5
);
$foo = new Foo(array('classes' => array(
public function __construct(array $config = array()) {
'cache' => 'applicationextensionsCache'
// ...
)));
}
protected function _init() {
// ... = $this->_classes['cache'];
$cache
} $cache::write(__CLASS__, $this->_someGeneratedValue());
} }
}
?>
?>
66.
<?php
namespace applicationbar;
use lithiumutilString;
use lithiumutilCollection;
class Foo extends lithiumcoreObject {
protected $_classes = array(
'cache' => 'lithiumstorageCache',
'logger' => 'lithiumanalysisLogger'
);
public function __construct(array $config = array()) {
// ...
}
protected function _init() {
// ... = $this->_classes['cache'];
$cache
} $cache::write(__CLASS__, $this->_someGeneratedValue());
} }
}
?>
?>
86.
Zoom?
• Performance vs. speed of development is a
series of trade-offs
• Large-scale apps don’t use stock framework
infrastructure, and that’s a good thing
• A generalized framework will never be as
fast as hand-tuned code
87.
Zoom!
• Choice is good
• Use native extensions (PECL) whenever
possible.
• Don’t like a class? Change it. At runtime.
• Profiled at every step of the way with
XHProf and XDebug cachegrinds.
99.
use lithiumanalysisLogger;
Post Logger
Post::applyFilter('find', function($self, $params, $chain) {
// Generate the log message
$conditions = $params['options']['conditions'];
$message = 'Post query with constraint ' . var_export($conditions, true);
Logger::write('info', $message);
return $chain->next($self, $params, $chain);
});
100.
What about Observer?
• Dependent on a centralized publish/
subscribe system
• Extra layer of abstraction
• Fewer possibilities
101.
What about Observer?
• Filters are self-contained and attach
directly to objects
• Direct and intuitive
102.
Features: Everything is an adapter.
(well, almost)
103.
Databases
• 1st-class support for document-oriented
databases
• MongoDB & CouchDB: production ready
• Relational databases in beta
• Cassandra/Redis/Riak in the works, too
109.
Databases
• Adapter based, plugin aware
• Will ship with MySQL, SQLite & PostgreSQL
• SQL Server support via plugin
• Query API
110.
The Query API
• Flexible data container
• Allows each backend data store to only worry
about features it implements
• Keeps model API separate from backend data
sources
113.
The Query API
• Run simple queries via the Model API
• Build your own complex queries with the
Query API
• Create your own adapter, or drop in a
custom query optimizer
115.
Plays nice with others
• Easily load & use libraries from other
frameworks:
• Zend Framework, Solar, Symfony, PEAR,
etc.
• PSR-0 Class-loading standard