Aop, Metaprogramming and codegeneration with PHP

3,948 views

Published on

Real world and crazy ideas on next generation PHP programming approaches

Published in: Technology
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,948
On SlideShare
0
From Embeds
0
Number of Embeds
15
Actions
Shares
0
Downloads
0
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide

Aop, Metaprogramming and codegeneration with PHP

  1. 1. MagentoAOP, Metaprogramming, CodegenerationOr the way of throwing elephants to a blackbox. Serge Smertin
  2. 2. MagentoAbout  Zend Certified Engineer  Senior Sw. Engineer @ EPAM  PHP since 2005  CakePHP since 2007  Zend Framework since 2008  Yii since 2010  Symfony 2.0 since 2011  Can also tell you something about pros & cons of CodeIgniner, Drupal, Wordpress
  3. 3. MagentoAgenda Inversion of control Metaprogramming Unexpected & Interesting Codegeneration Real life usage
  4. 4. MagentoDesign matters: SOLID 5 principles of enterprise object-oriented design: • Single responsibility • Open-close • Liskov substitution • Interface segregation • Dependency injection
  5. 5. MagentoDependency Injection Only possible with some kind of service locator Makes able to lazy initialize all resource dependencies Simplify debugging and development Simplify existing components extension and integration Dependency injection in PHP 5.3/5.4 http://slidesha.re/vE8Wyp
  6. 6. MagentoService locators in PHP Most of them require build stage For performance reasons they leverage codegeneration Require dependency configuration in some of the established ways Heavily utilize Reflection API
  7. 7. MagentoWhy building?
  8. 8. MagentoPimple  73 lines of PHP code  Use closures heavily  Made as fun proof of concept  Good for little projects  Base of Silex microframework  URLS • Pimple: http://pimple.sensiolabs.org/ • Silex project: http://silex.sensiolabs.org/
  9. 9. MagentoSymfony 2 DI Component  Mature production ready  Stores configuration within XML, YAML or annotations  Support for event observers  Support for custom service tagging  Scopes  Require build step for deploy  Supported by Sensio Labs. Paid subscriptions available  Could be integrated through PEAR  Easy   URLS go here: • DI for PHP 5.2 - http://bit.ly/uGt8CK • PEAR channel: http://pear.symfony.com/ • Service Container - http://bit.ly/s7F8HF
  10. 10. MagentoSome cookies: CLI  Some tasks could be done through CLI easier  Cron?  Daemons?  Continuous integration?  Expose services to console?
  11. 11. Magentocli:call  What about writing custom command for accessing nearly every defined service in container for isolated working? $ ./app/console cli:call service.name methodName [arg1, arg2, arg3, …]
  12. 12. MagentoMetaprogramming Is how programs are self-aware Is not recommended to use at run time Is the art of operating metadata Is black magic processed at build step Is possible with PHP 5 Is making the code shorter
  13. 13. MagentoMetadata XML files YAML files Database Naming conventions
  14. 14. MagentoMetadata XML files YAML files Database Naming conventions … boring.
  15. 15. MagentoMetadata XML files PHP doc comments YAML files PHP code itself Database Reflection Naming Annotations conventions SQL code
  16. 16. MagentoReflection API  A way of retrieving information about parameters for a class method  A way of accessing private property of a parent class  A way of passing method parameters by name  Another way of making callback  Other more or less interesting ways of application
  17. 17. MagentoAnnotation magic  Actually are custom docblock tags with some extend  Some kind of XDoclet API for PHP  Some other couple of words here  Some frameworks endorse usage: Symfony2 & FLOW3  Couple of existing solutions available • Regular expressions  • PHPUnit • ZendReflectionDocblockTag (just extended PCRE, actually) • Doctrine annotation reader (parser-based method)  Links: • Doctrine Annotations Reference http://bit.ly/s6kQfh • An article of 2008 http://bit.ly/uT1v2U • XDoclet overview of 2005 http://bit.ly/tYy8pa
  18. 18. MagentoTokenization  Just token_get_all() and be insane  Build a classmap file with namespace information  Generate unit test skeletons  Put all TODO’s in comments as tickets to Jira  Some of more sophisticated things I haven’t thought about
  19. 19. MagentoSQL code: annotations. Why not?
  20. 20. MagentoSQL: Sharding. Annotations?..  Get meta-info about sharded connection to use from query directly  Or parse the query, but little longer  /*entity customer://1234 */ SELECT name FROM customer WHERE id = 1234  Database Scale http://slidesha.re/vC1i9x  Sharding for startups http://bit.ly/vLa68N
  21. 21. MagentoDoctrine Common: Annotation reader  Annotation is a class  Any number of properties could be passed to constructor  Nesting  Short forms  Takes time to process
  22. 22. MagentoTakes time to process? All configuration is read from DI container DI container is regenerated upon build Dev. env. regenerates DI each request Prod. env. reads cached DI Annotations aren’t processed in prod. env. PROFIT!
  23. 23. Magento… well, mostly… Not all is processed on build Annotations are good for event listeners * Convenient way for storing meta- information within the code* Classes defined as services and tagged with special event hooks. Latertransformed to code in some of generated DIC methods.
  24. 24. MagentoProcessing annotations1. Create class implementing SymfonyComponentDependencyInjectionCompiler CompilerPassInterface2. Collect annotations via reader3. Save processed metadata in container via ContainerBuilder::setParameter()4. Add build(ContainerBuilder $cb) method to bundle main class5. Add kernel.* event observers6. PROFIT
  25. 25. MagentoReal life: collecting metadata
  26. 26. MagentoAutowiring  Inject serviced needed to places needed  Reflection-heavy  Hard, but possible for PHP  MVC simplifying   Ready solutions • Autowiring Bundle – http://bit.ly/uDTKYi • JMSDiExtraBundle – http://bit.ly/t7pP89 • FLOW3 autowiring – http://bit.ly/tcJQ10
  27. 27. MagentoCommon now is less: CRON • Adding periodical tasks seem somewhat boring • With annotated configuration it could be set up in seconds • This simple annotation will be transformed in crontab file to something like 0 */4 * * * /usr/bin/php /path/to/app/console cli:call our.user.service sendNotifications
  28. 28. MagentoDoing things wrong?
  29. 29. MagentoDoing things wrong When my IDE* cannot help auto completing Im using bad practice programming * Netbeans, Eclipse, PHPStorm, .. put your favorite here
  30. 30. MagentoReal life: Autowiring  Create services with simple annotating them  Inject existing services to class properties  Apply name guessing strategies  JMSDiExtraBundle used
  31. 31. MagentoKeeping code short Configure routes inline Configure templates inline Inject only services, that the action really needs. Recognized by IDE directly Return needed variables for view
  32. 32. Magentogrep Nice tool to get only those classes with annotations & autowiring to parse True UNIX way Or use a class-map file – URL goes here Done at the build step
  33. 33. MagentoCodegeneration and codedegeneration  Programs program programs  As ideal – lets developer develop business logic, not the boilerplate  Programs make pieces of programs • RAD tools and frameworks • IDE code templates  Having templates is really good  Customization is good  “Code Generation in Action” by Jack Herrington D. http://amzn.to/skQzEr
  34. 34. MagentoUse cases Project rapid start Enterprise stuff DB interaction & ORM Better unit test skeletons Performance Code transformation Boilerplates & customization Bunch of routine stuff …
  35. 35. MagentoUse-case: Generating unit-tests Goal: save time creating boilerplate code for • Initialization of all dependent objects • Public methods • Possible conditional logic • Asserting actual and expected results • Mock object methods boilerplate
  36. 36. MagentoHow?Wrapper over token_get_all()Reflection APIZendReflection & ZendCodeGenerator
  37. 37. MagentoUse-case: proxy generation for performance  Template engines – compile own markup to PHP  Symfony DI Component – generates service bootstrap in PHP  JMSSecurityBundle – puts security checking to generated proxies  SymfonyGeneratorBundle – makes writing boilerplate CRUD code for controllers and entities faster and easier.  Put your own here.
  38. 38. MagentoCommon things Framework specific Define placeholders Extend and Proxy Liscov substitution principle Have templates, that are editable Have an easy way to make own templates Regenerate stuff on architecture change
  39. 39. MagentoExisting solutions PHP ecosystem  Symfony2 – SensioGeneratorBundle – http://symfony.com/  Doctrine2 – two-way ORM/DB generator – http://bit.ly/veIvvm  ZendFramework – ZendCodeGenerator – http://bit.ly/s7mYHD  cg-library – http://bit.ly/vtBfk7  QCodo – interesting RAD generator – http://qcodo.com/  CakePHP – RAD project start - http://cakephp.org/ Other  CodeSmith – http://codesmithtools.com/ …
  40. 40. MagentoGenerating codegenerators Have an ideal code sample: R&D something nice  Get code slice from line X to line Y Define common pattern fast Get template. Test it. Improve sample. Apply results of your concept fast
  41. 41. MagentoIn 6 months … Improve ideal code sample Improve template Regenerate those hundreds of files in seconds with compatibility kept PROFIT.
  42. 42. MagentoA tool  Some internal tool for generating generators, unit tests, fixtures  Typical usage: Sample file Start and end lines Format $ pugooroo tpl RolseService.php 108 118 Copy output --pieces --heredoc --copy Pick vars to buffer  --function generateStuff cogen> Enter code pieces you want to replace Wrap up to function user Interactive group CLI app!11 Group cogen> Enter alias for user [piece0]: FIRST cogen> Enter alias for group [piece1]: SECOND cogen> Enter alias for Group [piece2]: SECOND_CAMELCASED
  43. 43. MagentoAnd typical result function generateStuff ($FIRST, $SECOND, $SECOND_CAMELCASED) { $tmpl = <<<EOF ${$FIRST}Counts = array(); while ($row = $stmt->fetchObject()) { ${$FIRST}Counts[(int) $row->{$SECOND}_id] = (int) $row- >num_{$FIRST}s; } foreach(${$SECOND}s as ${$SECOND}) { /* @var ${$SECOND} {$SECOND_CAMELCASED} */ if(isset (${$FIRST}Counts[${$SECOND}->getId()])) { ${$SECOND}->setUsercount(${$FIRST}Counts[${$SECOND}->getId()]); } } EOF; return $tmpl; }
  44. 44. MagentoCLI: interaction & copy to buffer Interaction: streams • php://stdin • php://stdout Copy to buffer from CLI: • MacOS: echo $res | pbcopy • Linux: echo $res | xclip … • Windows: 
  45. 45. MagentoThe more sophisticated things #Joined array turns out to be more flexible than HEREDOC: function generateStuff ($FIRST, $SECOND, $SECOND_CAMELCASED, $needsSomething = true) { $tmpl = array(); $tmpl[] = " ${$FIRST}Counts = array();"; $tmpl[] = " while ($row = $stmt->fetchObject()) {"; $tmpl[] = " ${$FIRST}Counts[(int) $row->{$SECOND}_id] = (int) $row- >num_{$FIRST}s;"; $tmpl[] = " }"; $tmpl[] = " "; if($needsSomething) { $tmpl[] = " foreach(${$SECOND}s as ${$SECOND}) {"; $tmpl[] = " if(isset (${$FIRST}Counts[${$SECOND}- >getId()])) {"; $tmpl[] = " ${$SECOND}- >setUsercount(${$FIRST}Counts[${$SECOND}->getId()]);"; $tmpl[] = " }"; $tmpl[] = " }"; $tmpl[] = ""; } $tmpl = join("n", $tmpl); return $tmpl; }
  46. 46. MagentoReal life: tagged keys in cache Goal: • Resultset of a method could be cached • Resultset is dependent on other resultsets validity • If dependent resultset becomes invalid – invalidate only needed keys • Perform application-wide substitutions like currently logged in user and etc • Make adding and removing cache really easy Bad things • Require complex code to maintain • Hard to read
  47. 47. MagentoSolution  Java EhCache framework – http://ehcache.org/  @Cacheable & @TriggersRemove with tagging- specific features  Generate code for proxy class  Substitute original class within inversion of control container  Call the same method without any API change  Turn off caching when needed
  48. 48. MagentoSlight changes to code
  49. 49. MagentoGenerated code for caching
  50. 50. MagentoReal life: add security restrictions  Goal: • Protect methods of service from unauthorized access • Have access granularity to actions of controller • Limit access for modifying particular entities • Make it easy  Solutions: • Symfony2 – JmsSecurityExtraBundle – http://bit.ly/sX0hN6 • DiExtraBundle – autowiring stuff – http://bit.ly/t7pP89 • AopBundle – intercept method calls – http://bit.ly/vFqWSD
  51. 51. MagentoEvents
  52. 52. MagentoFast forms & XML * Doctrine OXM: http://github.com/doctrine/oxm
  53. 53. MagentoQuestions & Answers
  54. 54. MagentoThank you• http://twitter.com/nf_x• http://ua.linkedin.com/smertin

×