“The principle of dependency inversion is at the root of many of the benefits claimed for object- oriented technology. Its proper application is necessary for the creation of reusable frameworks”
/** * @Inject */ public function setRenderer(RenderInterface $renderer) { ... 1.annotate at injection point class RendererModule extends AbstractModule { protected function configure() { $this->bind('RenderInterface') ->to('HalRenderer') ->in(Scope::SINGLETON); } $injector = new Injector(new RendererModule); 2 bind abstraction to concretion 3.create an injector
/** * @Inject */ public function setRenderer(RenderInterface $renderer) { ... 1.annotate at injection point class RendererModule extends AbstractModule { protected function configure() { $this->bind('RenderInterface') ->to('HalRenderer') ->in(Scope::SINGLETON); } $injector = new Injector(new RendererModule); 2. bind abstraction to concretion 3.create an injector
$injector = new Injector(new HalRendererModule); /** * @Inject */ public function setRenderer(RenderInterface $renderer) { ... 1.annotate at injection point class RendererModule extends AbstractModule { protected function configure() { $this->bind('RenderInterface') ->to('HalRenderer') ->in(Scope::SINGLETON); } 2 bind abstraction to concretion 3.create an injector
class RendererModule extends AbstractModule { protected function configure() { $this ->bind('RenderInterface') ->to('HalRenderer') ->in(Scope::SINGLETON); } } Use concrete class only in compile
$renderer = $injector->getInstance('UserInterface'); Only abstraction in runtime /** * @Inject */ public function __construct(RenderInterface $renderer) {
DI Best practice “Your code should deal directly with the Injector as little as possible. Instead, you want to bootstrap your application by injecting one root object.”
$app Object i/f i/f Object i/f i/f Object Router Response JSON XM L 1st framework: DI Framework • DI framework w/ binding DSL • compile / runtime separation • use only “socket” in runtime • application is single big one value • implement structure, not behavior
class SandboxResourcePageIndexRay0000000071f9ab280000000033fb446fAop extends Sandbox\Resource\Page\Index implements Ray\Aop\WeavedInterface { private $rayAopIntercept = true; public $rayAopBind; public function onGet() { // native call if (!isset($this->rayAopBind[__FUNCTION__])) { return call_user_func_array('parent::' . __FUNCTION__, func_get_args()); } // proceed source method from interceptor if (!$this->rayAopIntercept) { $this->rayAopIntercept = true; return call_user_func_array('parent::' . __FUNCTION__, func_get_args()); } // proceed next interceptor $this->rayAopIntercept = false; $interceptors = $this->rayAopBind[__FUNCTION__]; $annotation = isset($this->rayAopBind->annotation[__FUNCTION__]) ? $this->rayAopBind >annotation[__FUNCTION__] : null; $invocation = new \Ray\Aop\ReflectiveMethodInvocation(array($this, __FUNCTION__), func_get_args(), $interceptors, $annotation); return $invocation->proceed(); } Under the hood: Method interception sub class is created in order enable this interception and keep type safety.
Hypermedia framework for object as a service It allows objects to have RESTful web service benefits such as client-server, uniform interface, statelessness, resource expression with mutual connectivity and layered components.
https://www.infoq.com/jp/articles/webber-rest-workflow Figure1 The Customer State Machine Figure 2 The Barista's State Machine Hypermedia as the Engine of Application State