Post on 15-Jul-2015
Dependency InversionSOLID
High-level modules should not depend on low-level modules. Both should depend on abstractions.
http://en.wikipedia.org/wiki/Dependency_inversion_principle
class UserModify { public function __constructor() {
$this->storage = new MysqlStorage(); }
public function modify($data) { $result = $this->storage->save($data); return $result;
} }
⾼高階直接依賴低階
class UserModify { public function __constructor(DataStorageInterface $storage) {
$this->storage = $storage; }
public function modify($data) { $result = $this->storage->save($data); return $result;
} }
class MysqlStorage implements DataStorageInterface { public function save($data){ // …. }
}
interface DataStorageInterface { public function save(array $data);
}
Abstraction
Low Level Module
Hight Level Module
隱藏低階模組的細節
class UserModify { public function __constructor() { $dbConfig = [….];
$this->storage = new MysqlStorage($dbConfig); }
}
容易抽換實作
class UserModify { public function __constructor(DataStorageInterface $storage) {
$this->storage = $storage; }
}
class SqliteStorage implements DataStorageInterface { public function save($data){ // …. }
}
SqliteStorage Instance
讓測試變容易
class DummyStorage implements DataStorageInterface { public function save() { return ‘Success’; }
}
class UserModify { public function modify($data) {
return $this->storage->save($data); }
}
class UserModifyTest { public function it_return_new_instance_after_modify($data) {
$instance = new UserModify(new DummyStorage); $result = $instance->modify();
assert($result, ‘Success’); }
}
Inverse of Control
http://zh.wikipedia.org/wiki/%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC
Dependency Injection
http://en.wikipedia.org/wiki/Dependency_injection
Dependency injection is a software design pattern that implements inversion of control for software libraries, where the caller delegates to an external framework the control flow of discovering and importing a service or software module.
.
├── AppServiceProvider.php
├── BusServiceProvider.php
├── ConfigServiceProvider.php
├── EventServiceProvider.php
├── FilterServiceProvider.php
├── RepoServiceProvider.php
└── RouteServiceProvider.php
app/Providers
<?php namespace Backend\Providers; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { public function register() {
$this->app->bind( ‘Jaster/Interfaces/FooInterface’, ‘Jaster/Implements/FooImplementClass’ ); }}
app/Providers/AppServiceProvider.php
'providers' => [ /* * Laravel Framework Service Providers... */ 'Illuminate\Foundation\Providers\ArtisanServiceProvider', 'Illuminate\Auth\AuthServiceProvider', 'Illuminate\Bus\BusServiceProvider', 'Illuminate\Cache\CacheServiceProvider', 'Illuminate\Foundation\Providers\ConsoleSupportServiceProvider', 'Illuminate\Routing\ControllerServiceProvider',
// ….],
config/app.php
Service Container
The Laravel service container is a powerful tool for managing class dependencies. Dependency injection is a fancy word that essentially means this: class dependencies are "injected" into the class via the constructor or, in some cases, "setter" methods.
http://laravel.com/docs/5.0/container
Trace initialize of service container ( Illuminate\Foundation\Application )
Illuminate\Foundation\Application::__construct
Illuminate\Foundation\Application::registerBaseBindings
Illuminate\Foundation\Application::registerBaseServiceProviders
Illuminate\Foundation\Application::registerCoreContainerAliases
Trace register of Illuminate\Contracts\Http\Kernel
bootstrap/app.php $app->singleton(‘Illuminate\Contracts\Http\Kernel', 'App\Http\Kernel');
Illuminate\Foundation\Application::singleton
Illuminate\Foundation\Application::bind
Trace how to use Illuminate\Contracts\Http\Kernel
$kernel = $app->make('Illuminate\Contracts\Http\Kernel');public/index.php
Illuminate\Foundation\Application::make
Illuminate\Container\Container::make
Illuminate\Container\Container::build
Trace Facade autoloader
Illuminate\Foundation\Http\Kernel::bootstrap
Illuminate\Foundation\Application::bootstrapWith
Illuminate\Foundation\Bootstrap\RegisterFacades
Illuminate\Foundation\AliasLoader::register
Illuminate\Foundation\AliasLoader::prependToLoaderStack
PHP UK Conference 2014 - Stephan Hochdorfer - The 7 Deadly Sins of Dependency Injection
https://www.youtube.com/watch?v=hMix8gfDy54