Upload
marcello-duarte
View
5.024
Download
0
Tags:
Embed Size (px)
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.
Citation preview
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