by @_md
emergent design with
I work here
I contribute here
I tweet here @_md
Marcello Duarte
it’s 2007
@padraicb
@tswicegood
a port for rspec
! = =
http://earthymoon.deviantart.com/art/Elephant-png-122633500 http://sonylisation.deviantart.com/art/Ruby-Nr-2-207831683
bowling.score.should eq(0)
in ruby everything is an object
and all objects are open
bowling.score.should eq(0)
in ruby everything is an object
and all objects are open
http://www.flickr.com/photos/owenbooth/126288240/
bowling.score.should eq(0)
in ruby everything is an object
and all objects are open
http://www.flickr.com/photos/owenbooth/126288240/
bowling.score.should eq(0)
$this->spec($bowling->getScore()) ->shouldEqual(0);
PHPSPEC EARLY SYNTAX EXAMPLE
http://www.flickr.com/photos/jamesrbowe/8403688026/
amber... red... green...
md@bossa:tests $ phpunit .PHPUnit 3.7.14 by Sebastian Bergmann.
PHP Fatal error: Class 'Customer' not found in /Users/mduarte/Documents/NoSync/Lab/phpunit/tests/CustomerTest.php on line 8
Fatal error: Class 'Customer' not found in /Users/mduarte/Documents/NoSync/Lab/phpunit/tests/CustomerTest.php on line 8
you gotta be mocking me!
public function testUpdateWithEqualTypes(){ $installer = $this->createInstallerMock(); $manager = new InstallationManager('vendor'); $manager->addInstaller($installer);
$initial = $this->createPackageMock(); $target = $this->createPackageMock(); $operation = new UpdateOperation($initial, $target, 'test');
$initial ->expects($this->once()) ->method('getType') ->will($this->returnValue('library')); $target ->expects($this->once()) ->method('getType') ->will($this->returnValue('library'));
$installer ->expects($this->once()) ->method('supports') ->with('library') ->will($this->returnValue(true));
$installer ->expects($this->once()) ->method('update') ->with($this->repository, $initial, $target);
@_md
@everzet
goals{fun to work with
goals{development toolfun to work with
goals{development toollet’s not get in the way
fun to work with
goals{enforce (mockist) TDD
development toollet’s not get in the way
fun to work with
goals{enforce (mockist) TDDdo it the PHP way
development toollet’s not get in the way
fun to work with
{ "require-dev": { "phpspec/phpspec": "2.0.*@dev" }, "config": { "bin-dir": "bin" }, "autoload": { "psr-0": { "": "src" } }}
$ bin/phpspec describe Some/Class$ bin/phpspec describe Some/Class
$ bin/phpspec describe Some/Class
$ bin/phpspec run
$ bin/phpspec describe Some/Class
$ bin/phpspec run
$ bin/phpspec describe Some/Class
$ bin/phpspec run
phpspec generators
$ bin/phpspec describe Some/Class
$ bin/phpspec run
phpspec generators
$ bin/phpspec describe Some/Class
$ bin/phpspec run
$ editor_of_choice . phpspec generators
$ bin/phpspec describe Some/Class
$ bin/phpspec run
$ editor_of_choice . phpspec generators
$ bin/phpspec describe Some/Class
$ bin/phpspec run
$ editor_of_choice . phpspec generators
$ bin/phpspec describe Some/Class
$ bin/phpspec run
$ editor_of_choice . phpspec generators
$ bin/phpspec describe Some/Class
$ bin/phpspec run
$ editor_of_choice . phpspec generators
$ bin/phpspec describe Some/Class
$ bin/phpspec run
$ editor_of_choice . phpspec generators
little demo
emergent design
design emerge iteratively driven by tests
designis...
design softwareis...
design softwareis
to describe how we’re solving a problem
calculate cost variance for a period
calculate cost variance for a period
Period
first learn design, then emergent design
“Key in making great and growable systems is to
design how its modules communicate
[and not] what their properties and behaviours should be.”
Messaging
View
poin
ts R
esea
rch
Inst
itute
Sou
rce
- Bon
nie
Mac
bird
UR
L -h
ttp://
ww
w.vp
ri.or
g
messaging
$this->person->getCar()->getEngine()->ignite();
focus on messagingmakes the code flexible
$this->person->startCar();
describing how objects interact to solve problemswhich roles, responsibilities and messages
design softwareis
big design up front
IT’S HARD TO CHANGE LATER.
WE NEED TO THINK ABOUT THINGS BEFORE DEVELOPING.
WE NEED TO MAKE SURE WE DON’T MISS ANYTHING.
THIS IS JUST THE WAY WE DO IT.
relative cost of repaircos
t
time
analysis design code test deploy rework
$
yagni
61%of the requested features are actually delivered
[Standish Group Report 06]
27%of requested features are actually used
5% to 10%are responsible for realising the benefits envisioned
design for the high priority itemsand make it easy to change later
describing how objects interact to solve problemswhich roles, responsibilities and messages
in a change-friendly way
design software in agileis
easier said than done?
test
coderefactor
use simple design rules to refactor
1. All tests run and pass2. Remove duplication3. Remove opacity4. Remove complexity
results in code
1. Testable2. Modular3. Expressive4. Simple
lack of tests breaks inner quality
1. Viscosity2. Immobility, Rigidity, Fragility3. Unreadable4. Complex
simple design is great to detect smells
simple design1. All tests run and pass2. Remove duplication3. Remove opacity4. Remove complexity
smells1. Any tests smells?2. Any DRY smells?3. Any opacity smells?4. Any complexity smells?
Test Smells
• Lack of tests
• Tests are not unitary
• Setup is too complex
• Unclear exercise
• More than one expectation in a test
• No expectation
• Too many paths
Dry Smells
• Simple duplication
• Logic duplication
• Duplication of constant
• Alternative classes with different interfaces
Opacity Smells
• Name not from domain
• Name not expressing intent
• Feature envy
• Method does more than one thing
• Method too long
• Primitive obsession
• Comments in the code
• Middle Man
Complexity Smells
• Unnecessary else
• Unnecessary if
• Unnecessary switch
• Too many arguments passed
• Inappropriate Intimacy
• Work in construction
• Static context
use design patterns to refactor
creational? behavioural? structural?
what can happen in a method?
return a value modify stateprint somethingthrow an exceptiondelegate{methods
return a value modify stateprint somethingthrow an exceptiondelegate{methods
not the final behaviour
return a value print somethingthrow an exceptiondelegate{methods
we should probably delegate that too
return a value throw an exceptiondelegate{methods
design delegation with mocks
start by defining behaviour
internally delegate to another method
Finally
• Define new role• Extract collaborators using mocks• Move behaviour definition to new collaborator test
phpspec
emergent design
simple design and smells
designing composition with mocks
Marcello Duarte
I work here
I contribute here
I tweet here @_md
Thank you !
Questions or Comments?
want to learn more? bitly.com/inviqa-bdd-training
@_md joind.in/8459