BEAR.Sunday (2017)

BEAR.Sunday (2017)

A resource orientated framework using the DI /AOP/REST Triangle

Aad26cd7119bd8c0c2bbea107515716d?s=128

Akihito Koriyama

October 17, 2016
Tweet

Transcript

  1. A resource orientated framework using the DI /AOP/REST Triangle BEAR.Sunday

    (2017)
  2. None
  3. BEAR.Sunday is an application framework. But it offers no libraries.

    (We have good stuff)
  4. instead, it offers three object frameworks.

  5. What is framework ?

  6. “imposes a set of design constraints on end-user code.”

  7. None
  8. None
  9. 3.hypermedia framework

  10. DI benefits • Dependency inversion principle (DIP) • Object instantiation

    / usage separation
  11. DIP • Code should depend on things that are at

    the same or higher level of abstraction • High level policy should not depend on low level details
  12. “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”
  13. Ray.DI dependency injection framework

  14. /** * @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
  15. /** * @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
  16. $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
  17. $user = $injector->getInstance('UserInterface');
 4. Get the object with dependent User

    Render er Renderer Interface depends A B
  18. QSPDFEVSBM PCKFDUPSJFUOFE DPNQJMF SVOUJNF Implement the structure, not a procedure

  19. class RendererModule extends AbstractModule { protected function configure() { $this

    ->bind('RenderInterface') ->to('HalRenderer') ->in(Scope::SINGLETON); } } Use concrete class only in compile
  20. $renderer = $injector->getInstance('UserInterface');
 Only abstraction in runtime /** * @Inject

    */ public function __construct(RenderInterface $renderer) {
  21. 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.”
  22. Application = one root object

  23. Application class

  24. None
  25. Application is root object retrieved with injector:
 
 
 


    
 app name app context
  26. Application has dependency.

  27. Dependency has dependency and so on.. Object is either contain

    or belonged
  28. You get a application object graph. huge, but can be

    stored one single root value $app
  29. "QQMJDBUJPODBOCFTFSJBMJ[FE $app can be serialized and stored Injection is reused

    beyond requests.
  30. $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
  31. Aspect Oriented Programing

  32. What is AOP? Cache Log Auth A programming paradigm that

    aims to increase modularity by allowing the separation of cross-cutting concerns
  33. /** * @Cacheable */
 class Post { public function onGet($id)

    { // ... $this->body = $stmt->fetchAll(PDO::FETCH_ASSOC); return $this; } class Post extends AppModel { public function newest() { $result = Cache::read('newest_posts', 'longterm'); if (!$result) { $result = $this->find('all'); Cache::write('newest_posts', $result, 'longterm'); } return $result; } }
  34. M C I I AOP

  35. M C Cache Cache is called by method invocation,
 If

    the cache is warm the model is never called. $obj->read(2); Miss !
  36. Aspects Core Concern Cross Cutting Concern Separation

  37. Rock Concert Example

  38. interface MethodInterceptor { public function invoke(MethodInvocation $invocation); } 


  39. class Transactional implements MethodInterceptor { public function invoke(MethodInvocation $invocation) {

    $object = $invocation->getThis(); $ref = new ReflectionProperty($object, 'db'); $ref->setAccessible(true); $db = $ref->getValue($object); $db->beginTransaction(); try { $invocation->proceed(); $db->commit(); } catch (Exception $e) { $db->rollback(); } } } Transactional interceptor Core Concern Cross Cutting Concern
  40. class CacheInterceptor implements MethodInterceptor { public function invoke(MethodInvocation $invocation) {

    $obj = $invocation->getThis(); $args = $invocation->getArguments(); $id = get_class($obj) . serialize($args); $saved = $this->cache->fetch($id); if ($saved) { return $saved; } $result = $invocation->proceed(); $this->cache->save($id, $result); return $result; } } Core Concern Cross Cutting Concern Cache interceptor
  41. 4JNQMZBOOPUBUF  UIFODSFBUFZPVSCJOEJOH #JOE

  42. Layering by context • MVC, Is 3 enough ?

  43. API Client

  44. API Log Client Valid Auth

  45. API Log !7BMJE BENJO %&-&5& Client Valid Auth

  46. Aspect layering by context Model Cache Form Transaction Auth Validation

  47. <?php 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.
  48. Runtime injection by aspect • method / parameter lookup •

    test friendly
  49. 2nd framework: Aspect Oriented Framework • AOP alliance standard •

    Layering by context • Type safe • Runtime injection
  50. None
  51. 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.
  52. CLI Web

  53. Embedded Resource

  54. None
  55. Linked Resource

  56. None
  57. None
  58. Web Context Parameter

  59. Resource Parameter

  60. 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
  61. Hypermedia as the Engine of Application State

  62. Order Payment hyper reference: payment Hypermedia Driven API

  63. Content-Type: application/hal+json

  64. https://www.infoq.com/jp/news/2014/03/amazon-hal-appstream

  65. The key of success of web • URI • Unified

    Interface • Hyperlink
  66. • API is hub • API is core value API

    driven development DB Mobil e Web API Cloud Moc k URI API API
  67. http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html

  68. Layered Resource UI Mobile Web Page Resource App script App

    Resource Entity
  69. None
  70. None
  71. 1. Entry file

  72. 2. Application script ᶃ create root object with context ᶄ

    304 ? ᶅ create request ᶆ invoke request ᶇ transfer
  73. 3. Resource state

  74. 3. Representation state transfer

  75. Performance • annotation ? dependency injection ? 
 method interception

    ? DSL ? named parameter ? • Fast • cache all compiled object • generate raw factory code • http friendly architecture
  76. Scale • “model proxy” pattern • ‘app://self/blog/entry’ can be anything.

    • contextual injection makes db scale easy • assisted injection
  77. Hard spot / Soft spot • DI configure hard spot.

    QFSTZTUFN • Aop configure softspot, change on request

  78. Connecting frameworks • DI - object as dependency • AOP

    - domain logic to application logic • Hypermedia - resource to resource
  79. Abstraction frameworks • DSL • Annotation • URI • Interface

    • Aspects • Hypermedia
  80. AOP (Gregor Kiczales) DI (Martin Fowler) REST (Roy Fielding) OOP

    (Allan Kay) Annotation (Anders Hejlsberg) Guice (Bob Lee)
  81. None
  82. “Zen” framework

  83. Thanks. http://www.flickr.com/photos/stevehoad/4678289858/ @mackstar @koriym