STORY DRIVEN
WEB DEVELOPMENT
MICHAEL KOUKOULLIS
PROGRAMMER
DESIGN
BUILD
WEB APPLICATIONS
STYLE OF DEVELOPMENT
SET OF TOOLS
WE FIND USEFUL
STORY DRIVEN DEVELOPMENT
CODE
RUBY
RAILS
CUCUMBER
HAPPY HAPPY SAD
WHAT I REALLY WANT?
WHY IT WORKS FOR US!
EVOLVING METHOD
DELIVERING BETTER SOFTWARE
ELEGANCE
ENJOYABLE
CREATIVE
STANDS ON ITS FEET
FOCUS. PEOPLE. TOOLS.
ON WITH THE SHOW
STORY DRIVEN DEVELOPMENT
EXAMPLE. FEATURE.
 Feature: Article tags
   In order to work with article tags
   As a site user
   I want to both create ...
EXAMPLE. FEATURE.


  Scenario: Creating a tag
    Given an article exists with no tags
    When I submit a new tag for th...
EXAMPLE. FEATURE.


  Scenario: Creating a tag
    Given an article exists with no tags
    When I submit a new tag for th...
EXAMPLE. FEATURE.
 Feature: Article tags
   In order to work with article tags
   As a site user
   I want to both create ...
DECLARATION OF INTENTION
NATURAL LANGUAGE
IMMENSELY POWERFUL
BEST THING YOU CAN DO AS A
PROGRAMMER?
CODE LESS.
EXAMPLE. FEATURE.
 Feature: Article tags
   In order to work with article tags
   As a site user
   I want to both create ...
WRITE PROSE
AVOID GETTING PROGRAMMATIC
MAKE IT A ‘REAL’ STORY
ITS EXECUTABLE!
WORKFLOW
RUNNING THE STORY
FEATURE. RUNNER.
DEFINING. STEPS.
DEFINING. MODELS.
DEFINING. MODELS.
class Article < ActiveRecord::Base
  has_many :taggings, :dependent => :destroy
  has_many :tags, :throu...
DEFINING. MODELS.
class Article < ActiveRecord::Base
  has_many :taggings, :dependent => :destroy
  has_many :tags, :throu...
DEFINING. MODELS.
class Article < ActiveRecord::Base
  has_many :taggings, :dependent => :destroy
  has_many :tags, :throu...
RERUNNING. FEATURE.
DEFINING. ROUTES.
ActionController::Routing::Routes.draw do |map|
  map.home quot;quot;, :controller => quot;pagesquot;, :...
