Story Driven Web Development

48
STORY DRIVEN WEB DEVELOPMENT

description

A presentation delivered to the open source developer conference in Sydney, December 2008

Transcript of Story Driven Web Development

Page 1: Story Driven Web Development

STORY DRIVENWEB DEVELOPMENT

Page 2: Story Driven Web Development

MICHAEL KOUKOULLISPROGRAMMER

Page 3: Story Driven Web Development
Page 4: Story Driven Web Development

DESIGNBUILDWEB APPLICATIONS

Page 5: Story Driven Web Development

STYLE OF DEVELOPMENTSET OF TOOLS

STORY DRIVEN DEVELOPMENTWE FIND USEFUL

Page 6: Story Driven Web Development

CODERUBYRAILSCUCUMBERHAPPY HAPPY SAD

Page 7: Story Driven Web Development

WHAT I REALLY WANT?WHY IT WORKS FOR US!

Page 8: Story Driven Web Development

EVOLVING METHODDELIVERING BETTER SOFTWARE

Page 9: Story Driven Web Development
Page 10: Story Driven Web Development

ELEGANCEENJOYABLE

STANDS ON ITS FEETCREATIVE

Page 11: Story Driven Web Development

FOCUS. PEOPLE. TOOLS.

Page 12: Story Driven Web Development

ON WITH THE SHOWSTORY DRIVEN DEVELOPMENT

Page 13: Story Driven Web Development

EXAMPLE. FEATURE.

Feature: Article tags In order to work with article tags As a site user I want to both create and delete tags

Page 14: Story Driven Web Development

EXAMPLE. FEATURE.

Scenario: Creating a tag Given an article exists with no tags When I submit a new tag for the article Then the article should have one tag And I am redirected to the article

Page 15: Story Driven Web Development

EXAMPLE. FEATURE.

Scenario: Creating a tag Given an article exists with no tags When I submit a new tag for the article Then the article should have one tag And I am redirected to the article Scenario: Deleting a tag Given an article exists with one tag When I delete the article tag Then the article should have no tags And I am redirected to the article

Page 16: Story Driven Web Development

Feature: Article tags In order to work with article tags As a site user I want to both create and delete tags

Scenario: Creating a tag Given an article exists with no tags When I submit a new tag for the article Then the article should have one tag And I am redirected to the article Scenario: Deleting a tag Given an article exists with one tag When I delete the article tag Then the article should have no tags And I am redirected to the article

EXAMPLE. FEATURE.

Page 17: Story Driven Web Development

DECLARATION OF INTENTIONNATURAL LANGUAGEIMMENSELY POWERFUL

Page 18: Story Driven Web Development

BEST THING YOU CAN DO AS A PROGRAMMER?CODE LESS.

Page 19: Story Driven Web Development

Feature: Article tags In order to work with article tags As a site user I want to both create and delete tags

Scenario: Creating a tag Given an article exists with no tags When I submit a new tag for the article Then the article should have one tag And I am redirected to the article Scenario: Deleting a tag Given an article exists with one tag When I delete the article tag Then the article should have no tags And I am redirected to the article

EXAMPLE. FEATURE.

Page 20: Story Driven Web Development

WRITE PROSE

ITS EXECUTABLE!

AVOID GETTING PROGRAMMATICMAKE IT A ‘REAL’ STORY

Page 21: Story Driven Web Development

WORKFLOWRUNNING THE STORY

Page 22: Story Driven Web Development

FEATURE. RUNNER.

Page 23: Story Driven Web Development

DEFINING. STEPS.

Page 24: Story Driven Web Development

DEFINING. MODELS.

Page 25: Story Driven Web Development

DEFINING. MODELS.class Article < ActiveRecord::Base has_many :taggings, :dependent => :destroy has_many :tags, :through => :taggings

def add_tag(value) new_tag = Tag.find_or_create_by_name(value) unless Tagging.exists?(:article_id => self.id, :tag_id => new_tag) taggings.create(:tag => new_tag) end endend

Page 26: Story Driven Web Development

DEFINING. MODELS.class Article < ActiveRecord::Base has_many :taggings, :dependent => :destroy has_many :tags, :through => :taggings

def add_tag(value) new_tag = Tag.find_or_create_by_name(value) unless Tagging.exists?(:article_id => self.id, :tag_id => new_tag) taggings.create(:tag => new_tag) end endend

class Tagging < ActiveRecord::Base belongs_to :tag belongs_to :articleend

Page 27: Story Driven Web Development

DEFINING. MODELS.class Article < ActiveRecord::Base has_many :taggings, :dependent => :destroy has_many :tags, :through => :taggings

def add_tag(value) new_tag = Tag.find_or_create_by_name(value) unless Tagging.exists?(:article_id => self.id, :tag_id => new_tag) taggings.create(:tag => new_tag) end endend

class Tagging < ActiveRecord::Base belongs_to :tag belongs_to :articleend

class Tag < ActiveRecord::Base has_many :taggingsend

Page 28: Story Driven Web Development

RERUNNING. FEATURE.

Page 29: Story Driven Web Development

