Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Programowanie aspektowe w PHP

34be88398f623c109b61d23e8215bd23?s=47 Mariusz Gil
September 30, 2012

Programowanie aspektowe w PHP

Abstrakt prezentacji:

Programowanie obiektowe możemy postrzegać jako dwuwymiarową przestrzeń klas, obiektów i występujących pomiędzy nimi interakcji w postaci np. wywołań metod. Na przestrzeni lat powstało także wiele metod i rozwiązań pomagających zapanować nad tworzącą się w ten sposób skomplikowaną siecią, warto by tu wspomnieć choćby enkapsulację, wzorce GoF czy GRASP. Niemal zawsze pojawiają się jednak zagadnienia przecinające przestrzeń ortogonalnie, bez związku z konkretną funkcjonalnością. Przeplot logiki aplikacyjnej z dodatkowym kodem realizującym zadania poboczne (tzw. warkocz) utrudnia jego analizowanie czy debugowanie. Trudno chyba sobie jednak wyobrazić aplikację bez systemu logowania zdarzeń, czy pomiaru czasów wykonania poszczególnych fragmentów kodu w trybie debug.

Z pomocą w implementacji logiki ortogonalnej przychodzi paradygmat programowania aspektowego, opracowany przez Gregora Kiczalesa w laboratoriach Xerox PARC. Za jego pomocą można niejako stworzyć trzeci wymiar, w którym umieszczana i implementowana jest logika ortogonalna, którą na dodatek można natychmiastowo włączać/wyłączać w całym kodzie źródłowym, bez potrzeby jego modyfikacji! Największe sukcesy paradygmatu AOP są związane z językiem Java (i kompilatorem AspecjJ), to jednak istnieje szereg rozwiązań dla PHP, dzięki którym nasz kod może stać się jeszcze bardziej modularny czy też “re-używalny”.

W trakcie sesji zapoznamy się z terminologią wykorzystywaną w AOP, zasadę tworzenia i wykorzystywania aspektów oraz możliwe do zastosowania biblioteki i frameworki PHP.

34be88398f623c109b61d23e8215bd23?s=128

Mariusz Gil

September 30, 2012
Tweet

