Refactoring Katas   Danilo Sato - @dtsato      ThoughtWorks     www.dtsato.com
Kata?
Kata?
Kata?• Exercícios para praticar• Melhorar habilidades específicas: •   TDD •   Algoritmos •   Design •   Código Ruim? •   ...
Kata?TestTestTestTest
Kata?TestTestTestTest
Kata?TestTestTestTest
Kata?TestTestTestTest
RefatoraçãoTest
RefatoraçãoTest             Code
RefatoraçãoTest             Code
Refatoração                 CodeTest
Refatoração                 CodeTest
Refatoração                 CodeTest
Refatoração                 CodeTest
Refatoração                 CodeTest
Refatoração                 CodeTest
Refatoração                 CodeTest
Refatoração                    CodeTest                Remover duplicação
Outros tipos...                CodeTest
Outros tipos...              Code   CodeTest
Outros tipos...                  Code   CodeTest    Test
Outros tipos...                  Code        CodeTest    Test                      Se paração de                    respon...
Outros tipos...                CodeTest
Outros tipos...Test            Code
Outros tipos...Test            Code
Outros tipos...Test             Code               Mudança no design
Ainda mais
A idéia
A idéia
A idéia          ?
A idéia?             ?
A idéia    ?             ??
#comofas1. Criticar código2. Analisar a solução final3. Planejar os passos4. Mão na massa!
def index(params)  scope = Event  case params[:timeframe]  when tomorrow    scope = scope.between_day(DateTime.now + 1)  w...
def index(params)  scope = Event                      switch/case  case params[:timeframe]  when tomorrow    scope = scope...
def index(params)  scope = Event  case params[:timeframe]  when tomorrow    scope = scope.between_day(DateTime.now + 1)  w...
def index(params)  scope = Event  case params[:timeframe]  when tomorrow    scope = scope.between_day(DateTime.now + 1)  w...
class Event < ActiveRecord::Base  named_scope :between_dates, lambda { |start_date, end_date|    {:conditions => ["at >= ?...
jeitos diferentes de                                                  fazer a mesmaclass Event < ActiveRecord::Base       ...
class Event < ActiveRecord::Base  named_scope :between_dates, lambda { |start_date, end_date|    {:conditions => ["at >= ?...
Plano1. Centralizar lógica de manipulação de datas2. Unificar named scopes3. Extrair lógica do Controller4. Quebrar lógica ...
def index(params)  case params[:timeframe]  when tomorrow    date = DateTime.now + 1    start_date = date.at_beginning_of_...
class Event < ActiveRecord::Base  named_scope :between_dates, lambda { |start_date, end_date|    {:conditions => {:at => s...
class Event < ActiveRecord::Base  named_scope :between_dates, lambda { |start_date, end_date|    {:conditions => {:at => s...
Antes              . ............                             ds              0 .49367 secon Finished in           res 13 ...
Antes                                          Depois                                                   .......           ...
class CalendarSearchController  attr_reader :events  def index(params)    timeframe = TimeFrame.for(params[:timeframe], pa...
class TimeFrame < Struct.new(:start_date, :end_date)  def self.for(type, start_date, end_date, hour)    case type    when ...
describe TimeFrame do  before do    @today = DateTime.strptime(06/01/2011, %m/%d/%Y)    DateTime.stub!(:now).and_return(@t...
describe TimeFrame do  before do    @today = DateTime.strptime(06/01/2011, %m/%d/%Y)    DateTime.stub!(:now).and_return(@t...
Antes .......                             dsdescribe d in 0 .25355 secon Finishe TimeFrame do es  before les, 0 failur  7 ...
Antes                                          Depois                                                 ........ .......    ...
class TimeFrame  attr_reader :start_date, :end_date  class Today < TimeFrame    def initialize      date = DateTime.now   ...
class TimeFrame  ...  def self.for(type, start_date, end_date, hour)    case type    when tomorrow then Tomorrow.new    wh...
class TimeFrame  ...  def self.for(type, start_date, end_date, hour)    case type    when tomorrow then Tomorrow.new    wh...
class TimeFrame  ...          Antes .def .self.for(type, start_date, end_date, hour)   ... ...     case type              ...
class TimeFrame  ...         Antes                                      Depois                                            ...
Obrigado!Danilo Sato - @dtsato   ThoughtWorks  www.dtsato.com
sato/kata-refac toring-calendarhttp: //github.com/dt                Obrigado!                 Danilo Sato - @dtsato       ...
Upcoming SlideShare
Loading in...5
×

Refactoring Katas - AgileBrazil 2011

1,535

Published on

Slides from my Lightning Talk at AgileBrazil 2011 in Fortaleza about refactoring katas. Check the code on Github at: http://github.com/dtsato/kata-refactoring-calendar

0 Comments
5 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,535
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
0
Comments
0
Likes
5
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Transcript of "Refactoring Katas - AgileBrazil 2011"

    1. 1. Refactoring Katas Danilo Sato - @dtsato ThoughtWorks www.dtsato.com
    2. 2. Kata?
    3. 3. Kata?
    4. 4. Kata?• Exercícios para praticar• Melhorar habilidades específicas: • TDD • Algoritmos • Design • Código Ruim? • ...
    5. 5. Kata?TestTestTestTest
    6. 6. Kata?TestTestTestTest
    7. 7. Kata?TestTestTestTest
    8. 8. Kata?TestTestTestTest
    9. 9. RefatoraçãoTest
    10. 10. RefatoraçãoTest Code
    11. 11. RefatoraçãoTest Code
    12. 12. Refatoração CodeTest
    13. 13. Refatoração CodeTest
    14. 14. Refatoração CodeTest
    15. 15. Refatoração CodeTest
    16. 16. Refatoração CodeTest
    17. 17. Refatoração CodeTest
    18. 18. Refatoração CodeTest
    19. 19. Refatoração CodeTest Remover duplicação
    20. 20. Outros tipos... CodeTest
    21. 21. Outros tipos... Code CodeTest
    22. 22. Outros tipos... Code CodeTest Test
    23. 23. Outros tipos... Code CodeTest Test Se paração de responsa bilidades
    24. 24. Outros tipos... CodeTest
    25. 25. Outros tipos...Test Code
    26. 26. Outros tipos...Test Code
    27. 27. Outros tipos...Test Code Mudança no design
    28. 28. Ainda mais
    29. 29. A idéia
    30. 30. A idéia
    31. 31. A idéia ?
    32. 32. A idéia? ?
    33. 33. A idéia ? ??
    34. 34. #comofas1. Criticar código2. Analisar a solução final3. Planejar os passos4. Mão na massa!
    35. 35. def index(params) scope = Event case params[:timeframe] when tomorrow scope = scope.between_day(DateTime.now + 1) when this_week scope = scope.between_dates(DateTime.now, ( DateTime.now + 6 ).end_of_day) when custom if params[:start_date].blank? params[:start_date] = DateTime.now.beginning_of_week.strftime(%m/%d/%Y) end if params[:end_date].blank? params[:end_date] = (DateTime.now.end_of_week - 2).strftime(%m/%d/%Y) end scope = scope.between_dates(DateTime.strptime(params[:start_date], %m/%d/%Y),DateTime.strptime(params[:end_date], %m/%d/%Y).end_of_day) when hour scope = scope.between_hour_on_day(DateTime.strptime(params[:hour], %m/%d/%Y %H:%M)) when today scope = scope.between_day(DateTime.now) end @events = scope.allend
    36. 36. def index(params) scope = Event switch/case case params[:timeframe] when tomorrow scope = scope.between_day(DateTime.now + 1) when this_week scope = scope.between_dates(DateTime.now, ( DateTime.now + 6 ).end_of_day) when custom if params[:start_date].blank? params[:start_date] = DateTime.now.beginning_of_week.strftime(%m/%d/%Y) end if params[:end_date].blank? params[:end_date] = (DateTime.now.end_of_week - 2).strftime(%m/%d/%Y) end scope = scope.between_dates(DateTime.strptime(params[:start_date], %m/%d/%Y),DateTime.strptime(params[:end_date], %m/%d/%Y).end_of_day) when hour scope = scope.between_hour_on_day(DateTime.strptime(params[:hour], %m/%d/%Y %H:%M)) when today scope = scope.between_day(DateTime.now) end @events = scope.allend
    37. 37. def index(params) scope = Event case params[:timeframe] when tomorrow scope = scope.between_day(DateTime.now + 1) when this_week string parse scope = scope.between_dates(DateTime.now, ( DateTime.now + 6 ).end_of_day) when custom if params[:start_date].blank? params[:start_date] = DateTime.now.beginning_of_week.strftime(%m/%d/%Y) end if params[:end_date].blank? params[:end_date] = (DateTime.now.end_of_week - 2).strftime(%m/%d/%Y) end scope = scope.between_dates(DateTime.strptime(params[:start_date], %m/%d/%Y),DateTime.strptime(params[:end_date], %m/%d/%Y).end_of_day) when hour scope = scope.between_hour_on_day(DateTime.strptime(params[:hour], %m/%d/%Y %H:%M)) when today scope = scope.between_day(DateTime.now) end @events = scope.allend
    38. 38. def index(params) scope = Event case params[:timeframe] when tomorrow scope = scope.between_day(DateTime.now + 1) when this_week scope = scope.between_dates(DateTime.now, ( DateTime.now + 6 ).end_of_day) when custom if params[:start_date].blank? params[:start_date] = DateTime.now.beginning_of_week.strftime(%m/%d/%Y) end if params[:end_date].blank? params[:end_date] = (DateTime.now.end_of_week - 2).strftime(%m/%d/%Y) end scope = scope.between_dates(DateTime.strptime(params[:start_date], %m/%d/%Y),DateTime.strptime(params[:end_date], %m/%d/%Y).end_of_day) when hour scope = scope.between_hour_on_day(DateTime.strptime(params[:hour], %m/%d/%Y %H:%M)) when today scope = scope.between_day(DateTime.now) end escopos diferentes @events = scope.allend
    39. 39. class Event < ActiveRecord::Base named_scope :between_dates, lambda { |start_date, end_date| {:conditions => ["at >= ? AND at <= ?", start_date, end_date ] } } named_scope :between_hour_on_day, lambda { |start_hour| end_date = start_hour + 1.hour-1.second { :conditions => {:at => start_hour..end_date} } } named_scope :between_day, lambda { |date| start_date = date.at_beginning_of_day end_date = start_date.end_of_day { :conditions => {:at => start_date..end_date} } }end
    40. 40. jeitos diferentes de fazer a mesmaclass Event < ActiveRecord::Base coisa named_scope :between_dates, lambda { |start_date, end_date| {:conditions => ["at >= ? AND at <= ?", start_date, end_date ] } } named_scope :between_hour_on_day, lambda { |start_hour| end_date = start_hour + 1.hour-1.second { :conditions => {:at => start_hour..end_date} } } named_scope :between_day, lambda { |date| start_date = date.at_beginning_of_day end_date = start_date.end_of_day { :conditions => {:at => start_date..end_date} } }end
    41. 41. class Event < ActiveRecord::Base named_scope :between_dates, lambda { |start_date, end_date| {:conditions => ["at >= ? AND at <= ?", start_date, end_date ] } } named_scope :between_hour_on_day, lambda { |start_hour| end_date = start_hour + 1.hour-1.second { :conditions => {:at => start_hour..end_date} } } mais lógica named_scope :between_day, lambda { |date| start_date = date.at_beginning_of_day end_date = start_date.end_of_day { :conditions => {:at => start_date..end_date} } }end
    42. 42. Plano1. Centralizar lógica de manipulação de datas2. Unificar named scopes3. Extrair lógica do Controller4. Quebrar lógica de timeframes diferentes
    43. 43. def index(params) case params[:timeframe] when tomorrow date = DateTime.now + 1 start_date = date.at_beginning_of_day end_date = start_date.end_of_day when this_week start_date = DateTime.now end_date = (DateTime.now + 6 ).end_of_day when custom start_date = params[:start_date].blank? ? DateTime.now.beginning_of_week :DateTime.strptime(params[:start_date], %m/%d/%Y) end_date = params[:end_date].blank? ? (DateTime.now.end_of_week - 2) :DateTime.strptime(params[:end_date], %m/%d/%Y).end_of_day when hour start_date = DateTime.strptime(params[:hour], %m/%d/%Y %H:%M) end_date = start_date + 1.hour-1.second when today date = DateTime.now start_date = date.at_beginning_of_day end_date = start_date.end_of_day end @events = Event.between_dates(start_date, end_date)end
    44. 44. class Event < ActiveRecord::Base named_scope :between_dates, lambda { |start_date, end_date| {:conditions => {:at => start_date..end_date}} }end
    45. 45. class Event < ActiveRecord::Base named_scope :between_dates, lambda { |start_date, end_date| {:conditions => {:at => start_date..end_date}} }end lib/calendar_search_controller.rb | 27 +++++++++++++-------------- lib/event.rb | 13 +------------ spec/event_spec.rb | 37 ------------------------------------- 3 files changed, 14 insertions(+), 63 deletions(-)
    46. 46. Antes . ............ ds 0 .49367 secon Finished in res 13 examp les, 0 failuclass Event < ActiveRecord::Base named_scope :between_dates, lambda { |start_date, end_date| {:conditions => {:at => start_date..end_date}} }end lib/calendar_search_controller.rb | 27 +++++++++++++-------------- lib/event.rb | 13 +------------ spec/event_spec.rb | 37 ------------------------------------- 3 files changed, 14 insertions(+), 63 deletions(-)
    47. 47. Antes Depois ....... . ............ ds Finished in 0 .49367 secon 0.25355 seco Finished in res 7 examples, nds 13 examp les, 0 failu 0 failuresclass Event < ActiveRecord::Base named_scope :between_dates, lambda { |start_date, end_date| {:conditions => {:at => start_date..end_date}} }end lib/calendar_search_controller.rb | 27 +++++++++++++-------------- lib/event.rb | 13 +------------ spec/event_spec.rb | 37 ------------------------------------- 3 files changed, 14 insertions(+), 63 deletions(-)
    48. 48. class CalendarSearchController attr_reader :events def index(params) timeframe = TimeFrame.for(params[:timeframe], params[:start_date],params[:end_date], params[:hour]) @events = Event.between_dates(timeframe.start_date, timeframe.end_date) endend mudança nos testes:it "should create time frame from params and retrieve events" do timeframe = TimeFrame.new(DateTime.now, DateTime.now) TimeFrame.should_receive(:for).with(today, start, end,hour).and_return(timeframe) events = [Event.new, Event.new] Event.should_receive(:between_dates).with(timeframe.start_date,timeframe.end_date).and_return(events) @controller.index(:timeframe => today, :start_date => start, :end_date =>end, :hour => hour) @controller.events.should == eventsend
    49. 49. class TimeFrame < Struct.new(:start_date, :end_date) def self.for(type, start_date, end_date, hour) case type when tomorrow date = DateTime.now + 1 TimeFrame.new(date.at_beginning_of_day, date.end_of_day) when this_week TimeFrame.new(DateTime.now, (DateTime.now + 6 ).end_of_day) when custom start_date = start_date.blank? ? DateTime.now.beginning_of_week :DateTime.strptime(start_date, %m/%d/%Y) end_date = end_date.blank? ? (DateTime.now.end_of_week - 2) :DateTime.strptime(end_date, %m/%d/%Y).end_of_day TimeFrame.new(start_date, end_date) when hour start_date = DateTime.strptime(hour, %m/%d/%Y %H:%M) end_date = start_date + 1.hour-1.second TimeFrame.new(start_date, end_date) when today date = DateTime.now TimeFrame.new(date.at_beginning_of_day, date.end_of_day) end endend
    50. 50. describe TimeFrame do before do @today = DateTime.strptime(06/01/2011, %m/%d/%Y) DateTime.stub!(:now).and_return(@today) end describe "todays event" do it "should use beginning and end of day" do timeframe = TimeFrame.for(today, nil, nil, nil) timeframe.start_date.should == @today.at_beginning_of_day timeframe.end_date.should == @today.end_of_day end end ...end
    51. 51. describe TimeFrame do before do @today = DateTime.strptime(06/01/2011, %m/%d/%Y) DateTime.stub!(:now).and_return(@today) end describe "todays event" do it "should use beginning and end of day" do timeframe = TimeFrame.for(today, nil, nil, nil) timeframe.start_date.should == @today.at_beginning_of_day timeframe.end_date.should == @today.end_of_day end Rakefile | 4 ++ end lib/calendar_search_controller.rb | 24 +--------- ... lib/time_frame.rb | 24 ++++++++++end spec/acceptance_tests.rb | 75 +++++++++++++++++++++++++++++++ spec/calendar_search_controller_spec.rb | 75 ++++--------------------------- spec/time_frame_spec.rb | 63 ++++++++++++++++++++++++++ 6 files changed, 178 insertions(+), 87 deletions(-)
    52. 52. Antes ....... dsdescribe d in 0 .25355 secon Finishe TimeFrame do es before les, 0 failur 7 examp do @today = DateTime.strptime(06/01/2011, %m/%d/%Y) DateTime.stub!(:now).and_return(@today) end describe "todays event" do it "should use beginning and end of day" do timeframe = TimeFrame.for(today, nil, nil, nil) timeframe.start_date.should == @today.at_beginning_of_day timeframe.end_date.should == @today.end_of_day end Rakefile | 4 ++ end lib/calendar_search_controller.rb | 24 +--------- ... lib/time_frame.rb | 24 ++++++++++end spec/acceptance_tests.rb | 75 +++++++++++++++++++++++++++++++ spec/calendar_search_controller_spec.rb | 75 ++++--------------------------- spec/time_frame_spec.rb | 63 ++++++++++++++++++++++++++ 6 files changed, 178 insertions(+), 87 deletions(-)
    53. 53. Antes Depois ........ ....... ds Finished indescribe d in 0 .25355 secon she TimeFrame do 0.17938 seco nds Fini 8 examples, before les, 0 failures 7 ex amp do 0 failures @today = DateTime.strptime(06/01/2011, %m/%d/%Y) DateTime.stub!(:now).and_return(@today) end describe "todays event" do it "should use beginning and end of day" do timeframe = TimeFrame.for(today, nil, nil, nil) timeframe.start_date.should == @today.at_beginning_of_day timeframe.end_date.should == @today.end_of_day end Rakefile | 4 ++ end lib/calendar_search_controller.rb | 24 +--------- ... lib/time_frame.rb | 24 ++++++++++end spec/acceptance_tests.rb | 75 +++++++++++++++++++++++++++++++ spec/calendar_search_controller_spec.rb | 75 ++++--------------------------- spec/time_frame_spec.rb | 63 ++++++++++++++++++++++++++ 6 files changed, 178 insertions(+), 87 deletions(-)
    54. 54. class TimeFrame attr_reader :start_date, :end_date class Today < TimeFrame def initialize date = DateTime.now @start_date, @end_date = date.at_beginning_of_day, date.end_of_day end end ...enddescribe TimeFrame::Today do it "should use beginning and end of day" do timeframe = TimeFrame::Today.new timeframe.start_date.should == @today.at_beginning_of_day timeframe.end_date.should == @today.end_of_day end ...end
    55. 55. class TimeFrame ... def self.for(type, start_date, end_date, hour) case type when tomorrow then Tomorrow.new when this_week then ThisWeek.new when custom then Custom.new(start_date, end_date) when hour then Hour.new(hour) when today then Today.new end endenddescribe TimeFrame::Today do ... describe "parsing" do it "should parse todays timeframe" do TimeFrame.for(today, nil, nil, nil).shouldbe_an_instance_of(TimeFrame::Today) end ... endend
    56. 56. class TimeFrame ... def self.for(type, start_date, end_date, hour) case type when tomorrow then Tomorrow.new when this_week then ThisWeek.new when custom then Custom.new(start_date, end_date) when hour then Hour.new(hour) when today then Today.new end endenddescribe TimeFrame::Today do ... describe "parsing" do lib/time_frame.rb | 59 +++++++++++++++++++++++++++++++++------------- it "should parse todays timeframe" do spec/time_frame_spec.rb | 44 ++++++++++++++++++++++++++-------- TimeFrame.for(today, nil, nil, nil).should 2 files changed, 75 insertions(+), 28 deletions(-)be_an_instance_of(TimeFrame::Today) end ... endend
    57. 57. class TimeFrame ... Antes .def .self.for(type, start_date, end_date, hour) ... ... case type ds 0 .17938 secon when tomorrow then Tomorrow.new Finished in when les, 0 failures ThisWeek.new 8 examp this_week then when custom then Custom.new(start_date, end_date) when hour then Hour.new(hour) when today then Today.new end endenddescribe TimeFrame::Today do ... describe "parsing" do lib/time_frame.rb | 59 +++++++++++++++++++++++++++++++++------------- it "should parse todays timeframe" do spec/time_frame_spec.rb | 44 ++++++++++++++++++++++++++-------- TimeFrame.for(today, nil, nil, nil).should 2 files changed, 75 insertions(+), 28 deletions(-)be_an_instance_of(TimeFrame::Today) end ... endend
    58. 58. class TimeFrame ... Antes Depois ............ def .self.for(type, start_date, end_date, hour) . .... ... case type ds Finished in when d in 0 .17938 secon she tomorrow then Tomorrow.new 0.19023 seco nds Fini 13 examples, when les, 0 failures ThisWeek.new 8 examp this_week then 0 failures when custom then Custom.new(start_date, end_date) when hour then Hour.new(hour) when today then Today.new end endenddescribe TimeFrame::Today do ... describe "parsing" do lib/time_frame.rb | 59 +++++++++++++++++++++++++++++++++------------- it "should parse todays timeframe" do spec/time_frame_spec.rb | 44 ++++++++++++++++++++++++++-------- TimeFrame.for(today, nil, nil, nil).should 2 files changed, 75 insertions(+), 28 deletions(-)be_an_instance_of(TimeFrame::Today) end ... endend
    59. 59. Obrigado!Danilo Sato - @dtsato ThoughtWorks www.dtsato.com
    60. 60. sato/kata-refac toring-calendarhttp: //github.com/dt Obrigado! Danilo Sato - @dtsato ThoughtWorks www.dtsato.com

    ×