The framework as an implementation detail

Post on 10-May-2015

5024 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

What would your application look like if it were written by the people who write the testing frameworks? If unit tests make classes more modular, by forcing you to test it in isolation, then what is the effect of expanding this to a less granular level, the acceptance and functional test. The more modern application architecture evolves, the more we hear the very old patterns being rediscovered and re-adopted. 1979 Trygve's MVC is a classic example, so are the SOLID principles. In this talk we will look on how Symfony allows for a really decoupled, easy to test application, by following on the footsteps of Alistair Cockburn's hexagonal architecture.

Transcript

The Framework as an Implementation DetailMarcello Duarte / Konstantin Kudryashov

@_md @everzeta SensioLabsEvent

About us

@_mdMarcello Duarte HEAD OF TRAINING, INVIQA

@everzetKonstantin Kudryashov BDD PRACTICE MANAGER, INVIQA

@_md @everzeta SensioLabsEvent

This talk

[ Convenience ][ Choices ][ Future ]

@_md @everzeta SensioLabsEvent

Choice

Convenience

http://www.flickr.com/photos/johnwinkelman/6200402992/

@_md @everzeta SensioLabsEvent

We dolove .

@_md @everzeta SensioLabsEvent

Promise

“A framework is ‘just’ one of the tools to help you develop better and faster”

– Symfony documentation

@_md @everzeta SensioLabsEvent

“The only way to go fast is to go well” – Uncle Bob

FAST SLOW

QUALITY SWITCH

@_md @everzeta SensioLabsEvent

Relative cost of repair

analysis design code test support

@_md @everzeta SensioLabsEvent

Convenientvs

Maintainable

@_md @everzeta SensioLabsEvent

A framework is “convenient” when it makes choices for you

BookController e

xtends Controlle

r

AuthorsController extends ContainerAwareController

@_md @everzeta SensioLabsEvent

The code is maintainable when the framework lets you make

the choices

@_md @everzeta SensioLabsEvent

Instability and abstractnessinstability

abstractness

@_md @everzeta SensioLabsEvent

The “convenient” code is usually not very testable

@_md @everzeta SensioLabsEvent

Symfony can be convenient

public function updateAction($id){ $em = $this->getDoctrine()->getManager(); $product = $em->getRepository('AcmeStoreBundle:Product')->find($id);

if (!$product) { throw $this->createNotFoundException( 'No product found for id '.$id ); }

$product->setName('New product name!'); $em->flush();

return $this->redirect($this->generateUrl('homepage'));}

@_md @everzeta SensioLabsEvent

The “convenient” Controllertends to ask for more

Integration Tests

@_md @everzeta SensioLabsEvent

Integration Testsstinks of coupling

@_md @everzeta SensioLabsEvent

Feedback

Outer QualityInner Quality

Acceptance TestsUnit Tests

@_md @everzeta SensioLabsEvent

Choice

Choices

http://www.flickr.com/photos/tmartin/32010732/

@_md @everzeta SensioLabsEvent

Should we always TDD? what the Start Up said what the Craftsmen said

@_md @everzeta SensioLabsEvent

We doTest Driven Design

@_md @everzeta SensioLabsEvent

Design is about choices

@_md @everzeta SensioLabsEvent

Design is a professional activity

@_md @everzeta SensioLabsEvent

TDD is about communication

@_md @everzeta SensioLabsEvent

TDD is about your stakeholders

@_md @everzeta SensioLabsEvent

The developers in the team are also stakeholders

@_md @everzeta SensioLabsEvent

TDD is for long term relationships

@_md @everzeta SensioLabsEvent

How many dependencies can you spot?

public function updateAction($id){ $em = $this->getDoctrine()->getManager(); $product = $em->getRepository('AcmeStoreBundle:Product')->find($id);

if (!$product) { throw $this->createNotFoundException( 'No product found for id '.$id ); }

$product->setName('New product name!'); $em->flush();

return $this->redirect($this->generateUrl('homepage'));}

@_md @everzeta SensioLabsEvent

How many dependencies can you spot?

public function updateAction($id){ $em = $this->getDoctrine()->getManager(); $product = $em->getRepository('AcmeStoreBundle:Product')->find($id);

if (!$product) { throw $this->createNotFoundException( 'No product found for id '.$id ); }

$product->setName('New product name!'); $em->flush();

return $this->redirect($this->generateUrl('homepage'));}

DoctrineRedirectRouterModel

@_md @everzeta SensioLabsEvent

Hexagonal Architecture

“The hexagon is not a hexagon because the number six is important, but rather to allow the people doing the drawing

to have room to insert ports and adapters as they need”

:)

[Cockburn 08]

@_md @everzeta SensioLabsEvent

http://www.flickr.com/photos/10849858@N00/2696404813

@_md @everzeta SensioLabsEvent

http://www.flickr.com/photos/mac_users_guide/3680586328/

@_md @everzeta SensioLabsEvent

your application

@_md @everzeta SensioLabsEvent

web gui app

your application

user side ports

test adapter

@_md @everzeta SensioLabsEvent

web gui app

your application

user side ports

test adapter

data side ports

db access service

in memory

db

@_md @everzeta SensioLabsEvent

Hexagonal Architecture

Dbrest

Logs

@_md @everzeta SensioLabsEvent

Dependency Inversion

Higher level modules should not depend on lower level details

[Martin 02]

@_md @everzeta SensioLabsEvent

Naive implementation

controller

use case

utility

uses

uses

@_md @everzeta SensioLabsEvent

Dependency Inversion

use case

serviceadapter

utilityadapter

service

utility

@_md @everzeta SensioLabsEvent

Choice

Let’s see some code

@_md @everzeta SensioLabsEvent

Choice

Future

@_md @everzeta SensioLabsEvent

Choice

Thanks!joind.in/9331

github.com/MarcelloDuarte/hexagonal-symfony

top related