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.
HTTP caching and Symfony2Be lazy, be ESI   Alessandro Nadalin         May, 13 2011
Symfony2 sucks    at caching
because it doesnt have an application caching layer
high five, thats great
Sf2 embraces the HTTP caching specification          and thats not because
Fabien is  lazy
thats because
Fabien kicks asses
HTTP cache     is a   King in Symfony2
Caching in Symfony2
Caching is, obviously, a matter of the response
since the response is an object, we have some basic OO stuff    to handle HTTP cache
Creating a responsepublic function indexAction(){  $res = $this->render(MyBundle:Default:home.html.twig, array(     title ...
Creating a responsepublic function indexAction(){  $res = $this->render(MyBundle:Default:home.html.twig, array(     title ...
Creating a responsepublic function indexAction(){  $res = $this->render(MyBundle:Default:home.html.twig, array(     title ...
Creating a responsepublic function indexAction(){  $res = $this->render(MyBundle:Default:home.html.twig, array(     title ...
Creating a responsepublic function indexAction(){  $res = $this->render(MyBundle:Default:home.html.twig, array(     title ...
Creating a responsepublic function indexAction(){  $res = $this->render(MyBundle:Default:home.html.twig, array(     title ...
Expiration
Expirationpublic function indexAction(){  $res = $this->render(MyBundle:Default:home.html.twig, array(     title => My blo...
Expirationpublic function indexAction(){  $res = $this->render(MyBundle:Default:home.html.twig, array(     title => My blo...
Expirationpublic function indexAction(){  $res = $this->render(MyBundle:Default:home.html.twig, array(     title => My blo...
Expiration through Cache-Controlpublic function indexAction(){  $res = $this->render(MyBundle:Default:home.html.twig, arra...
Expiration through Cache-Controlpublic function indexAction(){  $res = $this->render(MyBundle:Default:home.html.twig, arra...
Expiration through Cache-Controlpublic function indexAction(){  $res = $this->render(MyBundle:Default:home.html.twig, arra...
Expiration through Cache-Controlpublic function indexAction(){  $res = $this->render(MyBundle:Default:home.html.twig, arra...
Validation
Validationpublic function articleAction($id){  $article = $this->get(entity_manager)->query($id)...  $res = $this->render(...
Validationpublic function articleAction($id){  $article = $this->get(entity_manager)->query($id)...  $res = $this->render(...
Validationpublic function articleAction($id){  $article = $this->get(entity_manager)->query($id)...  $res = $this->render(...
Validationpublic function articleAction($id){  $article = $this->get(entity_manager)->query($id)...  $res = $this->render(...
Validationpublic function articleAction($id){  $article = $this->get(entity_manager)->query($id)...  $res = $this->render(...
Automagically get a Datetime from Doctrine2namespace AcmeBlogBundleEntity;/** * @orm:Entity * @orm:Table(name="article") *...
Automagically get a Datetime from Doctrine2namespace AcmeBlogBundleEntity;/** * @orm:Entity * @orm:Table(name="article") *...
but hey, you say
whats the advatage of using validation if we always hit         the DB and create a new Response?
Validation, the right waypublic function articleAction($id){  $res          = new Response()  $etag        = Memcache::get...
Validation, the right waypublic function articleAction($id){  $res          = new Response()  $etag        = Memcache::get...
Validation, the right waypublic function articleAction($id){  $res          = new Response()  $etag        = Memcache::get...
Validation, the right waypublic function articleAction($id){  $res          = new Response()  $etag        = Memcache::get...
relax
Calculating an Etag, or a date, is cheaper  than generating a full MVC response
Control your power
Additional managementpublic function articleAction($id){  $res = new Response()  $res->setVary(array(     Accept-Encoding,...
Varying the responsepublic function articleAction($id){  $res = new Response()  $res->setVary(array(    Accept-Encoding,  ...
Cacheable by all cachespublic function articleAction($id){  $res = new Response()  $res->setVary(array(     Accept-Encodin...
or by local onlypublic function articleAction($id){  $res = new Response()  $res->setVary(array(     Accept-Encoding,  ));...
Good old 304public function articleAction($id){  $res = new Response()  $res->setVary(array(     Accept-Encoding,  ));  $r...
Stalepublic function articleAction($id){  $res = new Response()  $res->setVary(array(     Accept-Encoding,  ));  $res->set...
but hey, you say
HTTPs cache fails when dealing with really dynamic pages,because consumers will always have to hit the origin server,altho...
no bueno, you say
NOPE
ESI was built for that            http://www.w3.org/TR/esi-lang<esi:include src="http://mysite.com/twitterfeeds.html" />
ESI and Symfony2# controller$response->setSharedMaxAge(3600);# app/config/config.ymlframework:  esi: { enabled: true }# te...
ESI and Symfony2# controller$response->setSharedMaxAge(3600);# app/config/config.ymlframework:  esi: { enabled: true }# te...
ESI and Symfony2# controller$response->setSharedMaxAge(3600);# app/config/config.ymlframework:  esi: { enabled: true }# te...
ESI and Symfony2# controller$response->setSharedMaxAge(3600);# app/config/config.ymlframework:  esi: { enabled: true }# te...
ESI and Symfony2# controller$response->setSharedMaxAge(3600);# app/config/config.ymlframework:  esi: { enabled: true }# te...
Use Symfony2 reverse proxy
Use Symfony2 reverse proxy         (slower)
or Varnishhttp://www.varnish-cache.org/
Varnish configurationbackend apache {    .host = "127.0.0.1";    .port = "8080";}sub vcl_recv {  unset req.http.Accept-Enc...
Varnish configurationbackend apache {    .host = "127.0.0.1";       tell Symfony2    .port = "8080";     youre behind a re...
Why HTTP caching      is so   important?
Ask yourself:as a developer, what do I want      on my application?
EvolveLoose coupling    Work less
EvolveBecause you want your platform to extensible                                               Loose coupling           ...
EvolveBecause you want your platform to extensible                                                Loose couplingBecause yo...
EvolveBecause you want your platform to extensible                                                Loose couplingBecause yo...
enters our Hero #1
enters our Hero #2
http://www.lullabot.com/articles/a-beginners-guide-to-caching-data
2007
2011?
it supportsHTTP caching!  http://drupal.org/node/147310
it supportsHTTP caching!   http://drupal.org/node/147310 ( people is supposed to clap their hands here )
but
wait.... how?
Default headersExpires = Sun, 19 Nov 1978 05:00:00 GMT,Cache-Control = no-cache, must-revalidate,ETag = $_SERVER[REQUEST_T...
Default headersExpires = Sun, 19 Nov 1978 05:00:00 GMT,Cache-Control = no-cache, must-revalidate,ETag = $_SERVER[REQUEST_T...
Default headersExpires = Sun, 19 Nov 1978 05:00:00 GMT,Cache-Control = no-cache, must-revalidate,ETag = $_SERVER[REQUEST_T...
Default headersExpires = Sun, 19 Nov 1978 05:00:00 GMT,Cache-Control = no-cache, must-revalidate,ETag = $_SERVER[REQUEST_T...
is that even legal?
"but you can redefine them!"
drupal_add_http_header()
function drupal_add_http_header(){  ...    ...    drupal_send_headers($headers);}
so, whatdrupal_send_headers()    can do so evil?
header()       ,   of course
which means
drupal_add_http_header(Dumb-Header, Im batman!);...// other logic...drupal_add_http_header(Dumb-Header, Im not);var_dump(h...
drupal_add_http_header(Dumb-Header, Im batman!);...// other logic...drupal_add_http_header(Dumb-Header, Im not);var_dump(h...
drupal_add_http_header(Dumb-Header, I-m batman!);...// other logic...drupal_add_http_header(Dumb-Header, false);var_dump(h...
drupal_add_http_header(Dumb-Header, I-m batman!);...// other logic...drupal_add_http_header(Dumb-Header, false);var_dump(h...
drupal_add_http_header(Dumb-Header, I-m batman!);...// other logic...drupal_add_http_header(Dumb-Header,  );var_dump(heade...
drupal_add_http_header(Dumb-Header, I-m batman!);...// other logic...drupal_add_http_header(Dumb-Header,  );var_dump(heade...
or
you can use header_remove()           ( PHP 5.3 )
and create a new class to   manage/keep track ofheaders and caching directives
but were lazy               andwe dont want to reinvent the wheel
GoalsWork less                             evolve            loose coupling
GoalsWork less                             evolve            loose coupling
everything is done for us!            :)          but....
tmp files, cache tables, procedural code...               mmmmh....        gotta be something better
Frameworks
symfony ONE
Cache is used for compiling routes, autoloading, ...
Cache is used for compiling routes, autoloading, ...   ...but also for storing the view
GoalsWork less                             evolve            loose coupling
GoalsWork less                             evolve            loose coupling
at least because we use a framework
HTTP
GoalsWork less                             evolve            loose coupling
Less work
because the hard work is delegated to the browser/proxy
Evolve
because cache is abstracted from the application
Loose coupling
because caching is bound to the protocol, HTTP, notto your implementation ( Sf, RoR, Django )
Alessandro Nadalin
Alessandro Nadalin
Alessandro Nadalin    odino.org
Alessandro Nadalin    odino.org    @_odino_
Alessandro Nadalin    odino.org    @_odino_    http://joind.in/talk/view/2988
Alessandro Nadalin    odino.org    @_odino_    http://joind.in/talk/view/2988                Thanks!
Creditshttp://www.flickr.com/photos/snakphotography/5004775320/sizes/o/in/photostream/  http://www.flickr.com/photos/ashat...
 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
Upcoming SlideShare
Loading in …5
×

Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011

In the first part of the presentation we see how Symfony2 implements HTTP cache.

In the second one there's an explanation of why application cache layers suck, why nerly every php application does caching in the less productive way and how you benefit from HTTP cache from this point of view.

Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011

  1. 1. HTTP caching and Symfony2Be lazy, be ESI Alessandro Nadalin May, 13 2011
  2. 2. Symfony2 sucks at caching
  3. 3. because it doesnt have an application caching layer
  4. 4. high five, thats great
  5. 5. Sf2 embraces the HTTP caching specification and thats not because
  6. 6. Fabien is lazy
  7. 7. thats because
  8. 8. Fabien kicks asses
  9. 9. HTTP cache is a King in Symfony2
  10. 10. Caching in Symfony2
  11. 11. Caching is, obviously, a matter of the response
  12. 12. since the response is an object, we have some basic OO stuff to handle HTTP cache
  13. 13. Creating a responsepublic function indexAction(){ $res = $this->render(MyBundle:Default:home.html.twig, array( title => My blog, )); return $res;}
  14. 14. Creating a responsepublic function indexAction(){ $res = $this->render(MyBundle:Default:home.html.twig, array( title => My blog, )); return $res;}
  15. 15. Creating a responsepublic function indexAction(){ $res = $this->render(MyBundle:Default:home.html.twig, array( title => My blog, )); return $res;}
  16. 16. Creating a responsepublic function indexAction(){ $res = $this->render(MyBundle:Default:home.html.twig, array( title => My blog, )); return $res;}
  17. 17. Creating a responsepublic function indexAction(){ $res = $this->render(MyBundle:Default:home.html.twig, array( title => My blog, )); return $res;}
  18. 18. Creating a responsepublic function indexAction(){ $res = $this->render(MyBundle:Default:home.html.twig, array( title => My blog, )); return $res;}
  19. 19. Expiration
  20. 20. Expirationpublic function indexAction(){ $res = $this->render(MyBundle:Default:home.html.twig, array( title => My blog, )); $date = new DateTime(); $date->modify(+600 seconds); $res->setExpires($date); return $res;}
  21. 21. Expirationpublic function indexAction(){ $res = $this->render(MyBundle:Default:home.html.twig, array( title => My blog, )); $date = new DateTime(); $date->modify(+600 seconds); $res->setExpires($date); return $res;}
  22. 22. Expirationpublic function indexAction(){ $res = $this->render(MyBundle:Default:home.html.twig, array( title => My blog, )); $date = new DateTime(); $date->modify(+600 seconds); $res->setExpires($date); return $res;}
  23. 23. Expiration through Cache-Controlpublic function indexAction(){ $res = $this->render(MyBundle:Default:home.html.twig, array( title => My blog, )); $res->setMaxAge(600); $res->setSharedMaxAge(600); return $res;}
  24. 24. Expiration through Cache-Controlpublic function indexAction(){ $res = $this->render(MyBundle:Default:home.html.twig, array( title => My blog, )); $res->setMaxAge(600); $res->setSharedMaxAge(600); return $res;}
  25. 25. Expiration through Cache-Controlpublic function indexAction(){ $res = $this->render(MyBundle:Default:home.html.twig, array( title => My blog, )); $res->setMaxAge(600); $res->setSharedMaxAge(600); return $res;}
  26. 26. Expiration through Cache-Controlpublic function indexAction(){ $res = $this->render(MyBundle:Default:home.html.twig, array( title => My blog, )); $res->setMaxAge(600); $res->setSharedMaxAge(600); return $res;} Shared caches, like Symfony2 reverse proxy
  27. 27. Validation
  28. 28. Validationpublic function articleAction($id){ $article = $this->get(entity_manager)->query($id)... $res = $this->render(MyBundle:Default:article.html.twig, array( article => $article, )); $etag = "article:{$article->getId()}:{$article->getVersion()}"; $res->setETag($etag); $res->setLastModified($article->getModifiedAt()); return $res;
  29. 29. Validationpublic function articleAction($id){ $article = $this->get(entity_manager)->query($id)... $res = $this->render(MyBundle:Default:article.html.twig, array( article => $article, )); $etag = "article:{$article->getId()}:{$article->getVersion()}"; $res->setETag($etag); $res->setLastModified($article->getModifiedAt()); return $res;
  30. 30. Validationpublic function articleAction($id){ $article = $this->get(entity_manager)->query($id)... $res = $this->render(MyBundle:Default:article.html.twig, array( article => $article, )); $etag = "article:{$article->getId()}:{$article->getVersion()}"; $res->setETag($etag); $res->setLastModified($article->getModifiedAt()); return $res;
  31. 31. Validationpublic function articleAction($id){ $article = $this->get(entity_manager)->query($id)... $res = $this->render(MyBundle:Default:article.html.twig, array( article => $article, )); $etag = "article:{$article->getId()}:{$article->getVersion()}"; $res->setETag($etag); $res->setLastModified($article->getModifiedAt()); return $res;
  32. 32. Validationpublic function articleAction($id){ $article = $this->get(entity_manager)->query($id)... $res = $this->render(MyBundle:Default:article.html.twig, array( article => $article, )); $etag = "article:{$article->getId()}:{$article->getVersion()}"; Datetime object $res->setETag($etag); $res->setLastModified($article->getModifiedAt()); return $res;
  33. 33. Automagically get a Datetime from Doctrine2namespace AcmeBlogBundleEntity;/** * @orm:Entity * @orm:Table(name="article") */class Article{ /** * @orm:Column(type="datetime", name="modified_at") */ protected $modifiedAt;
  34. 34. Automagically get a Datetime from Doctrine2namespace AcmeBlogBundleEntity;/** * @orm:Entity * @orm:Table(name="article") */class Article{ /** * @orm:Column(type="datetime", name="modified_at") */ protected $modifiedAt;
  35. 35. but hey, you say
  36. 36. whats the advatage of using validation if we always hit the DB and create a new Response?
  37. 37. Validation, the right waypublic function articleAction($id){ $res = new Response() $etag = Memcache::get("Article:{$id}:etag"); $lastModified = Memcache::get("Article:{$id}:last_modified"); $res->setETag($etag); $res->setLastModified($lastModified); if ($res->isNotModified($this->get(request))) { return $res; } $article = $this->get(entity_manager)->query($id)... ...
  38. 38. Validation, the right waypublic function articleAction($id){ $res = new Response() $etag = Memcache::get("Article:{$id}:etag"); $lastModified = Memcache::get("Article:{$id}:last_modified"); $res->setETag($etag); $res->setLastModified($lastModified); if ($res->isNotModified($this->get(request))) { return $res; } $article = $this->get(entity_manager)->query($id)... ...
  39. 39. Validation, the right waypublic function articleAction($id){ $res = new Response() $etag = Memcache::get("Article:{$id}:etag"); $lastModified = Memcache::get("Article:{$id}:last_modified"); $res->setETag($etag); $res->setLastModified($lastModified); if ($res->isNotModified($this->get(request))) { return $res; } $article = $this->get(entity_manager)->query($id)... ...
  40. 40. Validation, the right waypublic function articleAction($id){ $res = new Response() $etag = Memcache::get("Article:{$id}:etag"); $lastModified = Memcache::get("Article:{$id}:last_modified"); $res->setETag($etag); $res->setLastModified($lastModified); if ($res->isNotModified($this->get(request))) { return $res; } $article = $this->get(entity_manager)->query($id)... ...
  41. 41. relax
  42. 42. Calculating an Etag, or a date, is cheaper than generating a full MVC response
  43. 43. Control your power
  44. 44. Additional managementpublic function articleAction($id){ $res = new Response() $res->setVary(array( Accept-Encoding, )); $res->setPublic(); $res->setNotModified(); ...
  45. 45. Varying the responsepublic function articleAction($id){ $res = new Response() $res->setVary(array( Accept-Encoding, )); $res->setPublic(); $res->setNotModified(); ...
  46. 46. Cacheable by all cachespublic function articleAction($id){ $res = new Response() $res->setVary(array( Accept-Encoding, )); $res->setPublic(); $res->setNotModified(); ...
  47. 47. or by local onlypublic function articleAction($id){ $res = new Response() $res->setVary(array( Accept-Encoding, )); $res->setPrivate(); $res->setNotModified(); ...
  48. 48. Good old 304public function articleAction($id){ $res = new Response() $res->setVary(array( Accept-Encoding, )); $res->setPrivate(); $res->setNotModified(); ...
  49. 49. Stalepublic function articleAction($id){ $res = new Response() $res->setVary(array( Accept-Encoding, )); $res->setPrivate(); $res->expire(); ...
  50. 50. but hey, you say
  51. 51. HTTPs cache fails when dealing with really dynamic pages,because consumers will always have to hit the origin server,although a part of the page would be cacheable ( header and footer, for example )
  52. 52. no bueno, you say
  53. 53. NOPE
  54. 54. ESI was built for that http://www.w3.org/TR/esi-lang<esi:include src="http://mysite.com/twitterfeeds.html" />
  55. 55. ESI and Symfony2# controller$response->setSharedMaxAge(3600);# app/config/config.ymlframework: esi: { enabled: true }# template{% render ...:twitterFeeds with {}, {standalone: true} %}# fragment controller$response->setSharedMaxAge(15);
  56. 56. ESI and Symfony2# controller$response->setSharedMaxAge(3600);# app/config/config.ymlframework: esi: { enabled: true }# template{% render ...:twitterFeeds with {}, {standalone: true} %}# fragment controller$response->setSharedMaxAge(15);
  57. 57. ESI and Symfony2# controller$response->setSharedMaxAge(3600);# app/config/config.ymlframework: esi: { enabled: true }# template{% render ...:twitterFeeds with {}, {standalone: true} %}# fragment controller$response->setSharedMaxAge(15);
  58. 58. ESI and Symfony2# controller$response->setSharedMaxAge(3600);# app/config/config.ymlframework: esi: { enabled: true }# template{% render ...:twitterFeeds with {}, {standalone: true} %}# fragment controller$response->setSharedMaxAge(15);
  59. 59. ESI and Symfony2# controller$response->setSharedMaxAge(3600);# app/config/config.ymlframework: esi: { enabled: true }# template{% render ...:twitterFeeds with {}, {standalone: true} %}# fragment controller$response->setSharedMaxAge(15);
  60. 60. Use Symfony2 reverse proxy
  61. 61. Use Symfony2 reverse proxy (slower)
  62. 62. or Varnishhttp://www.varnish-cache.org/
  63. 63. Varnish configurationbackend apache { .host = "127.0.0.1"; .port = "8080";}sub vcl_recv { unset req.http.Accept-Encoding; unset req.http.Vary; set req.http.Surrogate-Capability = "abc=ESI/1.0";}sub vcl_fetch { esi; ...
  64. 64. Varnish configurationbackend apache { .host = "127.0.0.1"; tell Symfony2 .port = "8080"; youre behind a reverse proxy} able to handle the ESI specificationsub vcl_recv { unset req.http.Accept-Encoding; unset req.http.Vary; set req.http.Surrogate-Capability = "abc=ESI/1.0";}sub vcl_fetch { esi; ...}
  65. 65. Why HTTP caching is so important?
  66. 66. Ask yourself:as a developer, what do I want on my application?
  67. 67. EvolveLoose coupling Work less
  68. 68. EvolveBecause you want your platform to extensible Loose coupling Work less
  69. 69. EvolveBecause you want your platform to extensible Loose couplingBecause you want it to be easy to integrate with, evolve, plugand mantain Work less
  70. 70. EvolveBecause you want your platform to extensible Loose couplingBecause you want it to be easy to integrate with, evolve, plugand mantain Work lessBecause every LoC is bug-prone and our man-day is a hard-to-scale cost
  71. 71. enters our Hero #1
  72. 72. enters our Hero #2
  73. 73. http://www.lullabot.com/articles/a-beginners-guide-to-caching-data
  74. 74. 2007
  75. 75. 2011?
  76. 76. it supportsHTTP caching! http://drupal.org/node/147310
  77. 77. it supportsHTTP caching! http://drupal.org/node/147310 ( people is supposed to clap their hands here )
  78. 78. but
  79. 79. wait.... how?
  80. 80. Default headersExpires = Sun, 19 Nov 1978 05:00:00 GMT,Cache-Control = no-cache, must-revalidate,ETag = $_SERVER[REQUEST_TIME],
  81. 81. Default headersExpires = Sun, 19 Nov 1978 05:00:00 GMT,Cache-Control = no-cache, must-revalidate,ETag = $_SERVER[REQUEST_TIME],
  82. 82. Default headersExpires = Sun, 19 Nov 1978 05:00:00 GMT,Cache-Control = no-cache, must-revalidate,ETag = $_SERVER[REQUEST_TIME],
  83. 83. Default headersExpires = Sun, 19 Nov 1978 05:00:00 GMT,Cache-Control = no-cache, must-revalidate,ETag = $_SERVER[REQUEST_TIME],
  84. 84. is that even legal?
  85. 85. "but you can redefine them!"
  86. 86. drupal_add_http_header()
  87. 87. function drupal_add_http_header(){ ... ... drupal_send_headers($headers);}
  88. 88. so, whatdrupal_send_headers() can do so evil?
  89. 89. header() , of course
  90. 90. which means
  91. 91. drupal_add_http_header(Dumb-Header, Im batman!);...// other logic...drupal_add_http_header(Dumb-Header, Im not);var_dump(headers_list());
  92. 92. drupal_add_http_header(Dumb-Header, Im batman!);...// other logic...drupal_add_http_header(Dumb-Header, Im not);var_dump(headers_list());array 0 => string X-Powered-By: PHP/5.3.2-1ubuntu4.7 1 => string Cache: Im not
  93. 93. drupal_add_http_header(Dumb-Header, I-m batman!);...// other logic...drupal_add_http_header(Dumb-Header, false);var_dump(headers_list());
  94. 94. drupal_add_http_header(Dumb-Header, I-m batman!);...// other logic...drupal_add_http_header(Dumb-Header, false);var_dump(headers_list());array 0 => string X-Powered-By: PHP/5.3.2-1ubuntu4.7 1 => string Cache: Im batman
  95. 95. drupal_add_http_header(Dumb-Header, I-m batman!);...// other logic...drupal_add_http_header(Dumb-Header, );var_dump(headers_list());
  96. 96. drupal_add_http_header(Dumb-Header, I-m batman!);...// other logic...drupal_add_http_header(Dumb-Header, );var_dump(headers_list());array 0 => string X-Powered-By: PHP/5.3.2-1ubuntu4.7 1 => string Cache:
  97. 97. or
  98. 98. you can use header_remove() ( PHP 5.3 )
  99. 99. and create a new class to manage/keep track ofheaders and caching directives
  100. 100. but were lazy andwe dont want to reinvent the wheel
  101. 101. GoalsWork less evolve loose coupling
  102. 102. GoalsWork less evolve loose coupling
  103. 103. everything is done for us! :) but....
  104. 104. tmp files, cache tables, procedural code... mmmmh.... gotta be something better
  105. 105. Frameworks
  106. 106. symfony ONE
  107. 107. Cache is used for compiling routes, autoloading, ...
  108. 108. Cache is used for compiling routes, autoloading, ... ...but also for storing the view
  109. 109. GoalsWork less evolve loose coupling
  110. 110. GoalsWork less evolve loose coupling
  111. 111. at least because we use a framework
  112. 112. HTTP
  113. 113. GoalsWork less evolve loose coupling
  114. 114. Less work
  115. 115. because the hard work is delegated to the browser/proxy
  116. 116. Evolve
  117. 117. because cache is abstracted from the application
  118. 118. Loose coupling
  119. 119. because caching is bound to the protocol, HTTP, notto your implementation ( Sf, RoR, Django )
  120. 120. Alessandro Nadalin
  121. 121. Alessandro Nadalin
  122. 122. Alessandro Nadalin odino.org
  123. 123. Alessandro Nadalin odino.org @_odino_
  124. 124. Alessandro Nadalin odino.org @_odino_ http://joind.in/talk/view/2988
  125. 125. Alessandro Nadalin odino.org @_odino_ http://joind.in/talk/view/2988 Thanks!
  126. 126. Creditshttp://www.flickr.com/photos/snakphotography/5004775320/sizes/o/in/photostream/ http://www.flickr.com/photos/ashatenbroeke/4367373081/sizes/z/in/photostream/ http://www.flickr.com/photos/juanpg/3333385784/sizes/z/in/photostream/ http://www.flickr.com/photos/congvo/301678287/sizes/l/in/photostream/ http://www.flickr.com/photos/adamrice/280300202/sizes/l/in/photostream/ http://www.flickr.com/photos/tomer_a/541411897/sizes/o/in/photostream/ http://www.flickr.com/photos/subpra/4514008262/sizes/l/in/photostream/ http://www.flickr.com/photos/lippincott/2539720043/sizes/l/in/photostream/ http://www.flickr.com/photos/rawryder/5086090931/sizes/l/in/photostream/ http://www.flickr.com/photos/robboudon/5312731161/sizes/l/in/photostream/ http://www.flickr.com/photos/bc-burnslibrary/4158243488/sizes/o/in/photostream/http://www.flickr.com/photos/13606325@N08/2416993706/sizes/o/in/photostream/ http://www.flickr.com/photos/neothezion/5135841069/sizes/l/in/photostream/ http://www.flickr.com/photos/planetschwa/2494067809/ http://www.flickr.com/photos/thomasthomas/258931782/ http://www.flickr.com/photos/jungle_boy/220181177/sizes/l/in/photostream/ http://www.flickr.com/photos/ramduk/3708039504/sizes/z/in/photostream/ http://www.flickr.com/photos/sashawolff/3228711025/sizes/l/in/photostream/

×