Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Why Lithium Sucks...

Why Lithium Sucks...

... Less than your Framework

Inspired by @nateabele and @jperras talk: http://www.slideshare.net/nateabele/lithium-the-framework-for-people-who-hate-frameworks

Mehdi Lahmam B.

June 11, 2013
Tweet

More Decks by Mehdi Lahmam B.

Other Decks in Programming

Transcript

  1. Why Lithium sucks
    MEHDI LAHMAM B.
    @mehlah

    View Slide

  2. Why Lithium sucks
    Less than your framework

    View Slide

  3. I’m Mehdi

    View Slide

  4. Object dependencies
    “The principle of separating configuration from use”

    View Slide

  5. function initialize(&$controller, $settings = []) {
    //...
    $prefixes = Router::prefixes();
    if (!empty($prefixes)) {
    foreach ($prefixes as $prefix) {
    // do something with the global state ...
    }
    }
    if (Configure::read() > 0) {
    App::import('Debugger');
    Debugger::checkSecurityKeys();
    }
    }
    Sucks
    Sucks hard !

    View Slide

  6. Configuration

    View Slide

  7. function spam($emails) {
    $this->Email->subject = 'Welcome to our really cool thing';
    $this->Email->replyTo = '[email protected]';
    $this->Email->from = 'Cool Web App ';
    $this->Email->template = 'simple_message';
    $this->Email->sendAs = 'both';
    foreach ($emails as $email) {
    $this->Email->to = $email['address'];
    $this->Email->subject = "Special offer for {$email['name']}";
    $this->Email->send();
    }
    } Sucks

    View Slide

  8. Dependency Injection

    View Slide

  9. class User {
    function __construct($storage) {
    $this->storage = $storage;
    }
    // ...
    }
    $storage = new SessionStorage('SESSION_ID');
    $user = new User($storage);
    Show that object who’s boss !

    View Slide

  10. Of course, we want to abstract this

    View Slide

  11. Of course, we want to abstract this
    Frameworks, adore abstraction

    View Slide

  12. Of course, we want to abstract this
    Frameworks, adore abstraction
    Fabien

    View Slide

  13. A DI story, in 6 parts

    View Slide

  14. $transport = new Zend_Mail_Transport_Smtp('smtp.gmail.com', array(
    'auth' => 'login',
    'username' => 'foo',
    'password' => 'bar',
    'ssl' => 'ssl',
    'port' => 465,
    ));
    $mailer = new Zend_Mail();
    $mailer->setDefaultTransport($transport);

    View Slide

  15. DI Container to the rescue !

    View Slide

  16. class Container {
    public function getMailTransport() {
    return new Zend_Mail_Transport_Smtp('smtp.gmail.com', array(
    'auth' => 'login',
    'username' => 'foo',
    'password' => 'bar',
    'ssl' => 'ssl',
    'port' => 465,
    ));
    }
    public function getMailer() {
    $mailer = new Zend_Mail();
    $mailer->setDefaultTransport($this->getMailTransport());
    return $mailer;
    }
    }

    View Slide

  17. class Container {
    public function getMailTransport() {
    return new Zend_Mail_Transport_Smtp('smtp.gmail.com', array(
    'auth' => 'login',
    'username' => 'foo',
    'password' => 'bar',
    'ssl' => 'ssl',
    'port' => 465,
    ));
    }
    public function getMailer() {
    $mailer = new Zend_Mail();
    $mailer->setDefaultTransport($this->getMailTransport());
    return $mailer;
    }
    }
    $container = new Container();
    $mailer = $container->getMailer();

    View Slide

  18. class Container {
    protected $parameters = array();
    public function __construct(array $parameters = array()) {
    $this->parameters = $parameters;
    }
    public function getMailTransport() {
    return new Zend_Mail_Transport_Smtp('smtp.gmail.com', array(
    'auth' => 'login',
    'username' => $this->parameters['mailer.username'],
    'password' => $this->parameters['mailer.password'],
    'ssl' => 'ssl',
    'port' => 465,
    ));
    }
    public function getMailer() {
    $mailer = new Zend_Mail();
    $mailer->setDefaultTransport($this->getMailTransport());
    return $mailer;
    }
    }

    View Slide

  19. $container = new Container(array(
    'mailer.username' => 'foo',
    'mailer.password' => 'bar',
    ));
    $mailer = $container->getMailer();

    View Slide

  20. The Dependency Injection Container in Symfony is managed
    by a class named sfServiceContainer.
    Fabien

    View Slide

  21. class Container extends sfServiceContainer {
    static protected $shared = array();
    protected function getMailTransportService() {
    return new Zend_Mail_Transport_Smtp('smtp.gmail.com', array(
    'auth' => 'login',
    'username' => $this['mailer.username'],
    'password' => $this['mailer.password'],
    'ssl' => 'ssl',
    'port' => 465,
    ));
    }
    protected function getMailerService() {
    if (isset(self::$shared['mailer'])) {
    return self::$shared['mailer'];
    }
    $class = $this['mailer.class'];
    $mailer = new $class();
    $mailer->setDefaultTransport($this->getMailTransportService());
    return self::$shared['mailer'] = $mailer;
    }
    }

    View Slide

  22. Of course now you want to abstract the crap out of the
    Service Container.
    http://fabien.potencier.org/article/13/introduction-to-the-symfony-service-container

    View Slide

  23. So let’s use a Builder to configure Services.

    View Slide

  24. require_once 'PATH/TO/sf/lib/sfServiceContainerAutoloader.php';
    sfServiceContainerAutoloader::register();
    $sc = new sfServiceContainerBuilder();
    $sc->
    register('mail.transport', 'Zend_Mail_Transport_Smtp')->
    addArgument('smtp.gmail.com')->
    addArgument(array(
    'auth' => 'login',
    'username' => '%mailer.username%',
    'password' => '%mailer.password%',
    'ssl' => 'ssl',
    'port' => 465,
    ))->
    setShared(false)
    ;
    $sc->
    register('mailer', '%mailer.class%')->
    addMethodCall('setDefaultTransport', array(new
    sfServiceReference('mail.transport')))
    ;

    View Slide

  25. And for good mesure, have our configurations for Service
    Containers in XML files.

    View Slide

  26. So ...
    we have Dependency Injection

    View Slide

  27. So ...
    we have Dependency Injection
    Managed by a Service Container

    View Slide

  28. So ...
    we have Dependency Injection
    Managed by a Service Container
    Parametrized with XML data (or YAML for cool boys)

    View Slide

  29. So ...
    we have Dependency Injection
    Managed by a Service Container
    Parametrized with XML data (or YAML for cool boys)
    And the whole thing configured by a Builder

    View Slide

  30. So ...
    we have Dependency Injection
    Managed by a Service Container
    Parametrized with XML data (or YAML for cool boys)
    And the whole thing configured by a Builder
    ... to fix one problem.

    View Slide

  31. Doh !

    View Slide

  32. Lithium tries to suck less

    View Slide

  33. Consistency

    View Slide

  34. namespace app\foo;
    use lithium\util\String;
    use lithium\util\Collection;
    class Foo extends \lihtium\core\Object {
    protected $_classes = [
    'logger' => 'lithium\analysis\Logger',
    'cache' => 'lithium\storage\Cache'
    ];
    public function __construct(array $config = []) {
    //...
    }
    protected function _init() {
    }
    }

    View Slide

  35. $foo = new Foo(['classes' => [
    'cache' => 'app\extensions\storage\cache'
    ]]);

    View Slide

  36. View Slide

  37. Auth
    Cache
    Catalog
    Connections
    Logger
    Session
    Adaptable

    View Slide

  38. Auth::config(['user' => [
    'adapter' => 'Form',
    'model' => 'Users',
    ]);

    View Slide

  39. Connections::config([
    'legacy' => array(
    'type' => 'database',
    'adapter' => 'MySQL'
    ),
    'new' => array(
    'type' => 'database',
    'adapter' => 'MongoDb'
    ),
    'funcky' => array(
    'type' => 'Http',
    'adapter' => 'CouchDb'
    )
    ]);

    View Slide

  40. Cache::config(array(
    'local' => array(
    'adapter' => 'Apc',
    ),
    'distributed' => array(
    'adapter' => 'Memcached',
    'servers' => ['127.0.0.1']
    ),
    'default' => array(
    'adapter' => 'File',
    )
    ));

    View Slide

  41. Aspect Oriented Design

    View Slide

  42. Posts::all()
    Logging
    Caching

    View Slide

  43. Posts::all()
    Logging
    Caching

    View Slide

  44. use lithium\analysis\Logger;
    Posts::applyFilter('find', function($self, $params, $chain) {
    Logger::write('info', 'A log message');
    return $chain->next($self, $params, $chain)
    }};

    View Slide

  45. Lithium tries to suck less

    View Slide

  46. http://lithify.me
    Sucks. But check it out anyway

    View Slide