Transcript

  1. PROGRAMOWANIE ASPEKTOWE PHP W MARIUSZ GIL PHPCON POLAND 2012

  2. O MNIE architekt, tech-lead developer, speaker

  3. dlaczeg ? ASPEKTY

  4. celem tej prezentacji jest...

  5. INCEPCJA

  6. PROGRAMOWANIE czy lubicie ?

  7. JEZYK PHP czy lubicie ? ,

  8. SPAGHETTI a lubicie ?

  9. class UserService { //... public function delete($user) { $this->logger->push(„Operation started

    at: ” . time()); if ($this->user->isAuthenticated()) { if ($this->user->isAllowedTo(self::DELETE) { $payments = PaymentPeer::retrieveByUser($user); foreach ($payments as $payment) { $payment->deleteFromCache(); $payment->delete(); } $user->deleteFromCache(); $user->delete(); } else { throw new UnauthorizedAccessException(); } } else { throw new UnauthorizedAccessException(); } $this->logger->push(„Operation finished at: ” . time()); } }
  10. 1

  11. 2

  12. 3

  13. TEORIA science motherf*cker, do you speak it?

  14. 60 ` OOP

  15. t unde tand the present unde tand the past „

  16. wiele problemó ` wiele rozwiazan `

  17. wiele problemó WZORCE PROJEKTOWE WZORCE GRASP DESIGN BY CONTRACTS ZASADY

    SOLID ZASADA DRY ZASADA KISS ZASADA YAGNI ` wiele rozwiazan `
  18. SEPARACJA ZAGADNIEN `

  19. Logowanie Persystencja Caching Funkcjonalnosc 1 Autentykacja Funkcjonalnosc 2 Funkcjonalnosc 3

    ` ` ` ` ` `
  20. Programowanie aspektowe (aspect-oriented programming, AOP) paradygmat tworzenia programów komputerowych wspomagajacy

    separacje zagadnien i rozdzielenie programu na czesci w jak najwiekszym stopniu niezwiazane funkcjonalnie ` , , , , , `
  21. OOP kod programu cache danych logowanie autentykacja OOP+AOP +

  22. class UserService { //... public function delete($user) { $this->logger->push(„Operation started

    at: ” . time()); if ($this->user->isAuthenticated()) { if ($this->user->isAllowedTo(self::DELETE) { $payments = PaymentPeer::retrieveByUser($user); foreach ($payments as $payment) { $payment->deleteFromCache(); $payment->delete(); } $user->deleteFromCache(); $user->delete(); } else { throw new UnauthorizedAccessException(); } } else { throw new UnauthorizedAccessException(); } $this->logger->push(„Operation finished at: ” . time()); } }
  23. 4PODSTAWOWE ELEMENTY ASPEKTÓW

  24. PUNKT ZLACZENIA dowolny identyfikowalny punkt programu, moze nim byc wywolanie

    lub wykonanie metody/konstruktora, odwolanie do pola w klasie obsluga wyjatku, etc. 1 ` . - - - - `
  25. PUNKT CIECIA zdefiniowana za pomoca okreslonej deklaracji kolekcja punktów zlaczen

    2 - ` ` ` ` `
  26. PORADA fragment kodu programu wykonywanego przed, po lub zamiast osiagniecia

    przez program punktu ciecia 3 ` ` `
  27. ASPEKT glówna jednostka modularyzacji programu, wyspecjalizowana klasa, która potrafi przecinac

    implementacje 4 - ` `
  28. KORZYSCI? `

  29. KORZYSCI? ` + modularyzacja kodu + wieksza czytelnosc + separacja

    zagadnien + aktywacja i zmiana flo całej aplikacji ` ` ` `
  30. PRAKTYKA programming motherf*cker, do you speak it?

  31. http://aop-php.github.com/ AOP-PHP jedna z dostepnych implementacji ,

  32. http://aop-php.github.com/ AOP-PHP jedna z dostepnych implementacji , 0.1.0-dev

  33. /** * Simple book bean class. * * @package demo

    * @version 1.0 */ class Book { /** * */ public $author; public $title; public $description; }
  34. /** * Simple storage bean class. * * @package demo

    * @version 1.0 */ class Storage { /** * */ public function store($model, $field, $value) { echo sprintf( "*** Store method executed: model \"%s\", field \"%s\", value \"%s\"\n", $model, $field, $value ); } /** * */ public function load($model, $field) { echo sprintf( "*** Load method executed: model \"%s\", field \"%s\"\n", $model, $field ); } }
  35. /** * Simple aspects. * * @package demo * @version

    1.0 */ $storage = new Storage(); $storageAdvice = function (AopTriggeredJoinPoint $joinpoint) use ($storage) { switch ($joinpoint->getKindOfAdvice()) { case AOP_KIND_BEFORE_READ_PROPERTY: $storage->load( $joinpoint->getTriggeringClassName(), $joinpoint->getTriggeringPropertyName() ); break; case AOP_KIND_AFTER_READ_PROPERTY: break; case AOP_KIND_BEFORE_WRITE_PROPERTY: break; case AOP_KIND_AFTER_WRITE_PROPERTY: $storage->store( $joinpoint->getTriggeringClassName(), $joinpoint->getTriggeringPropertyName(), $joinpoint->getAssignedValue() ); break; } };
  36. /** * Simple aspects. * * @package demo * @version

    1.0 */ $storage = new Storage(); $storageAdvice = function (AopTriggeredJoinPoint $joinpoint) use ($storage) { switch ($joinpoint->getKindOfAdvice()) { case AOP_KIND_BEFORE: case AOP_KIND_BEFORE_METHOD: case AOP_KIND_BEFORE_FUNCTION: case AOP_KIND_BEFORE_PROPERTY: case AOP_KIND_BEFORE_READ_PROPERTY: case AOP_KIND_BEFORE_WRITE_PROPERTY: case AOP_KIND_AROUND: case AOP_KIND_AROUND_METHOD: case AOP_KIND_AROUND_FUNCTION: case AOP_KIND_AROUND_PROPERTY: case AOP_KIND_AROUND_READ_PROPERTY: case AOP_KIND_AROUND_WRITE_PROPERTY: case AOP_KIND_AFTER: case AOP_KIND_AFTER_METHOD: case AOP_KIND_AFTER_FUNCTION: case AOP_KIND_AFTER_PROPERTY: case AOP_KIND_AFTER_READ_PROPERTY: case AOP_KIND_AFTER_WRITE_PROPERTY: break; } };
  37. /** * Simple aspect demo script. * * @param package

    demo * @version 1.0 */ require 'classes.php'; require 'aspects.php'; aop_add_before('Book->*', $storageAdvice); aop_add_after('Book->*', $storageAdvice); $book = new Book(); $book->title = 'Lorem ipsum'; $book->description = 'Lorem ipsum'; var_dump($book->title);
  38. /** * Simple aspect demo script. * * @param package

    demo * @version 1.0 */ require 'classes.php'; require 'aspects.php'; aop_add_after('MyClass->myMethod()', $sampleAdvice); aop_add_after('MyClass->my*()', $sampleAdvice); aop_add_after('MyClass->*()', $sampleAdvice); aop_add_after('*::myMethod()', $sampleAdvice); aop_add_after('**\*()', $sampleAdvice); aop_add_after('\namespace\MyClass->property', $sampleAdvice); aop_add_after('public MyClass->property', $sampleAdvice); aop_add_after('!public MyClass->*', $sampleAdvice); aop_add_after('public|private MyClass->*', $sampleAdvice); aop_add_after('read MyClass->*', $sampleAdvice);
  39. LIVE DEMO

  40. ph framework FLOW3 http://flow3.typo3.org/

  41. namespace  Examples\Forum\Domain\Model; class  Forum  {    /**      *

     @FLOW3\Inject      *  @var  \Examples\Forum\Logger\ApplicationLoggerInterface      */    protected  $applicationLogger;    /**      *  Delete  a  forum  post  and  log  operation      *      *  @param  \Examples\Forum\Domain\Model\Post  $post      *  @return  void      */      public  function  deletePost(Post  $post)  {          $this-­‐>applicationLogger-­‐>log('Removing  post  '  .  $post-­‐>getTitle(),  LOG_INFO);          $this-­‐>posts-­‐>remove($post);      } }
  42. namespace Examples\Forum\Logging; /** * @FLOW3\Aspect */ class LoggingAspect { /**

    * @FLOW3\Inject * @var \Examples\Forum\Logger\ApplicationLoggerInterface */ protected $applicationLogger; /** * Log a message if a post is deleted * * @param \TYPO3\FLOW3\AOP\JoinPointInterface $joinPoint * @FLOW3\Before("method(Examples\Forum\Domain\Model\Forum->deletePost())") * @return void */ public function logDeletePost(\TYPO3\FLOW3\AOP\JoinPointInterface $joinPoint) { $post = $joinPoint->getMethodArgument('post'); $this->applicationLogger->log('Removing post ' . $post->getTitle(), LOG_INFO); } }
  43. https://speakerdeck.com/u/mariuszgil speakerdeck joind.in https://joind.in/talk/view/7192 &

  44. DZIEKUJE email: mariusz@mariuszgil.pl twitter: mariuszgil , ,