$30 off During Our Annual Pro Sale. View Details »

Aspect Oriented Programming in PHP

Aspect Oriented Programming in PHP

AOP is a programming paradigm that aims to separate supporting functionality from the business logic. In this talk I'll explain in more detail what AOP is, how we can apply it in PHP, and what kind of solutions are currently available.

Link to Go! AOP: http://go.aopphp.com/
Link to PHP-AOP: http://pecl.php.net/package/AOP

Frank van den Brink

June 14, 2013
Tweet

More Decks by Frank van den Brink

Other Decks in Programming

Transcript

  1. ASPECT ORIENTED PROGRAMMING IN PHP I’m Frank van den Brink.

    I’m a Pragmatist. @fvdb
  2. TODAY’S AGENDA

  3. THE ORIGINS

  4. THE ORIGINS HOW IT WORKS

  5. THE ORIGINS HOW IT WORKS USING IT IN PHP

  6. THE ORIGINS

  7. Source: http://siliconvalley.sutromedia.com/xerox-parc.html

  8. class SecretService { public function getSecret($id) { // Check access

    if (!$this->isAllowedToAccess($id)) { throw new AccessDeniedException('You cannot do this!'); } // Get the secret $secret = $this->storage->getById($id); // Log that someone’s fetching the secret $this->logger->info('Secret accessed!'); return $secret; } }
  9. SEPARATION OF CONCERNS Hürsch, Lopes - 1995

  10. Programming intertwined code is hard and complex since all concerns

    have to be dealt with at the same time and at the same level. Source: Separation of Concerns - Hürsch, Lopes - 1995
  11. Programming intertwined code is hard and complex since all concerns

    have to be dealt with at the same time and at the same level. The extended programming language provides no adequate abstraction of concerns at the implementation level. Source: Separation of Concerns - Hürsch, Lopes - 1995
  12. Intertwined code is hard to understand because of the above

    lack of abstraction. Source: Separation of Concerns - Hürsch, Lopes - 1995
  13. Commingled code is hard to maintain and modify because the

    concerns are strongly coupled. Source: Separation of Concerns - Hürsch, Lopes - 1995
  14. The intertwined code gives rise to inheritance anomalies due to

    the strong coupling of different concerns. Source: Separation of Concerns - Hürsch, Lopes - 1995
  15. The intertwined code gives rise to inheritance anomalies due to

    the strong coupling of different concerns. It becomes impossible to redefine a method implementation or the commingled special concern in a subclass without redefining both. Source: Separation of Concerns - Hürsch, Lopes - 1995
  16. class SecretService { public function getSecret($id) { // Check access

    if (!$this->isAllowedToAccess($id)) { throw new AccessDeniedException('You cannot do this!'); } // Get the secret $secret = $this->storage->getById($id); // Log that someone’s fetching the secret $this->logger->info('Secret accessed!'); return $secret; } }
  17. class SecretService { public function getSecret($id) { return $this->storage->getById($id); }

    }
  18. META-LEVEL PROGRAMMING ADAPTIVE PROGRAMMING COMPOSITION FILTERS

  19. RG AML ETCML DJ DJAVA

  20. AspectJ

  21. HOW IT WORKS

  22. class Awesome { } 89 50 4e 47 0d 0a

    1a fe c3 1b 6c 88 COMPILER
  23. class SecretService { public function getSecret($id) { return $this->storage->getById($id); }

    }
  24. class SecretService { public function getSecret($id) { return $this->storage->getById($id); }

    } class AuthorizationAspect { public function checkAccessBeforeGetSecret($id) { if (!$this->isAllowedToAccess($id)) { throw new AccessDeniedException('You cannot do this!'); } } }
  25. class SecretService { public function getSecret($id) { return $this->storage->getById($id); }

    } class AuthorizationAspect { public function checkAccessBeforeGetSecret($id) { if (!$this->isAllowedToAccess($id)) { throw new AccessDeniedException('You cannot do this!'); } } } class LoggingAspect { public function logAfterGetSecret($id) { $this->logger->info('Secret accessed!'); } }
  26. class SecretService { public function getSecret($id) { // Check access

    if (!$this->isAllowedToAccess($id)) { throw new AccessDeniedException('You cannot do this!'); } // Get the secret $secret = $this->storage->getById($id); // Log that someone’s fetching the secret $this->logger->info('Secret accessed!'); return $secret; } }
  27. CROSS CUTTING CONCERN

  28. None
  29. None
  30. CROSS CUTTING CONCERN

  31. CROSS CUTTING CONCERN ASPECTS

  32. CROSS CUTTING CONCERN ASPECTS ADVICE

  33. class LoggingAspect { public function logAfterGetSecret($id) { $this->logger->info('Secret accessed!'); }

    }
  34. CROSS CUTTING CONCERN ASPECTS ADVICE

  35. CROSS CUTTING CONCERN ASPECTS ADVICE JOIN POINTS

  36. class SecretService { public function getSecret($id) { return $this->storage->getById($id); }

    } BEFORE METHOD CALL
  37. class SecretService { public function getSecret($id) { return $this->storage->getById($id); }

    } AFTER METHOD CALL
  38. class SecretService { public function getSecret($id) { return $this->storage->getById($id); }

    } AROUND METHOD CALL
  39. CROSS CUTTING CONCERN ASPECTS ADVICE JOIN POINTS

  40. CROSS CUTTING CONCERN ASPECTS ADVICE JOIN POINTS POINT CUTS

  41. Before( execution( public SecretService->*(*) ) )

  42. CROSS CUTTING CONCERN ASPECTS ADVICE JOIN POINTS POINT CUTS

  43. CROSS CUTTING CONCERN ASPECTS ADVICE JOIN POINTS POINT CUTS WEAVING

  44. WEAVING

  45. WEAVING

  46. WEAVING

  47. WEAVING

  48. WEAVING

  49. CROSS CUTTING CONCERN ASPECTS ADVICE JOIN POINTS POINT CUTS WEAVING

  50. USING IT IN PHP

  51. CAN YOU USE IT IN PHP?

  52. X X X X X O O O O

  53. X X X X X O O O O O

  54. AOP-PHP Flow AOP Go! AOP JMSAopBundle

  55. AOP-PHP Flow AOP Go! AOP JMSAopBundle ext lib lib lib

  56. AOP-PHP Flow AOP Go! AOP JMSAopBundle ext lib lib lib

  57. AOP-PHP Flow AOP Go! AOP JMSAopBundle ext lib lib lib

  58. AOP-PHP

  59. function logAfterGetSecret() { $this->logger->info('Secret accessed!'); } aop_add_after( 'SecretService->getSecret()', 'logAfterGetSecret' );

  60. Go! AOP

  61. new Example\Foobar Autoloader Weaver

  62. new Example\Foobar Autoloader Weaver

  63. new Example\Foobar Autoloader Weaver

  64. new Example\Foobar Autoloader Weaver

  65. new Example\Foobar Autoloader Weaver

  66. new Example\Foobar Autoloader Weaver

  67. new Example\Foobar Autoloader Weaver

  68. new Example\Foobar Autoloader Weaver

  69. class LoggingAspect implements Aspect { /** * @After("execution(public SecretService->getSecret(*))") */

    public function logAfterGetSecret(MethodInvocation $invocation) { $args = $invocation->getArguments(); $this->logger->info('Secret ' . $args[0] . ' accessed!'); } }
  70. class CachingAspect implements Aspect { /** * @Around("execution(public SecretService->getSecret(*))") */

    public function cacheGetSecret(MethodInvocation $invocation) { $args = $invocation->getArguments(); if ($this->cache->has($args[0])) { return $this->cache->get($args[0]); } $secret = $invocation->proceed(); $this->cache->set($args[0], $secret); return $secret; } }
  71. SHOULD YOU USE AOP?

  72. PERFORMANCE

  73. PERFORMANCE CLARITY

  74. PERFORMANCE CLARITY DON’T GO NUTS

  75. AOP ALL THE THINGS!

  76. MERCI BIEN @fvdb http://about.me/fvdb http://speakerdeck.com/u/fvdb