moving away from legacy code with bdd
DESCRIPTION
Greenfield projects are awesome – you can develop highest quality application using best practices on the market. But what if your bread actually is Legacy projects? Does it mean that you need to descend into darkness of QA absence? This talk will show you how to be successful even with the oldest legacy projects out there through the introduction of Agile processes and tools like Behat.TRANSCRIPT
Moving away from legacy code
with BDD
Who?!
BDD Evangelist !
BDD Practice Manager @Inviqa !
Creator of Behat, Mink, PhpSpec2, Prophecy
!Contributor to Symfony2, Composer
!Host of the “Elephant in the Room”
podcast
This talk is about
• Solving purely technical “TCIAM” problem with agile business analysis and discovery processes
• Building a delivery strategy on the idea of constant change
• Real-life experience
This talk is not about
• Greenfield projects
• Solutions for everyone
• How to write code
This talk is not about
• Greenfield projects
• Maintenance-mode projects
• Solutions for everyone
• How to write code (well, mostly)
Legacy projects
How most developers see their next project
My next project
My next project
His actual next project
Agile, TDD, BDD, General QA, etc…
// TODO: refactor this later
Is it really that bad?
If the project can afford at least one full-time specialist on a payroll that whines how horrible this project is, then surely it did something right.
// TODO: refactor this later
// TODO: refactor this later
// TODO: refactor this later
This world is full of brilliant projects that nobody wants to whine about. Sadly, it’s often simply because there’s no one left to pay for that.
The truth is: You deliver value!
Just not as effectively as you could
// TODO: refactor this later
Agile, TDD, BDD, General QA, etc…
How?
Three options
1. Rewrite an entire application using “the right way”
2. Do functional refactoring
3. Do business-oriented rewrite using “BDD pipeline”
#1: Full Rewrite
#1: Full Rewrite
• Scrum / Kanban
• TDD / BDD / DDD / Pair-programming
• New everything
• Mirroring functionality
#1: Income
6 Months later…
#1: Almost there…
#1: Full Rewrite
Just spaghetti, please: 4 man years
Full London meal (TDD, BDD, Agile, QA): ??? man years
#2: FUNCTIONAL Refactoring
#2: Functional Refactoring
• Blackbox testing
• New routing
• New templating system
• Migration of model layer (MySQL -> Mongo)
#2: Income
6 Months later…
#2: Ta-da!!!
– Your client. (most likely)
“Exactly what did you do here?”
#3: BDD PIPELINEAKA Business-Oriented rewrite
Why do some legacy projects suck?
Cost
Time
Because of the cost of change
… Of change where?
Why do applications change?
Welcome to the wonderland
of Agile Business Analysis
Questionnaire
1. What is the goal and minimal valuable product?
2. What is the minimal set of features to support it?
3. Which features are more likely to change?
4. How fully those features should be implemented?
5. How to avoid gold plating?
“BDD Pipeline”
1. Impact Mapping
2. Feature Mapping
3. Prioritisation
4. Example Workshop
5. Full-stack BDD
1. What is the Goal & minimal valuable product?
Impact Mapping
– Gojko Adzic
“Impact mapping is a strategic planning technique that prevents organisations from getting lost
while building products and delivering projects, by clearly communicating assumptions, helping teams align their activities with overall business objectives and make better roadmap decisions.”
Four levels of Impact Map
1. Why? are we doing all this (rewrite)? What is the goal we’re trying to achieve?
2. Who? will be impacted by it?
3. How? can they help us to achieve the goal?
4. What? can we do to support them?
MVP
impactmapping.org
2. What is the minimal set of features to support it?
Feature Mapping
– Marcello Duarte
“Feature mapping is a backlog grooming technique. It is a graphical process which helps teams in finding features that are necessary to
support discovered MVP”
Three levels of feature map
1. What? is the minimal marketable feature?
2. Who? will be impacted by this feature?
3. What? particular parts of this feature do they need to create this impact?
Product Backlog
In order to buy more products As a customer I need to have a product autocompletion in the search field
3. Which features are more likely to change?
Prioritisation workshop
In order to maintain my shopping history As a site visitor I need to be able to register on this site
In order to maintain my shopping history As a site visitor I need to be able to register on this site
benefit !actor
SELECT s.* FROM backlog as s ORDER BY s.role, s.benefit LIMIT 25
4. How fully those features should be implemented?
Example workshops
Three layers of a User-Story
• Business rule(s)
• Communication
• Acceptance criteria
Three layers of a User-Story
• Business rule(s) == Acceptance criteria
• Communication
Three layers of a User-Story
• Business rule(s) == Acceptance criteria
• Communication == Examples
Three layers of a User-Story
• Business rule(s)
• Communication == Examples == Acceptance criteria
in order to maintain my shopping history as a site visitor i need to be able to register on this site
Feature: registration
in order to maintain my shopping history as a site visitor i need to be able to register on this site
Feature: registration
Scenario: Successful registration when visitor provides all the required info
in order to maintain my shopping history as a site visitor i need to be able to register on this site
Feature: registration
Scenario: Successful registration when visitor provides all the required info
Scenario: Unable to register when visitor misses required info
in order to maintain my shopping history as a site visitor i need to be able to register on this site
Feature: registration
Scenario: Successful registration when visitor provides all the required info
Scenario: Unable to register when visitor misses required info
Scenario: ...
Scenario: ...
Scenario: ...
Scenario: ...
Scenario: ...
in order to maintain my shopping history as a site visitor i need to be able to register on this site
Feature: registration
Scenario: Successful registration when visitor provides all the required info
Scenario: Unable to register when visitor misses required info
Scenario: ...
in order to maintain my shopping history as a site visitor i need to be able to register on this site
Feature: registration
Scenario: Successful registration when visitor provides all the required info
Given I am on the homepage When I follow “sign up” And I fill in registration form And I submit it Then I should be successfully registered And I should be on the homepage again
5. How to avoid gold plating?
Delivery
Architecture
ArchitectureHTTP layering
Legacy system
Infrastructure
[GET] /products
Legacy system
Infrastructure
[GET] /products
[GET] /products/123
Legacy system
Infrastructure
[GET] /products
[GET] /products/123
New system
Legacy system
Infrastructure
[GET] /products
[GET] /products/123
New system
New system
Implementation
ImplementationFull-stack BDD
Stories
Examples
Describe
ImplementDesign
Stories
Examples
Describe
ImplementDesign
Scenario-BDD
in order to maintain my shopping history as a site visitor i need to be able to register on this site
Feature: registration
Scenario: Successful registration when visitor provides all the required info
Given I am on the homepage When I follow “sign up” And I fill in registration form And I submit it Then I should be successfully registered And I should be on the homepage again
in orderas ai need
Feature:
Scenario: Successful registration when visitor provides
Given I am on the When And I fill in And I submit itThen And I should be on the homepage
What could be automated should be automated
assertEquals(Your Feature, Your App)
Setup
1. Dump your sprint features into text files
2. Put those text files into the `features/` folder inside project
3. Install behat (via composer or behat.phar)
4. Initialize behat test suite by running `bin/behat —init`
Feature Context<?php !use Behat\Behat\Context\ClosuredContextInterface, Behat\Behat\Context\TranslatedContextInterface, Behat\Behat\Context\BehatContext, Behat\Behat\Exception\PendingException; use Behat\Gherkin\Node\PyStringNode, Behat\Gherkin\Node\TableNode; !class FeatureContext extends BehatContext { }
First run$> bin/behat ... You can implement step definitions for undefined steps with these snippets: ! /** * @Then I should see :arg1 */ public function iShouldSee($arg1) { throw new PendingException(); }
...
Append snippets$> bin/behat --append-snippets
Feedback loop$> bin/behat !Feature: registration in order to maintain my shopping history as a site visitor i need to be able to register on this site ! Scenario: Successful registration when visitor provides all the required info Given I am on the homepage TODO: write pending definition When I follow “sign up” And I fill in registration form And I submit it Then I should be successfully registered And I should be on the homepage again
Stories
Examples
Describe
ImplementDesign
Scenario-BDD
Colour it Red
Colour it red /** * @Given /^I am on the homepage$/ */ public function iAmOnTheHomepage() { $crawler = new \Some\Crawler\Lib\Crawler(); $crawler->goto(“http://localhost:8080/”); if (200 !== $crawler->getCurrentStatusCode()) { throw new RuntimeException(‘Can not open homepage’); } }
Colour it red$> bin/behat !Feature: registration in order to maintain my shopping history as a site visitor i need to be able to register on this site ! Scenario: Successful registration when visitor provides all the required info Given I am on the homepage Can not open homepage (RuntimeException) When I follow “sign up” And I fill in registration form And I submit it Then I should be successfully registered And I should be on the homepage again
Stories
Examples
Describe
ImplementDesign
Scenario-BDD
Change the messageAs quickly as possible
Change the message$> bin/behat !Feature: registration in order to maintain my shopping history as a site visitor i need to be able to register on this site ! Scenario: Successful registration when visitor provides all the required info Given I am on the homepage Can not open homepage (RuntimeException) When I follow “sign up” And I fill in registration form And I submit it Then I should be successfully registered And I should be on the homepage again
Change the message$> bin/behat !Feature: registration in order to maintain my shopping history as a site visitor i need to be able to register on this site ! Scenario: Successful registration when visitor provides all the required info Given I am on the homepage Route … not found (FrameworkException) When I follow “sign up” And I fill in registration form And I submit it Then I should be successfully registered And I should be on the homepage again
Change the message$> bin/behat !Feature: registration in order to maintain my shopping history as a site visitor i need to be able to register on this site ! Scenario: Successful registration when visitor provides all the required info Given I am on the homepage Template … not found (FrameworkException) When I follow “sign up” And I fill in registration form And I submit it Then I should be successfully registered And I should be on the homepage again
Change the message$> bin/behat !Feature: registration in order to maintain my shopping history as a site visitor i need to be able to register on this site ! Scenario: Successful registration when visitor provides all the required info Given I am on the homepage When I follow “sign up” TODO: write pending definition And I fill in registration form And I submit it Then I should be successfully registered And I should be on the homepage again
behat.org
Change the message$> bin/behat !Feature: registration in order to maintain my shopping history as a site visitor i need to be able to register on this site ! Scenario: Successful registration when visitor provides all the required info Given I am on the homepage When I follow “sign up” And I fill in registration form And I submit it Then I should be successfully registered Object `User` and its method `isRegistered` does not exist (RuntimeException) And I should be on the homepage again
Stories
Examples
Describe
ImplementDesign
Spec-BDD
Setup
1. Install phpspec via composer
2. use it
Stories
Examples
Describe
ImplementDesign
Spec-BDD
Prepare your first spec$> bin/phpspec desc Acme/Userbase/User
Describe your first message<?php !namespace spec\Acme\Userbase; !class User extends ObjectBehavior{ function it_is_registered_by_default() { $this->shouldBeRegistered(); } }
Colour it red$> bin/phpspec !Class “Acme\Userbase\User” does not exist. Create? [Y/n] y !Method `Acme\Userbase\User::isRegistered()` does not exist. Create? [Y/n] y
Stories
Examples
Describe
ImplementDesign
Spec-BDD
Stories
Examples
Describe
ImplementDesign
Spec-BDD
Stories
Examples
Describe
ImplementDesign
Spec-BDD
phpspec.net
Verify feature$> bin/behat !Feature: registration in order to maintain my shopping history as a site visitor i need to be able to register on this site ! Scenario: Successful registration when visitor provides all the required info Given I am on the homepage When I follow “sign up” And I fill in registration form And I submit it Then I should be successfully registered And I should be on the homepage again
Verify feature$> bin/behat !Feature: registration in order to maintain my shopping history as a site visitor i need to be able to register on this site ! Scenario: Successful registration when visitor provides all the required info Given I am on the homepage When I follow “sign up” And I fill in registration form And I submit it Then I should be successfully registered And I should be on the homepage again
Stories
Examples
Describe
ImplementDesign
#3: Income
6 months later…
#3: Same ashtrays, better car
We do that for clients
We do that for clientsAnd teach others in those rare
moments when we don’t
http:// .com