…poor coding style and/or lack of documentation makes the code hard to understand
Legacy code is bad when…
…there are no automated tests
Legacy code is bad when…
…it prevents you from delivering as quickly as you would like
Legacy code is bad when…
Why not just rewrite it all?
Over &me, new features get harder and harder to add
Cumulated effort to add new
features
Time
Total cost to maintain the
legacy application
Cost of not rewri&ng
What do we really want?
We need to be able to make the changes we need to make faster and more reliably
So how can we get changes out faster?
Build a safety net
Document the specifications
Build a safety net
Characterisation Test!!
A means to describe (characterise) the actual behaviour of an existing piece of software, and therefore protect existing behaviour of legacy code against unintended changes. !
Term coined by Michael Feathers
Broad, high level automated acceptance tests
Application
To write good automated tests
do not write tests
Write a user’s manual instead…
…but automate it
Automate user journeys
Organise your requirements
Browse the product catalogView product detailsSearch for products
Organise your requirements Browse the product catalogView product detailsSearch for products
Organise your requirements Browse the product catalogView product detailsSearch for products
Illustrate behaviour using examples
Document your business rules
Document your business rules
Good automated acceptance tests have layersMake them maintainable
Use layers!
Keep them tidy
Business Rules
Business Flow
Page/Component interac&ons
Page/Component details
Good automated acceptance tests have layersMake them maintainable
Start with high-level requirements
Drill down into more detailed requirements
Illustrate a requirement with tests
Documenting the specifications
A question of style
Spock
context["When cumulating Frequent Flyer points"] = () => { it["should earn points for each flight"] = () => { member.earnStatusPoints(100); member.earnStatusPoints(50); member.getStatusPoints().should_be(150); }; ! it["should get upgrade when enough points are earned"] = () => { member.earnStatusPoints(00); ! member.getStatus().should_be(Status.Silver); }; }; } } NSpec