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

Separation of concerns - DPC 12

1761ecd7fe763583553dde43e62c47bd?s=47 Joshua Thijssen
June 08, 2012
340

Separation of concerns - DPC 12

1761ecd7fe763583553dde43e62c47bd?s=128

Joshua Thijssen

June 08, 2012
Tweet

Transcript

  1. Separation of Concerns

  2. Separation of concerns About Joshua  Joshua Thijssen, NoxLogic /

    Techademy  Freelance Consultant, Developer, Trainer  Development in PHP, Python, Perl, C, Java  jthijssen@noxlogic.nl  @jaytaph
  3. Separation of concerns About Stephan  Stephan Hochdörfer, bitExpert AG

     Department Manager Research Labs  enjoying PHP since 1999  S.Hochdoerfer@bitExpert.de  @shochdoerfer
  4. Separation of concerns It is what I sometimes have called

    the separation of concerns, which [...] is yet the only available technique for effective ordering of one's thoughts. Edsger W. Dijkstra, "On the role of scientific thought" (1974)
  5. Separation of concerns SoC […] is the process of breaking

    a computer program into distinct features that overlap in functionality as little as possible. http://en.wikipedia.org/wiki/Separation_of_concerns
  6. Separation of concerns It`s all about focusing!

  7. Separation of concerns One step a time. Focus on the

    details!
  8. Separation of concerns <?php $items = array(); $token = file_get_contents("https://graph.facebook.com/oauth/access_token?...");

    $feed = file_get_contents("https://graph.facebook.com/ident/feed?".$token); $feed = json_decode($feed, true); foreach($feed['data'] as $post) { if('123456789012' === $post['from']['id']) { $items[] = array( 'date' => strtotime($post['created_time']), 'message' => $post['message']); } } $feed = file_get_contents("http://search.twitter.com/search.json?q=from:ident"); $feed = json_decode($feed, true); foreach($feed['results'] as $tweet) { $items[] = array( 'date' => strtotime($tweet['created_at']), 'message' => $tweet['text']); } foreach($items as $item) { echo $item['message']; }
  9. Separation of concerns <?php $items = array(); $token = file_get_contents("https://graph.facebook.com/oauth/access_token?...");

    $feed = file_get_contents("https://graph.facebook.com/ident/feed?".$token); $feed = json_decode($feed, true); foreach($feed['data'] as $post) { if('123456789012' === $post['from']['id']) { $items[] = array( 'date' => strtotime($post['created_time']), 'message' => $post['message']); } } $feed = file_get_contents("http://search.twitter.com/search.json?q=from:ident"); $feed = json_decode($feed, true); foreach($feed['results'] as $tweet) { $items[] = array( 'date' => strtotime($tweet['created_at']), 'message' => $tweet['text']); } foreach($items as $item) { echo $item['message']; }} Controller part!
  10. Separation of concerns <?php $items = array(); $token = file_get_contents("https://graph.facebook.com/oauth/access_token?...");

    $feed = file_get_contents("https://graph.facebook.com/ident/feed?".$token); $feed = json_decode($feed, true); foreach($feed['data'] as $post) { if('123456789012' === $post['from']['id']) { $items[] = array( 'date' => strtotime($post['created_time']), 'message' => $post['message']); } } $feed = file_get_contents("http://search.twitter.com/search.json?q=from:ident"); $feed = json_decode($feed, true); foreach($feed['results'] as $tweet) { $items[] = array( 'date' => strtotime($tweet['created_at']), 'message' => $tweet['text']); } foreach($items as $item) { echo $item['message']; } View part!
  11. Separation of concerns Very unstable. Not safe for changes....

  12. Separation of concerns „Make everything as simple as possible...“

  13. Separation of concerns Establish boundaries

  14. Separation of concerns What are the boundaries? Presentation Layer

  15. Separation of concerns What are the boundaries? Presentation Layer Business

    Layer
  16. Separation of concerns What are the boundaries? Presentation Layer Business

    Layer Resource Access Layer
  17. Isolate functionality, break it apart! Separation of concerns

  18. Separation of concerns <?php namespace Acme\DemoBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;

    use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; class DemoController extends Controller { /** * @Route("/", name="_demo") * @Template() */ public function indexAction() { $items = array(); $token = file_get_contents("https://graph.facebook.com/oauth/access_to..."); $feed = file_get_contents("https://graph.facebook.com/ident/feed?".$token); $feed = json_decode($feed, true); foreach($feed['data'] as $post) { if('123456789012' === $post['from']['id']) { $items[] = array( 'date' => strtotime($post['created_time']), 'message' => $post['message']); } }
  19. Separation of concerns $feed = file_get_contents("http://search.twitter.com/search.json?..."); $feed = json_decode($feed, true);

    foreach($feed['results'] as $tweet) { $items[] = array( 'date' => strtotime($tweet['created_at']), 'message' => $tweet['text']); } return array('items' => $items); } }
  20. Focus on one responsibility a time! Separation of concerns

  21. Separation of concerns <?php namespace Acme\DemoBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;

    use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; class DemoController extends Controller { /** * @Route("/", name="_demo") * @Template() */ public function indexAction() { $items = array(); $token = file_get_contents("https://graph.facebook.com/oauth/access_to..."); $feed = file_get_contents("https://graph.facebook.com/ident/feed?".$token); $feed = json_decode($feed, true); foreach($feed['data'] as $post) { if('123456789012' === $post['from']['id']) { $items[] = array( 'date' => strtotime($post['created_time']), 'message' => $post['message']); } } Facebook connector
  22. Separation of concerns $feed = file_get_contents("http://search.twitter.com/search.json?..." ); $feed = json_decode($feed,

    true); foreach($feed['results'] as $tweet) { $items[] = array( 'date' => strtotime($tweet['created_at']), 'message' => $tweet['text']); } return array('items' => $items); } } Twitter connector
  23. Interfaces as a contract Separation of concerns

  24. Separation of concerns <?php interface ConnectorInterface { /** * Will

    return an array of the latest posts. * return array */ public function getLatestPosts() { } }
  25. Separation of concerns <?php class FacebookConnector implements ConnectorInterface { protected

    $handle; public function __construct($handle) { $this->handle = $handle; } public function getLatestPosts() { $items = array(); $token = file_get_contents("https://graph.facebook.com/oauth/access..."); $feed = file_get_contents("https://graph.facebook.com/. $this->handle."/feed?".$token); $feed = json_decode($feed, true); foreach($feed['data'] as $post) { if('123456789012' === $post['from']['id']) { $items[] = array( 'date' => strtotime($post['created_time']), 'message' => $post['message']); } } return $items; } }
  26. Separation of concerns <?php class FacebookConnector implements ConnectorInterface { protected

    $handle; public function __construct($handle) { $this->handle = $handle; } public function getLatestPosts() { $token = $this->getAccessToken(); return $this->readPosts($token); } protected function getAccessToken() { return file_get_contents("https://graph.facebook.com/oauth/access_?..."); } protected function readPosts($token) { // read the post, filter all relevant and return them... } }
  27. Separation of concerns <?php class FacebookConnectorV2 extends FacebookConnector { protected

    function getAccessToken() { return md5($this->handle); } } Easy to extend, will not influence the behaviour of other methods!
  28. Separation of concerns <?php namespace Acme\DemoBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;

    use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; class DemoController extends Controller { /** * @Route("/", name="_demo") * @Template() */ public function indexAction() { $items = array(); $fb = $this->get('FbConnector'); $items += $fb->getLatestPosts(); $feed = file_get_contents("http://search.twitter.com/search.json?..."); $feed = json_decode($feed, true); foreach($feed['results'] as $tweet) { $items[] = array( 'date' => strtotime($tweet['created_at']), 'message' => $tweet['text']); }
  29. Separation of concerns <?php namespace Acme\DemoBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;

    use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; class DemoController extends Controller { /** * @Route("/", name="_demo") * @Template() */ public function indexAction() { $items = array(); $fb = $this->get('FbConnector'); $items += $fb->getLatestPosts(); $twitter = $this->get('TwitterConnector'); $items += $twitter->getLatestPosts(); return array('items' => $items); } }
  30. Will improve the testability! Separation of concerns

  31. Will reduce tight coupling! Separation of concerns

  32. Will increase component reuse! Separation of concerns

  33. The value of separation Why should I do it? Separation

    of concerns
  34. The value of separation 1. Getting rid of code duplication

    Separation of concerns
  35. The value of separation 2. Application becomes more stable and

    easier to understand Separation of concerns
  36. The value of separation 3. Single responsibility offers clear extension

    points Separation of concerns
  37. The value of separation 4. Increases the reusability of components

    Separation of concerns
  38. Separation of concerns How to separate the concerns?

  39. Separation of concerns How to separate? Horizontal Separation Presentation Layer

    Business Layer Resource Access Layer
  40. Separation of concerns How to separate? Horizontal Separation ./symfony |-app

    |---cache |---config |---Resources |-src |---Acme |-----DemoBundle |-------Controller |-------Resources |---------config |---------public |-----------css |-----------images |---------views |-----------Demo |-----------Welcome |-------Tests |---------Controller |-web
  41. Separation of concerns How to separate? Service Separation Service Interface

    Layer Business Layer Resource Access Layer
  42. Separation of concerns How to separate? Service Separation Frontend /

    UI Webservers REST API Datastore Solr Search Service
  43. Separation of concerns How to separate? Vertical Separation Module A

    Module B Module C
  44. Separation of concerns How to separate? Vertical Separation ./symfony |-app

    |---cache |---config |---Resources |-src |---Acme |-----AdminBundle |-------Controller |-------Resources |-------Tests |-----ProductsBundle |-------Controller |-------Resources |-------Tests |-----CustomersBundle |-------Controller |-------Resources |-------Tests |-web
  45. Separation of concerns How to separate? Vertical Separation Presentation Layer

    Business Layer Resource Access Layer Presentation Layer Business Layer Resource Access Layer Presentation Layer Business Layer Resource Access Layer
  46. Separation of concerns How to separate? Vertical Separation ./symfony |-app

    |---cache |---config |---Resources |-src |---Acme |-----AdminBundle |-------Controller |-------Resources |-------Tests |-----ProductsBundle |-------Controller |-------Resources |-------Tests |-----CustomersBundle |-------Controller |-------Resources |-------Tests |-web
  47. Cross-cutting concerns? How to deal with security or logging aspects?

    Separation of concerns
  48. Separation of concerns How to separate? Aspect Separation Presentation Layer

    Business Layer Resource Access Layer Aspects
  49. Separation of concerns How to separate? Aspect Separation <?php namespace

    Acme\Products\Aspects; /** * @FLOW3\Aspect */ class LoggingAspect { /** * @FLOW3\Inject * @var \Acme\Logger\LoggerInterface */ protected $logger; /** * @param \TYPO3\FLOW3\AOP\JoinPointInterface $joinPoint * @FLOW3\Before("method(Acme\Products\Model\Product->delete())") */ public function log(\TYPO3\FLOW3\AOP\JoinPointInterface $jp) { $product = $jp->getMethodArgument('product'); $this->logger->info('Removing ' . $product->getName()); } }
  50. Separation of concerns Dependency Direction

  51. Separation of concerns Dependency Direction "High-level modules should not depend

    on low-level modules. Both should depend on abstractions." Robert C. Martin
  52. Separation of concerns Inverting Concerns Presentation Layer Business Layer Resource

    Access Layer
  53. Separation of concerns Inverting Concerns Presentation Layer Business Layer Resource

    Access Layer Presentation Layer Business Layer Resource Access Layer UI Component
  54. Separation of concerns Inverting Concerns The goal of Dependency Injection

    is to separate the concerns of obtaining the dependencies from the core concerns of a component.
  55. Separation of concerns What are the benefits? Let`s recap....

  56. Separation of concerns What are the benefits? 1. Facilitate reusability

  57. Separation of concerns What are the benefits? 2. Ensure the

    maintainability
  58. Separation of concerns What are the benefits? 3. Increasing the

    code quality
  59. Separation of concerns What are the benefits? 4. Enables everyone

    to understand the application
  60. Separation of concerns What are the benefits? 5. Allows developers

    to work on components in isolation
  61. Thank you!

  62. http://joind.in/6244