62
Separation of Concerns

Separation of concerns - DPC12

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Separation of concerns - DPC12

Separation of Concerns

Page 2: Separation of concerns - DPC12

Separation of concerns

About Joshua

Joshua Thijssen, NoxLogic / Techademy

Freelance Consultant, Developer, Trainer

Development in PHP, Python, Perl, C, Java

[email protected]

@jaytaph

Page 3: Separation of concerns - DPC12

Separation of concerns

About Stephan

Stephan Hochdörfer, bitExpert AG

Department Manager Research Labs

enjoying PHP since 1999

[email protected]

@shochdoerfer

Page 4: Separation of concerns - DPC12

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)

Page 5: Separation of concerns - DPC12

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

Page 6: Separation of concerns - DPC12

Separation of concerns

It`s all about focusing!

Page 7: Separation of concerns - DPC12

Separation of concerns

One step a time. Focus on the details!

Page 8: Separation of concerns - DPC12

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'];}

Page 9: Separation of concerns - DPC12

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!

Page 10: Separation of concerns - DPC12

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!

Page 11: Separation of concerns - DPC12

Separation of concerns

Very unstable. Not safe for changes....

Page 12: Separation of concerns - DPC12

Separation of concerns

„Make everything as simple as possible...“

Page 13: Separation of concerns - DPC12

Separation of concerns

Establish boundaries

Page 14: Separation of concerns - DPC12

Separation of concerns

What are the boundaries?

Presentation Layer

Page 15: Separation of concerns - DPC12

Separation of concerns

What are the boundaries?

Presentation Layer

Business Layer

Page 16: Separation of concerns - DPC12

Separation of concerns

What are the boundaries?

Presentation Layer

Business Layer

Resource Access Layer

Page 17: Separation of concerns - DPC12

Isolate functionality, break it apart!

Separation of concerns

Page 18: Separation of concerns - DPC12

Separation of concerns

<?phpnamespace 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']); }}

Page 19: Separation of concerns - DPC12

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); }}

Page 20: Separation of concerns - DPC12

Focus on one responsibility a time!

Separation of concerns

Page 21: Separation of concerns - DPC12

Separation of concerns

<?phpnamespace 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

Page 22: Separation of concerns - DPC12

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

Page 23: Separation of concerns - DPC12

Interfaces as a contract

Separation of concerns

Page 24: Separation of concerns - DPC12

Separation of concerns

<?phpinterface ConnectorInterface { /** * Will return an array of the latest posts. * return array */ public function getLatestPosts() { }}

Page 25: Separation of concerns - DPC12

Separation of concerns

<?phpclass 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; }}

Page 26: Separation of concerns - DPC12

Separation of concerns

<?phpclass 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... }}

Page 27: Separation of concerns - DPC12

Separation of concerns

<?phpclass FacebookConnectorV2 extends FacebookConnector {

protected function getAccessToken() { return md5($this->handle); }}

Easy to extend, will not influence the behaviour of other methods!

Page 28: Separation of concerns - DPC12

Separation of concerns

<?phpnamespace 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']);}

Page 29: Separation of concerns - DPC12

Separation of concerns

<?phpnamespace 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); }}

Page 30: Separation of concerns - DPC12

Will improve the testability!

Separation of concerns

Page 31: Separation of concerns - DPC12

Will reduce tight coupling!

Separation of concerns

Page 32: Separation of concerns - DPC12

Will increase component reuse!

Separation of concerns

Page 33: Separation of concerns - DPC12

The value of separation

Why should I do it?

Separation of concerns

Page 34: Separation of concerns - DPC12

The value of separation

1. Getting rid of code duplication

Separation of concerns

Page 35: Separation of concerns - DPC12

The value of separation

2. Application becomes more stableand easier to understand

Separation of concerns

Page 36: Separation of concerns - DPC12

The value of separation

3. Single responsibility offers clear extension points

Separation of concerns

Page 37: Separation of concerns - DPC12

The value of separation

4. Increases the reusability of components

Separation of concerns

Page 38: Separation of concerns - DPC12

Separation of concerns

How to separate the concerns?

Page 39: Separation of concerns - DPC12

Separation of concerns

How to separate? Horizontal Separation

Presentation Layer

Business Layer

Resource Access Layer

Page 40: Separation of concerns - DPC12

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

Page 41: Separation of concerns - DPC12

Separation of concerns

How to separate? Service Separation

Service Interface Layer

Business Layer

Resource Access Layer

Page 42: Separation of concerns - DPC12

Separation of concerns

How to separate? Service Separation

Frontend / UI Webservers

REST API

Datastore

Solr Search Service

Page 43: Separation of concerns - DPC12

Separation of concerns

How to separate? Vertical Separation

ModuleA ModuleB ModuleC

Page 44: Separation of concerns - DPC12

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

Page 45: Separation of concerns - DPC12

Separation of concerns

How to separate? Vertical Separation

PresentationLayer

BusinessLayer

ResourceAccess Layer

PresentationLayer

BusinessLayer

ResourceAccess Layer

PresentationLayer

BusinessLayer

ResourceAccess Layer

Page 46: Separation of concerns - DPC12

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

Page 47: Separation of concerns - DPC12

Cross-cutting concerns?

How to deal with security or logging aspects?

Separation of concerns

Page 48: Separation of concerns - DPC12

Separation of concerns

How to separate? Aspect Separation

Presentation Layer

Business Layer

Resource Access Layer

Aspects

Page 49: Separation of concerns - DPC12

Separation of concerns

How to separate? Aspect Separation<?phpnamespace 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()); }}

Page 50: Separation of concerns - DPC12

Separation of concerns

Dependency Direction

Page 51: Separation of concerns - DPC12

Separation of concerns

Dependency Direction

"High-level modules should not depend on low-level modules.

Both should depend on abstractions."

Robert C. Martin

Page 52: Separation of concerns - DPC12

Separation of concerns

Inverting Concerns

PresentationLayer

BusinessLayer

ResourceAccess Layer

Page 53: Separation of concerns - DPC12

Separation of concerns

Inverting Concerns

PresentationLayer

BusinessLayer

ResourceAccess Layer

PresentationLayer

BusinessLayer

ResourceAccess Layer

UIComponent

Page 54: Separation of concerns - DPC12

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.

Page 55: Separation of concerns - DPC12

Separation of concerns

What are the benefits? Let`s recap....

Page 56: Separation of concerns - DPC12

Separation of concerns

What are the benefits?

1. Facilitate reusability

Page 57: Separation of concerns - DPC12

Separation of concerns

What are the benefits?

2. Ensure the maintainability

Page 58: Separation of concerns - DPC12

Separation of concerns

What are the benefits?

3. Increasing the code quality

Page 59: Separation of concerns - DPC12

Separation of concerns

What are the benefits?

4. Enables everyone to understand the application

Page 60: Separation of concerns - DPC12

Separation of concerns

What are the benefits?

5. Allows developers to work on components in isolation

Page 61: Separation of concerns - DPC12

Thank you!

Page 62: Separation of concerns - DPC12

http://joind.in/6244