DEFINING. ROUTES.

ActionController::Routing::Routes.draw do |map| map.home "", :controller => "pages", :action => "home" map.resources :articles do |article| article.resources :taggings endend

Page 30: Story Driven Web Development

RERUNNING. FEATURE.

Page 31: Story Driven Web Development

DEFINING. CONTROLERS.

class TaggingsController < ApplicationController def create article = Article.find(params[:article_id]) article.add_tag(params[:tags]) redirect_to article_path(article) end def destroy article = Article.find(params[:article_id]) tagging = article.taggings.find(params[:id]) tagging.destroy redirect_to article_path(article) endend

Page 32: Story Driven Web Development

RERUNNING. FEATURE. SUCCESS!

Page 33: Story Driven Web Development

JUST IN TIMEAPP DEVWORKFLOW

Page 34: Story Driven Web Development

SHARED STEPSREGEXDRY IT UP

Page 35: Story Driven Web Development

DRY IT UP. REGEX MATCHING.

Given /^an article exists with no tags$/ do @article = Article.create!(:title => "Beautiful Evidence")end

Given /^an article exists with one tag$/ do @article = Article.create!(:title => "Beautiful Evidence") @tag = Tag.create!(:name => "visualisation") @tagging = @article.taggings.create!(:tag => @tag)end

Page 36: Story Driven Web Development

DRY IT UP. REGEX MATCHING.

Given /^an article exists with no tags$/ do @article = Article.create!(:title => "Beautiful Evidence")end

Given /^an article exists with one tag$/ do @article = Article.create!(:title => "Beautiful Evidence") @tag = Tag.create!(:name => "visualisation") @tagging = @article.taggings.create!(:tag => @tag)end

Given /^an article exists with (\d+) tags$/ do |num| @article = Article.create!(:title => "Beautiful Evidence") num.to_i.times do |num| @tag = Tag.create!(:name => "random-tag-#{num}") @tagging = @article.taggings.create!(:tag => @tag) endend

Page 37: Story Driven Web Development

DRY IT UP. REGEX MATCHING.

Then /^the article should have one tag$/ do @article.taggings.length.should == 1end

Then /^the article should have no tags$/ do @article.taggings.length.should == 0end

Page 38: Story Driven Web Development

DRY IT UP. REGEX MATCHING.

Then /^the article should have one tag$/ do @article.taggings.length.should == 1end

Then /^the article should have no tags$/ do @article.taggings.length.should == 0end

Then /^the article should have (\d+) tags$/ do |num| @article.taggings.length.should == num.to_iend

Page 39: Story Driven Web Development

DRY IT UP. REGEX MATCHING.Feature: Article tags In order to work with article tags As a site user I want to both create and delete tags

Scenario: Creating a tag Given an article exists with no tags When I submit a new tag for the article Then the article should have one tag And I am redirected to the article Scenario: Deleting a tag Given an article exists with one tag When I delete the article tag Then the article should have no tags And I am redirected to the article

Page 40: Story Driven Web Development

DRY IT UP. REGEX MATCHING.

Given an article exists with 0 tags

Given an article exists with 1 tags

Then the article should have 0 tags

Then the article should have 1 tags

Page 41: Story Driven Web Development

WHAT ABOUT VIEWS?RESPONSE.SHOULDWEBRAT

Page 42: Story Driven Web Development

VIEWS. RESPONSE.SHOULD

Feature: Viewing an article In order to read an article As a site user I want access the article Scenario: Viewing an article Given an article exists with 1 tags When I view the article Then I should see the page And I should see the article title And I should see the article tag

Page 43: Story Driven Web Development

VIEWS. RESPONSE.SHOULDWhen /^I view the article$/ do get article_path(@article)end

Then /^I should see the page$/ do response.should be_successend

Then /^I should see the article title$/ do response.should include_text(@article.title)end

Then /^I should see the article tag$/ do response.should include_text(@tag.name)end

Page 44: Story Driven Web Development

VIEWS. WEBRATScenario: Submitting the add tag form Given an article exists with 0 tags When I visit the article page And I submit the tag form with 'edward' Then I am redirected to the article And the article should have 1 tags And the article should be tagged with 'edward'

Page 45: Story Driven Web Development

VIEWS. WEBRATScenario: Submitting the add tag form Given an article exists with 0 tags When I visit the article page And I submit the tag form with 'edward' Then I am redirected to the article And the article should have 1 tags And the article should be tagged with 'edward'

When /^I visit the article page$/ do visit article_path(@article)end

When /^I submit the tag form with '(\w+)'$/ do |value| fill_in "tags", :with => value click_button "submit"end

Then /^the article should be tagged with '(\w+)'$/ do |value| @article.tags.map(&:name).include?(value).should be_trueend

Page 46: Story Driven Web Development

STORY DRIVEN DEVELOPMENTNATURAL LANGUAGE SPECSELEGANTCHANCE TO CODE LESSENJOYABLE

Page 47: Story Driven Web Development

YOUTHANK

Page 48: Story Driven Web Development

MICHAEL KOUKOULLIStwitter: koukyemail : [email protected]