Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

A resource oriented framework using the DI/AOP/REST triangle

5,490 views

Published on

https://joind.in/talk/view/9302

Published in: Technology
  • Be the first to comment

A resource oriented framework using the DI/AOP/REST triangle

  1. 1. A resource orientated framework using the DI /AOP/REST Triangle
  2. 2. About Us • Akihito Koriyama • A Tokyo based freelance PHP architect • BEAR.Sunday lead, Aura PHP member • Richard McIntyre • Manchester / leeds based freelance PHP developer • BEAR.Sunday contributor, Lithium member
  3. 3. About Us • Akihito Koriyama • A Tokyo based freelance PHP architect • BEAR.Sunday lead, Aura PHP member • Richard McIntyre • Manchester / Leeds based freelance PHP developer • BEAR.Sunday contributor, Lithium member
  4. 4. BEAR.Sunday is an application framework. But it offers no libraries. (We have good stuff)
  5. 5. instead, it offers three object frameworks.
  6. 6. What is a framework ?
  7. 7. “imposes a set of design constraints on end-user code.”
  8. 8. 3.hypermedia framework
  9. 9. DI AOP REST
  10. 10. DI Benefits • Dependency Inversion Principle • Clear separation of object instantiation and object usage • Object delivery
  11. 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. 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. 13. Ray.DI Dependency Injection Framework
  14. 14. /** * @Inject */ public function __construct(RenderInterface $renderer) { ... 1.annotate at injection point class RendererModule extends AbstractModule { protected function configure() { $this->bind('RenderInterface') ->to('HalRenderer') ->in(Scope::SINGLETON); } $injector = Inject::create([new RendererModule]]; 2 bind abstraction to concretion 3.create an injector
  15. 15. /** * @Inject */ public function __construct(RenderInterface $renderer) { ... 1.annotate at injection point class RendererModule extends AbstractModule { protected function configure() { $this->bind('RenderInterface') ->to('HalRenderer') ->in(Scope::SINGLETON); } $injector = Inject::create([new RendererModule]]; 2. bind abstraction to concretion 3.create an injector
  16. 16. /** * @Inject */ public function __construct(RenderInterface $renderer) { ... 1.annotate at injection point class RendererModule extends AbstractModule { protected function configure() { $this->bind('RenderInterface') ->to('HalRenderer') ->in(Scope::SINGLETON); } $injector = Inject::create([new RendererModule]]; 2 bind abstraction to concretion 3.create an injector
  17. 17. $user = $injector->getInstance('UserInterface'); 4. Get an object graph from the $injector User Renderer Renderer Interface depends A B
  18. 18. procedural object orietned compilation runtime Implement the structure, not a procedure
  19. 19. class RendererModule extends AbstractModule { protected function configure() { $this ->bind('RenderInterface') ->to('HalRenderer') ->in(Scope::SINGLETON); } } Only use concrete classes in compilation
  20. 20. Only abstraction in runtime /** * @Inject */ public function __construct(RenderInterface $renderer) {
  21. 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. 22. Application = one root object
  23. 23. Application class
  24. 24. Application is root object retrieved with injector: $injector = Inject::create([new AppModule($context)]]; $app = $injector->getInstance(‘AppInterface’);
  25. 25. Application has dependency.
  26. 26. Dependencies have other dependencies Each object either contains or belongs to.
  27. 27. You get a application object graph. huge, but can be stored one single root value $app
  28. 28. Application can be serialized. $app can be serialized and stored Injection is reused beyond requests.
  29. 29. $app Object i/f i/f Object i/f i/f ObjectRouter Response JSON XM L 1st framework: DI Framework • annotations based DI framework w/ binding DSL • compilation / runtime separation • use only “plug/abstraction” at runtime • application a single large cached object • focus on structure not behavior
  30. 30. Aspect Oriented Programing
  31. 31. What is AOP? Cache Log Auth A programming paradigm that aims to increase modularity by allowing the separation of cross-cutting concerns
  32. 32. /** * @Cache */ 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; } }
  33. 33. MC I I AOP
  34. 34. MC Cache Cache is called by method invocation, If the cache is warm the model is never called. $obj->read(2); Miss !
  35. 35. Aspects Core Concern Cross Cutting Concern Separation
  36. 36. Rock Concert Example
  37. 37. interface MethodInterceptor { public function invoke(MethodInvocation $invocation); } $invocation->proceed(); // invoked method $object = $invocation->getThis(); // get source object $args = $invocation->getArgs(); // get arguments
  38. 38. 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
  39. 39. 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; } } `Cache`interceptor Core Concern Cross Cutting Concern
  40. 40. Simply annotate, then create your binding Bind
  41. 41. Layering by context • MVC, Is 3 enough ?
  42. 42. APIClient
  43. 43. API LogClient Valid Auth
  44. 44. API Log @Valid /admin DELETE Client Valid Auth
  45. 45. Aspect layering by context Model Cache Form Transaction Auth Validation
  46. 46. <?php class SandboxResourcePageIndexRay0000000071f9ab280000000033fb446fAop extends SandboxResourcePageIndex implements RayAopWeavedInterface { 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 RayAopReflectiveMethodInvocation(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.
  47. 47. Runtime injection by aspect • method / parameter lookup • test friendly
  48. 48. 2nd framework: Aspect Oriented Framework • AOP alliance standard • Layering by context • Type safe • Runtime injection
  49. 49. 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.
  50. 50. class Author extends ResourceObject { public $code = 200; public $headers = []; public $body = []; /** * @Link(rel="blog", href="app://self/blog/post?author_id={id}") */ public function onGet($id) { ... // change own state return $this; } public function onPost($name) { $this->code = 201; // created return $this; } public function onPut($id, $name)
  51. 51. $user = $resource ->get ->uri('app://self/user') ->withQuery(['id' => 1]) ->eager ->request(); var_dump($user->body); // Array // ( // [name] => John // [age] => 15 //) echo $user; // <div id=”name”>John</div> // <div id=”age”>15</div> public function onGet($id) { $this[‘name’] = ‘John’; $this[‘age’] = 15; return $this; } User Profile Friend
  52. 52. $order = $resource ->post ->uri('app://self/order') ->withQuery(['drink' => 'latte']) ->eager ->request(); $payment = [ 'credit_card_number' => '123456789', 'expires' => '07/07', 'name' => 'Koriym', 'amount' => '4.00' ]; // Now use a hyperlink to pay $response = $resource->href('pay', $payment); echo $response->code; // 201 Hypermedia as the Engine of Application State
  53. 53. class Order extends ResourceObject { /** * * @Link(rel="pay", method="put", href="app://self/payment{?order_id,card_number,amount}") */ public function onPost($drink) { // data store here $this['drink'] = $drink; $this['order_id'] = $orderId; // created $this->code = 201; return $this; } Hypermedia as the Engine of Application State
  54. 54. Order Payment hyper reference: pay HyperMedia Driven API
  55. 55. The key of success of web • URI • Unified Interface • Hyperlink
  56. 56. • API is hub • API is core value API driven development DB Mobil e Web API Cloud Moc k URI API API
  57. 57. http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html
  58. 58. Layered Resource UI Mobile Web Page Resource App script App Resource Entity
  59. 59. Performance • annotation ? dependency injection ? method interception ? DSL ? named parameter ? • Fast • cache all compiled object • http friendly architecture
  60. 60. Scale • “model proxy” pattern • ‘app://self/blog/entry’ can be anything. • contextual injection makes db scale easy
  61. 61. Hard spot / Soft spot • DI configure hardspot. per system • Aop configure softspot, change on request
  62. 62. Connecting frameworks • DI - object as dependency • AOP - domain logic to application logic • Hypermedia - resource to resource
  63. 63. Abstraction frameworks • DSL • Annotation • URI • Interface • Aspects • Hypermedia
  64. 64. “Zen” framework
  65. 65. Thanks. Arigato http://www.flickr.com/photos/stevehoad/4678289858/ @mackstar@koriym

×