Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

BEAR.Sunday is an application framework. But it offers no libraries. (We have good stuff)

Slide 6

Slide 6 text

instead, it offers three object frameworks.

Slide 7

Slide 7 text

What is a framework ?

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

3.hypermedia framework

Slide 12

Slide 12 text

DI AOP REST

Slide 13

Slide 13 text

DI Benefits • Dependency Inversion Principle • Clear separation of object instantiation and object usage • Object delivery

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

“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”

Slide 16

Slide 16 text

Ray.DI Dependency Injection Framework

Slide 17

Slide 17 text

/** * @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

Slide 18

Slide 18 text

/** * @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

Slide 19

Slide 19 text

/** * @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

Slide 20

Slide 20 text

$user = $injector->getInstance('UserInterface'); 4. Get an object graph from the $injector User Renderer Renderer Interface depends A B

Slide 21

Slide 21 text

QSPDFEVSBM PCKFDUPSJFUOFE DPNQJMBUJPO SVOUJNF Implement the structure, not a procedure

Slide 22

Slide 22 text

class RendererModule extends AbstractModule { protected function configure() { $this ->bind('RenderInterface') ->to('HalRenderer') ->in(Scope::SINGLETON); } } Only use concrete classes in compilation

Slide 23

Slide 23 text

Only abstraction in runtime /** * @Inject */ public function __construct(RenderInterface $renderer) {

Slide 24

Slide 24 text

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.”

Slide 25

Slide 25 text

Application = one root object

Slide 26

Slide 26 text

Application class

Slide 27

Slide 27 text

No content

Slide 28

Slide 28 text

Application is root object retrieved with injector: $injector = Injector::create([new AppModule($context)]]; $app = $injector->getInstance(‘AppInterface’);

Slide 29

Slide 29 text

Application has dependency.

Slide 30

Slide 30 text

No content

Slide 31

Slide 31 text

Dependencies have other dependencies Each object either contains or belongs to.

Slide 32

Slide 32 text

You get a application object graph. huge, but can be stored one single root value $app

Slide 33

Slide 33 text

"QQMJDBUJPODBOCFTFSJBMJ[FE $app can be serialized and stored Injection is reused beyond requests.

Slide 34

Slide 34 text

$app Object i/f i/f Object i/f i/f Object Router 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

Slide 35

Slide 35 text

Aspect Oriented Programing

Slide 36

Slide 36 text

What is AOP? Cache Log Auth A programming paradigm that aims to increase modularity by allowing the separation of cross-cutting concerns

Slide 37

Slide 37 text

/** * @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; } }

Slide 38

Slide 38 text

M C I I AOP

Slide 39

Slide 39 text

M C Cache Cache is called by method invocation, If the cache is warm the model is never called. $obj->read(2); Miss !

Slide 40

Slide 40 text

Aspects Core Concern Cross Cutting Concern Separation

Slide 41

Slide 41 text

Rock Concert Example

Slide 42

Slide 42 text

interface MethodInterceptor { public function invoke(MethodInvocation $invocation); } $invocation->proceed(); // invoked method $object = $invocation->getThis(); // get source object $args = $invocation->getArgs(); // get arguments

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

4JNQMZBOOPUBUF UIFODSFBUFZPVSCJOEJOH #JOE

Slide 46

Slide 46 text

Layering by context • MVC, Is 3 enough ?

Slide 47

Slide 47 text

API Client

Slide 48

Slide 48 text

API Log Client Valid Auth

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

Aspect layering by context Model Cache Form Transaction Auth Validation

Slide 51

Slide 51 text

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.

Slide 52

Slide 52 text

Runtime injection by aspect • method / parameter lookup • test friendly

Slide 53

Slide 53 text

2nd framework: Aspect Oriented Framework • AOP alliance standard • Layering by context • Type safe • Runtime injection

Slide 54

Slide 54 text

No content

Slide 55

Slide 55 text

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.

Slide 56

Slide 56 text

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)

Slide 57

Slide 57 text

$user = $resource ->get ->uri('app://self/user') ->withQuery(['id' => 1]) ->eager ->request(); var_dump($user->body); // Array // ( // [name] => John // [age] => 15 //) echo $user; //
John
//
15
public function onGet($id) { $this[‘name’] = ‘John’; $this[‘age’] = 15; return $this; } User Profile Friend

Slide 58

Slide 58 text

$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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

Order Payment hyper reference: pay HyperMedia Driven API

Slide 61

Slide 61 text

The key of success of web • URI • Unified Interface • Hyperlink

Slide 62

Slide 62 text

• API is hub • API is core value API driven development DB Mobil e Web API Cloud Moc k URI API API

Slide 63

Slide 63 text

http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html

Slide 64

Slide 64 text

Layered Resource UI Mobile Web Page Resource App script App Resource Entity

Slide 65

Slide 65 text

No content

Slide 66

Slide 66 text

No content

Slide 67

Slide 67 text

No content

Slide 68

Slide 68 text

No content

Slide 69

Slide 69 text

Performance • annotation ? dependency injection ? method interception ? DSL ? named parameter ? • Fast • cache all compiled object • http friendly architecture

Slide 70

Slide 70 text

Scale • “model proxy” pattern • ‘app://self/blog/entry’ can be anything. • contextual injection makes db scale easy

Slide 71

Slide 71 text

Hard spot / Soft spot • DI configure hardspot. QFSTZTUFN • Aop configure softspot, change on request

Slide 72

Slide 72 text

Connecting frameworks • DI - object as dependency • AOP - domain logic to application logic • Hypermedia - resource to resource

Slide 73

Slide 73 text

Abstraction frameworks • DSL • Annotation • URI • Interface • Aspects • Hypermedia

Slide 74

Slide 74 text

No content

Slide 75

Slide 75 text

“Zen” framework

Slide 76

Slide 76 text

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