RERUNNING. FEATURE.
DEFINING. CONTROLERS.
class TaggingsController < ApplicationController
  def create
    article = Article.find(params[:art...
RERUNNING. FEATURE. SUCCESS!
JUST IN TIME
APP DEV
WORKFLOW
SHARED STEPS
REGEX
DRY IT UP
DRY IT UP. REGEX MATCHING.
Given /^an article exists with no tags$/ do
  @article = Article.create!(:title => quot;Beautif...
DRY IT UP. REGEX MATCHING.
Given /^an article exists with no tags$/ do
  @article = Article.create!(:title => quot;Beautif...
DRY IT UP. REGEX MATCHING.
Then /^the article should have one tag$/ do
  @article.taggings.length.should == 1
end

Then /^...
DRY IT UP. REGEX MATCHING.
Then /^the article should have one tag$/ do
  @article.taggings.length.should == 1
end

Then /^...
DRY IT UP. REGEX MATCHING.
Feature: Article tags
  In order to work with article tags
  As a site user
  I want to both cr...
DRY IT UP. REGEX MATCHING.


  Given an article exists with 0 tags

  Then the article should have 1 tags




  Given an a...
WHAT ABOUT VIEWS?
RESPONSE.SHOULD
WEBRAT
VIEWS. RESPONSE.SHOULD
Feature: Viewing an article
  In order to read an article
  As a site user
  I want access the arti...
VIEWS. RESPONSE.SHOULD
When /^I view the article$/ do
  get article_path(@article)
end

Then /^I should see the page$/ do
...
VIEWS. WEBRAT
Scenario: Submitting the add tag form
  Given an article exists with 0 tags
  When I visit the article page
...
VIEWS. WEBRAT
Scenario: Submitting the add tag form
  Given an article exists with 0 tags
  When I visit the article page
...
STORY DRIVEN DEVELOPMENT
NATURAL LANGUAGE SPECS
ELEGANT
CHANCE TO CODE LESS
ENJOYABLE
THANK
YOU
MICHAEL KOUKOULLIS
twitter: kouky
email : m@agencyrainford.com
Story Driven Web Development
Story Driven Web Development
Próxima SlideShare
Cargando en…5
×

Story Driven Web Development

17.125 visualizaciones

Publicado el

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

Publicado en: Tecnología, Educación

Story Driven Web Development

  1. STORY DRIVEN WEB DEVELOPMENT
  2. MICHAEL KOUKOULLIS PROGRAMMER
  3. DESIGN BUILD WEB APPLICATIONS
  4. STYLE OF DEVELOPMENT SET OF TOOLS WE FIND USEFUL STORY DRIVEN DEVELOPMENT
  5. CODE RUBY RAILS CUCUMBER HAPPY HAPPY SAD
  6. WHAT I REALLY WANT? WHY IT WORKS FOR US!
  7. EVOLVING METHOD DELIVERING BETTER SOFTWARE
  8. ELEGANCE ENJOYABLE CREATIVE STANDS ON ITS FEET
  9. FOCUS. PEOPLE. TOOLS.
  10. ON WITH THE SHOW STORY DRIVEN DEVELOPMENT
  11. EXAMPLE. FEATURE. Feature: Article tags In order to work with article tags As a site user I want to both create and delete tags
  12. 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
  13. 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
  14. EXAMPLE. FEATURE. 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
  15. DECLARATION OF INTENTION NATURAL LANGUAGE IMMENSELY POWERFUL
  16. BEST THING YOU CAN DO AS A PROGRAMMER? CODE LESS.
  17. EXAMPLE. FEATURE. 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
  18. WRITE PROSE AVOID GETTING PROGRAMMATIC MAKE IT A ‘REAL’ STORY ITS EXECUTABLE!
  19. WORKFLOW RUNNING THE STORY
  20. FEATURE. RUNNER.
  21. DEFINING. STEPS.
  22. DEFINING. MODELS.
  23. 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 end end
  24. 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 end end class Tagging < ActiveRecord::Base belongs_to :tag belongs_to :article end
  25. 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 end end class Tagging < ActiveRecord::Base belongs_to :tag belongs_to :article end class Tag < ActiveRecord::Base has_many :taggings end
  26. RERUNNING. FEATURE.
  27. DEFINING. ROUTES. ActionController::Routing::Routes.draw do |map| map.home quot;quot;, :controller => quot;pagesquot;, :action => quot;homequot; map.resources :articles do |article| article.resources :taggings end end
  28. RERUNNING. FEATURE.
  29. 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) end end
  30. RERUNNING. FEATURE. SUCCESS!
  31. JUST IN TIME APP DEV WORKFLOW
  32. SHARED STEPS REGEX DRY IT UP
  33. DRY IT UP. REGEX MATCHING. Given /^an article exists with no tags$/ do @article = Article.create!(:title => quot;Beautiful Evidencequot;) end Given /^an article exists with one tag$/ do @article = Article.create!(:title => quot;Beautiful Evidencequot;) @tag = Tag.create!(:name => quot;visualisationquot;) @tagging = @article.taggings.create!(:tag => @tag) end
  34. DRY IT UP. REGEX MATCHING. Given /^an article exists with no tags$/ do @article = Article.create!(:title => quot;Beautiful Evidencequot;) end Given /^an article exists with one tag$/ do @article = Article.create!(:title => quot;Beautiful Evidencequot;) @tag = Tag.create!(:name => quot;visualisationquot;) @tagging = @article.taggings.create!(:tag => @tag) end Given /^an article exists with (d+) tags$/ do |num| @article = Article.create!(:title => quot;Beautiful Evidencequot;) num.to_i.times do |num| @tag = Tag.create!(:name => quot;random-tag-#{num}quot;) @tagging = @article.taggings.create!(:tag => @tag) end end
  35. DRY IT UP. REGEX MATCHING. Then /^the article should have one tag$/ do @article.taggings.length.should == 1 end Then /^the article should have no tags$/ do @article.taggings.length.should == 0 end
  36. DRY IT UP. REGEX MATCHING. Then /^the article should have one tag$/ do @article.taggings.length.should == 1 end Then /^the article should have no tags$/ do @article.taggings.length.should == 0 end Then /^the article should have (d+) tags$/ do |num| @article.taggings.length.should == num.to_i end
  37. 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
  38. DRY IT UP. REGEX MATCHING. Given an article exists with 0 tags Then the article should have 1 tags Given an article exists with 1 tags Then the article should have 0 tags
  39. WHAT ABOUT VIEWS? RESPONSE.SHOULD WEBRAT
  40. 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
  41. VIEWS. RESPONSE.SHOULD When /^I view the article$/ do get article_path(@article) end Then /^I should see the page$/ do response.should be_success end 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
  42. VIEWS. WEBRAT Scenario: 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'
  43. VIEWS. WEBRAT Scenario: 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 quot;tagsquot;, :with => value click_button quot;submitquot; end Then /^the article should be tagged with '(w+)'$/ do |value| @article.tags.map(&:name).include?(value).should be_true end
  44. STORY DRIVEN DEVELOPMENT NATURAL LANGUAGE SPECS ELEGANT CHANCE TO CODE LESS ENJOYABLE
  45. THANK YOU
  46. MICHAEL KOUKOULLIS twitter: kouky email : m@agencyrainford.com

×