SlideShare uma empresa Scribd logo
1 de 46
Baixar para ler offline
Refactoring Conditional
  Dispatcher with Command
(based on Refactoring to Patterns)

        Sreenivas Ananthakrishna
let’s start with an example...
http://www.flickr.com/photos/fastlanedaily/509830016/
http://www.flickr.com/photos/martineian/485029758/




                                                    The ATM!
so what can the ATM do?
so what can the ATM do?

➡   Display the login screen when card is inserted
so what can the ATM do?

➡   Display the login screen when card is inserted

➡   Authenticate the user
so what can the ATM do?

➡   Display the login screen when card is inserted

➡   Authenticate the user

➡   Allow
 authenticated user to withdraw $$$
ATM Overview
Services



                    Authentication

View     ATM
       Controller
                       Account
View
  ➡    renders the screen
Services
  ➡    authenticates the user
  ➡    transfer/ debit money from account
Controller
  ➡    handles requests from view
let’s focus on building the ATMController...
and in TDD fashion, the test come first!
describe quot;an instance of quot;, ATMController do
  it quot;should render login when card is insertedquot; do
    view = mock(View)
    view.should_receive(:render).
          with(:login, {:account_id => 1234})

    controller = ATMController.new view
    controller.handle :card_inserted, {:account_id => 1234}
  end
end
now, the implementation
class ATMController
  def initialize view
    @view = view
  end

  def handle event, params
      @view.render :login, {:account_id => params[:account_id]}
  end
end
second test
it quot;should raise error for unknown eventquot; do
  view = mock(View)
  view.should_not_receive(:render)

  controller = ATMController.new view
  lambda {controller.handle(:foo, {})}.
             should raise_error(RuntimeError,
                   quot;cannot handle event fooquot;)
end
implementation
class ATMController
  def initialize view
    @view = view
  end

  def handle event, params
    if event == :card_inserted
        @view.render :login, {:account_id => params[:account_id]}
    else
         raise quot;cannot handle event #{event}quot;
    end
  end
end
third test
it quot;should display withdraw menu when user has authenticatedquot; do
  view = mock(View)
  view.should_receive(:render).with(:withdraw_menu)

 authentication_service = mock(AuthenticationService)
 authentication_service.should_receive(:authenticate).
                        with(1234, 5678).
                        and_return(true)

  controller = ATMController.new view, authentication_service
  controller.handle :authenticate,
                     {:account_id => 1234, :pin => 5678}
end
implementation
class ATMController
  def initialize view, authentication_service
    @authentication_service = authentication_service
    @view = view
  end

  def handle event, params
     case event
       when :card_inserted
         @view.render :login, {:account_id => params[:account_id]}
       when :authenticate
         if @authentication_service.
                      authenticate(params[:account_id], params[:pin])
           @view.render :withdraw_menu
         end
       else
            raise quot;cannot handle event #{event}quot;
     end
  en
addition of new dependencies has broken
              other tests!
so let’s fix it!
it quot;should render login when card is insertedquot; do
    view = mock(View)
    view.should_receive(:render).with(:login, {:account_id =>
1234})

  authentication_service = mock(AuthenticationService)
      authentication_service.should_not_receive(:authenticate)


    controller = ATMController.new view , authentication_service
controller.handle :card_inserted, {:account_id => 1234}
  end
so, as the controller keeps handling new
                 events...
so, as the controller keeps handling new
                 events...

๏   handle method keeps getting bloated
so, as the controller keeps handling new
                 events...

๏   handle method keeps getting bloated
    ๏   which means higher complexity
so, as the controller keeps handling new
                 events...

๏   handle method keeps getting bloated
    ๏   which means higher complexity
๏   adding new events requires changing the
    controller implementation
so, as the controller keeps handling new
                 events...

๏   handle method keeps getting bloated
    ๏   which means higher complexity
๏   adding new events requires changing the
    controller implementation
๏   addition of new receivers also affects
    existing test cases
let’s see how we can simplify
by refactoring to the Command
refactoring mechanics
step 1: compose method
Before
def handle event, params
  case event
    when :card_inserted
      @view.render :login, {:account_id => params[:account_id]}
    when :authenticate
      if @authentication_service.
                   authenticate(params[:account_id], params[:pin])
        @view.render :withdraw_menu
      end
    else
         raise quot;cannot handle event #{event}quot;
  end
end
After
def handle event, params
    case event
      when :card_inserted
        handle_card_inserted params
      when :authenticate
        handle_authenticate params
      else
           raise quot;cannot handle event #{event}quot;
    end
  end
step 2: extract class
Before

def handle_authenticate params
    if @authentication_service.
                authenticate(params[:account_id], params[:pin])
      @view.render :withdraw_menu
    end
end
After

def handle_authenticate params
    action = AuthenticateAction.new @view, @authentication_service
    action.execute params
end
extract superclass
class Action
  def execute params
    raise quot;not implemented!quot;
  end
end



class AuthenticateAction < Action
  def initialize view, authentication_service
    @view = view
    @authentication_service = authentication_service
  end
  def execute params
    if @authentication_service.
                authenticate(params[:account_id], params[:pin])
      @view.render :withdraw_menu
    end
  end
end
configure the controller
  with map of actions
class ATMController
  def initialize map
    @actions = map
  end

  def handle event, params
      if @actions.include? event
        @actions[event].execute params
      else
           raise quot;cannot handle event #{event}quot;
    end
  end
end
now, even the tests are simpler!
describe quot;an instance of quot;, ATMController do
  it quot;should execute the action for the eventquot; do
      params = {'foo' => 'bar'}
      action = mock(Action)
      action.should_receive(:execute).with(params)

        controller = ATMController.new({:foo_event => action})
        controller.handle(:foo_event, params)
  end

  it quot;should raise error for unknown eventquot; do
    controller = ATMController.new({})
    lambda {controller.handle(:foo, {})}.
                should raise_error quot;cannot handle event fooquot;
  end

end
some points for discussion


•   Do we need a command pattern in
    dynamic languages ?
    •   can we get away with using a block/
        closure
•   What are the different ways in which these
    commands could be configured?

Mais conteúdo relacionado

Mais de melbournepatterns (20)

Iterator Pattern
Iterator PatternIterator Pattern
Iterator Pattern
 
Iterator
IteratorIterator
Iterator
 
Concurrency Patterns
Concurrency PatternsConcurrency Patterns
Concurrency Patterns
 
Continuous Integration, Fast Builds and Flot
Continuous Integration, Fast Builds and FlotContinuous Integration, Fast Builds and Flot
Continuous Integration, Fast Builds and Flot
 
Command Pattern
Command PatternCommand Pattern
Command Pattern
 
Code Contracts API In .Net
Code Contracts API In .NetCode Contracts API In .Net
Code Contracts API In .Net
 
LINQ/PLINQ
LINQ/PLINQLINQ/PLINQ
LINQ/PLINQ
 
Gpu Cuda
Gpu CudaGpu Cuda
Gpu Cuda
 
Facade Pattern
Facade PatternFacade Pattern
Facade Pattern
 
Phani Kumar - Decorator Pattern
Phani Kumar - Decorator PatternPhani Kumar - Decorator Pattern
Phani Kumar - Decorator Pattern
 
Composite Pattern
Composite PatternComposite Pattern
Composite Pattern
 
Adapter Design Pattern
Adapter Design PatternAdapter Design Pattern
Adapter Design Pattern
 
Prototype Design Pattern
Prototype Design PatternPrototype Design Pattern
Prototype Design Pattern
 
Factory Method Design Pattern
Factory Method Design PatternFactory Method Design Pattern
Factory Method Design Pattern
 
Abstract Factory Design Pattern
Abstract Factory Design PatternAbstract Factory Design Pattern
Abstract Factory Design Pattern
 
A Little Lisp
A Little LispA Little Lisp
A Little Lisp
 
State Pattern in Flex
State Pattern in FlexState Pattern in Flex
State Pattern in Flex
 
Active Object
Active ObjectActive Object
Active Object
 
Extract Composite Talk Andy
Extract Composite Talk AndyExtract Composite Talk Andy
Extract Composite Talk Andy
 
Selenium Interpreter
Selenium InterpreterSelenium Interpreter
Selenium Interpreter
 

Último

Falcon Invoice Discounting: Empowering Your Business Growth
Falcon Invoice Discounting: Empowering Your Business GrowthFalcon Invoice Discounting: Empowering Your Business Growth
Falcon Invoice Discounting: Empowering Your Business GrowthFalcon investment
 
JAJPUR CALL GIRL ❤ 82729*64427❤ CALL GIRLS IN JAJPUR ESCORTS
JAJPUR CALL GIRL ❤ 82729*64427❤ CALL GIRLS IN JAJPUR  ESCORTSJAJPUR CALL GIRL ❤ 82729*64427❤ CALL GIRLS IN JAJPUR  ESCORTS
JAJPUR CALL GIRL ❤ 82729*64427❤ CALL GIRLS IN JAJPUR ESCORTSkajalroy875762
 
Lucknow Housewife Escorts by Sexy Bhabhi Service 8250092165
Lucknow Housewife Escorts  by Sexy Bhabhi Service 8250092165Lucknow Housewife Escorts  by Sexy Bhabhi Service 8250092165
Lucknow Housewife Escorts by Sexy Bhabhi Service 8250092165meghakumariji156
 
Marel Q1 2024 Investor Presentation from May 8, 2024
Marel Q1 2024 Investor Presentation from May 8, 2024Marel Q1 2024 Investor Presentation from May 8, 2024
Marel Q1 2024 Investor Presentation from May 8, 2024Marel
 
KALYANI 💋 Call Girl 9827461493 Call Girls in Escort service book now
KALYANI 💋 Call Girl 9827461493 Call Girls in  Escort service book nowKALYANI 💋 Call Girl 9827461493 Call Girls in  Escort service book now
KALYANI 💋 Call Girl 9827461493 Call Girls in Escort service book nowkapoorjyoti4444
 
Only Cash On Delivery Call Girls In Sikandarpur Gurgaon ❤️8448577510 ⊹Escorts...
Only Cash On Delivery Call Girls In Sikandarpur Gurgaon ❤️8448577510 ⊹Escorts...Only Cash On Delivery Call Girls In Sikandarpur Gurgaon ❤️8448577510 ⊹Escorts...
Only Cash On Delivery Call Girls In Sikandarpur Gurgaon ❤️8448577510 ⊹Escorts...lizamodels9
 
Nanded Call Girl Just Call 8084732287 Top Class Call Girl Service Available
Nanded Call Girl Just Call 8084732287 Top Class Call Girl Service AvailableNanded Call Girl Just Call 8084732287 Top Class Call Girl Service Available
Nanded Call Girl Just Call 8084732287 Top Class Call Girl Service Availablepr788182
 
SEO Case Study: How I Increased SEO Traffic & Ranking by 50-60% in 6 Months
SEO Case Study: How I Increased SEO Traffic & Ranking by 50-60%  in 6 MonthsSEO Case Study: How I Increased SEO Traffic & Ranking by 50-60%  in 6 Months
SEO Case Study: How I Increased SEO Traffic & Ranking by 50-60% in 6 MonthsIndeedSEO
 
Katrina Personal Brand Project and portfolio 1
Katrina Personal Brand Project and portfolio 1Katrina Personal Brand Project and portfolio 1
Katrina Personal Brand Project and portfolio 1kcpayne
 
The Abortion pills for sale in Qatar@Doha [+27737758557] []Deira Dubai Kuwait
The Abortion pills for sale in Qatar@Doha [+27737758557] []Deira Dubai KuwaitThe Abortion pills for sale in Qatar@Doha [+27737758557] []Deira Dubai Kuwait
The Abortion pills for sale in Qatar@Doha [+27737758557] []Deira Dubai Kuwaitdaisycvs
 
Berhampur 70918*19311 CALL GIRLS IN ESCORT SERVICE WE ARE PROVIDING
Berhampur 70918*19311 CALL GIRLS IN ESCORT SERVICE WE ARE PROVIDINGBerhampur 70918*19311 CALL GIRLS IN ESCORT SERVICE WE ARE PROVIDING
Berhampur 70918*19311 CALL GIRLS IN ESCORT SERVICE WE ARE PROVIDINGpr788182
 
obat aborsi bandung wa 081336238223 jual obat aborsi cytotec asli di bandung9...
obat aborsi bandung wa 081336238223 jual obat aborsi cytotec asli di bandung9...obat aborsi bandung wa 081336238223 jual obat aborsi cytotec asli di bandung9...
obat aborsi bandung wa 081336238223 jual obat aborsi cytotec asli di bandung9...yulianti213969
 
UAE Bur Dubai Call Girls ☏ 0564401582 Call Girl in Bur Dubai
UAE Bur Dubai Call Girls ☏ 0564401582 Call Girl in Bur DubaiUAE Bur Dubai Call Girls ☏ 0564401582 Call Girl in Bur Dubai
UAE Bur Dubai Call Girls ☏ 0564401582 Call Girl in Bur Dubaijaehdlyzca
 
Durg CALL GIRL ❤ 82729*64427❤ CALL GIRLS IN durg ESCORTS
Durg CALL GIRL ❤ 82729*64427❤ CALL GIRLS IN durg ESCORTSDurg CALL GIRL ❤ 82729*64427❤ CALL GIRLS IN durg ESCORTS
Durg CALL GIRL ❤ 82729*64427❤ CALL GIRLS IN durg ESCORTSkajalroy875762
 
Unveiling Falcon Invoice Discounting: Leading the Way as India's Premier Bill...
Unveiling Falcon Invoice Discounting: Leading the Way as India's Premier Bill...Unveiling Falcon Invoice Discounting: Leading the Way as India's Premier Bill...
Unveiling Falcon Invoice Discounting: Leading the Way as India's Premier Bill...Falcon Invoice Discounting
 
Cuttack Call Girl Just Call 8084732287 Top Class Call Girl Service Available
Cuttack Call Girl Just Call 8084732287 Top Class Call Girl Service AvailableCuttack Call Girl Just Call 8084732287 Top Class Call Girl Service Available
Cuttack Call Girl Just Call 8084732287 Top Class Call Girl Service Availablepr788182
 
Nashik Call Girl Just Call 7091819311 Top Class Call Girl Service Available
Nashik Call Girl Just Call 7091819311 Top Class Call Girl Service AvailableNashik Call Girl Just Call 7091819311 Top Class Call Girl Service Available
Nashik Call Girl Just Call 7091819311 Top Class Call Girl Service Availablepr788182
 
Pre Engineered Building Manufacturers Hyderabad.pptx
Pre Engineered  Building Manufacturers Hyderabad.pptxPre Engineered  Building Manufacturers Hyderabad.pptx
Pre Engineered Building Manufacturers Hyderabad.pptxRoofing Contractor
 
Horngren’s Cost Accounting A Managerial Emphasis, Canadian 9th edition soluti...
Horngren’s Cost Accounting A Managerial Emphasis, Canadian 9th edition soluti...Horngren’s Cost Accounting A Managerial Emphasis, Canadian 9th edition soluti...
Horngren’s Cost Accounting A Managerial Emphasis, Canadian 9th edition soluti...ssuserf63bd7
 
Putting the SPARK into Virtual Training.pptx
Putting the SPARK into Virtual Training.pptxPutting the SPARK into Virtual Training.pptx
Putting the SPARK into Virtual Training.pptxCynthia Clay
 

Último (20)

Falcon Invoice Discounting: Empowering Your Business Growth
Falcon Invoice Discounting: Empowering Your Business GrowthFalcon Invoice Discounting: Empowering Your Business Growth
Falcon Invoice Discounting: Empowering Your Business Growth
 
JAJPUR CALL GIRL ❤ 82729*64427❤ CALL GIRLS IN JAJPUR ESCORTS
JAJPUR CALL GIRL ❤ 82729*64427❤ CALL GIRLS IN JAJPUR  ESCORTSJAJPUR CALL GIRL ❤ 82729*64427❤ CALL GIRLS IN JAJPUR  ESCORTS
JAJPUR CALL GIRL ❤ 82729*64427❤ CALL GIRLS IN JAJPUR ESCORTS
 
Lucknow Housewife Escorts by Sexy Bhabhi Service 8250092165
Lucknow Housewife Escorts  by Sexy Bhabhi Service 8250092165Lucknow Housewife Escorts  by Sexy Bhabhi Service 8250092165
Lucknow Housewife Escorts by Sexy Bhabhi Service 8250092165
 
Marel Q1 2024 Investor Presentation from May 8, 2024
Marel Q1 2024 Investor Presentation from May 8, 2024Marel Q1 2024 Investor Presentation from May 8, 2024
Marel Q1 2024 Investor Presentation from May 8, 2024
 
KALYANI 💋 Call Girl 9827461493 Call Girls in Escort service book now
KALYANI 💋 Call Girl 9827461493 Call Girls in  Escort service book nowKALYANI 💋 Call Girl 9827461493 Call Girls in  Escort service book now
KALYANI 💋 Call Girl 9827461493 Call Girls in Escort service book now
 
Only Cash On Delivery Call Girls In Sikandarpur Gurgaon ❤️8448577510 ⊹Escorts...
Only Cash On Delivery Call Girls In Sikandarpur Gurgaon ❤️8448577510 ⊹Escorts...Only Cash On Delivery Call Girls In Sikandarpur Gurgaon ❤️8448577510 ⊹Escorts...
Only Cash On Delivery Call Girls In Sikandarpur Gurgaon ❤️8448577510 ⊹Escorts...
 
Nanded Call Girl Just Call 8084732287 Top Class Call Girl Service Available
Nanded Call Girl Just Call 8084732287 Top Class Call Girl Service AvailableNanded Call Girl Just Call 8084732287 Top Class Call Girl Service Available
Nanded Call Girl Just Call 8084732287 Top Class Call Girl Service Available
 
SEO Case Study: How I Increased SEO Traffic & Ranking by 50-60% in 6 Months
SEO Case Study: How I Increased SEO Traffic & Ranking by 50-60%  in 6 MonthsSEO Case Study: How I Increased SEO Traffic & Ranking by 50-60%  in 6 Months
SEO Case Study: How I Increased SEO Traffic & Ranking by 50-60% in 6 Months
 
Katrina Personal Brand Project and portfolio 1
Katrina Personal Brand Project and portfolio 1Katrina Personal Brand Project and portfolio 1
Katrina Personal Brand Project and portfolio 1
 
The Abortion pills for sale in Qatar@Doha [+27737758557] []Deira Dubai Kuwait
The Abortion pills for sale in Qatar@Doha [+27737758557] []Deira Dubai KuwaitThe Abortion pills for sale in Qatar@Doha [+27737758557] []Deira Dubai Kuwait
The Abortion pills for sale in Qatar@Doha [+27737758557] []Deira Dubai Kuwait
 
Berhampur 70918*19311 CALL GIRLS IN ESCORT SERVICE WE ARE PROVIDING
Berhampur 70918*19311 CALL GIRLS IN ESCORT SERVICE WE ARE PROVIDINGBerhampur 70918*19311 CALL GIRLS IN ESCORT SERVICE WE ARE PROVIDING
Berhampur 70918*19311 CALL GIRLS IN ESCORT SERVICE WE ARE PROVIDING
 
obat aborsi bandung wa 081336238223 jual obat aborsi cytotec asli di bandung9...
obat aborsi bandung wa 081336238223 jual obat aborsi cytotec asli di bandung9...obat aborsi bandung wa 081336238223 jual obat aborsi cytotec asli di bandung9...
obat aborsi bandung wa 081336238223 jual obat aborsi cytotec asli di bandung9...
 
UAE Bur Dubai Call Girls ☏ 0564401582 Call Girl in Bur Dubai
UAE Bur Dubai Call Girls ☏ 0564401582 Call Girl in Bur DubaiUAE Bur Dubai Call Girls ☏ 0564401582 Call Girl in Bur Dubai
UAE Bur Dubai Call Girls ☏ 0564401582 Call Girl in Bur Dubai
 
Durg CALL GIRL ❤ 82729*64427❤ CALL GIRLS IN durg ESCORTS
Durg CALL GIRL ❤ 82729*64427❤ CALL GIRLS IN durg ESCORTSDurg CALL GIRL ❤ 82729*64427❤ CALL GIRLS IN durg ESCORTS
Durg CALL GIRL ❤ 82729*64427❤ CALL GIRLS IN durg ESCORTS
 
Unveiling Falcon Invoice Discounting: Leading the Way as India's Premier Bill...
Unveiling Falcon Invoice Discounting: Leading the Way as India's Premier Bill...Unveiling Falcon Invoice Discounting: Leading the Way as India's Premier Bill...
Unveiling Falcon Invoice Discounting: Leading the Way as India's Premier Bill...
 
Cuttack Call Girl Just Call 8084732287 Top Class Call Girl Service Available
Cuttack Call Girl Just Call 8084732287 Top Class Call Girl Service AvailableCuttack Call Girl Just Call 8084732287 Top Class Call Girl Service Available
Cuttack Call Girl Just Call 8084732287 Top Class Call Girl Service Available
 
Nashik Call Girl Just Call 7091819311 Top Class Call Girl Service Available
Nashik Call Girl Just Call 7091819311 Top Class Call Girl Service AvailableNashik Call Girl Just Call 7091819311 Top Class Call Girl Service Available
Nashik Call Girl Just Call 7091819311 Top Class Call Girl Service Available
 
Pre Engineered Building Manufacturers Hyderabad.pptx
Pre Engineered  Building Manufacturers Hyderabad.pptxPre Engineered  Building Manufacturers Hyderabad.pptx
Pre Engineered Building Manufacturers Hyderabad.pptx
 
Horngren’s Cost Accounting A Managerial Emphasis, Canadian 9th edition soluti...
Horngren’s Cost Accounting A Managerial Emphasis, Canadian 9th edition soluti...Horngren’s Cost Accounting A Managerial Emphasis, Canadian 9th edition soluti...
Horngren’s Cost Accounting A Managerial Emphasis, Canadian 9th edition soluti...
 
Putting the SPARK into Virtual Training.pptx
Putting the SPARK into Virtual Training.pptxPutting the SPARK into Virtual Training.pptx
Putting the SPARK into Virtual Training.pptx
 

Refactoring Conditional Dispatcher To Command

  • 1. Refactoring Conditional Dispatcher with Command (based on Refactoring to Patterns) Sreenivas Ananthakrishna
  • 2. let’s start with an example...
  • 4. so what can the ATM do?
  • 5. so what can the ATM do? ➡ Display the login screen when card is inserted
  • 6. so what can the ATM do? ➡ Display the login screen when card is inserted ➡ Authenticate the user
  • 7. so what can the ATM do? ➡ Display the login screen when card is inserted ➡ Authenticate the user ➡ Allow authenticated user to withdraw $$$
  • 9. Services Authentication View ATM Controller Account
  • 10. View ➡ renders the screen Services ➡ authenticates the user ➡ transfer/ debit money from account Controller ➡ handles requests from view
  • 11. let’s focus on building the ATMController...
  • 12. and in TDD fashion, the test come first!
  • 13. describe quot;an instance of quot;, ATMController do it quot;should render login when card is insertedquot; do view = mock(View) view.should_receive(:render). with(:login, {:account_id => 1234}) controller = ATMController.new view controller.handle :card_inserted, {:account_id => 1234} end end
  • 15. class ATMController def initialize view @view = view end def handle event, params @view.render :login, {:account_id => params[:account_id]} end end
  • 17. it quot;should raise error for unknown eventquot; do view = mock(View) view.should_not_receive(:render) controller = ATMController.new view lambda {controller.handle(:foo, {})}. should raise_error(RuntimeError, quot;cannot handle event fooquot;) end
  • 19. class ATMController def initialize view @view = view end def handle event, params if event == :card_inserted @view.render :login, {:account_id => params[:account_id]} else raise quot;cannot handle event #{event}quot; end end end
  • 21. it quot;should display withdraw menu when user has authenticatedquot; do view = mock(View) view.should_receive(:render).with(:withdraw_menu) authentication_service = mock(AuthenticationService) authentication_service.should_receive(:authenticate). with(1234, 5678). and_return(true) controller = ATMController.new view, authentication_service controller.handle :authenticate, {:account_id => 1234, :pin => 5678} end
  • 23. class ATMController def initialize view, authentication_service @authentication_service = authentication_service @view = view end def handle event, params case event when :card_inserted @view.render :login, {:account_id => params[:account_id]} when :authenticate if @authentication_service. authenticate(params[:account_id], params[:pin]) @view.render :withdraw_menu end else raise quot;cannot handle event #{event}quot; end en
  • 24. addition of new dependencies has broken other tests!
  • 26. it quot;should render login when card is insertedquot; do view = mock(View) view.should_receive(:render).with(:login, {:account_id => 1234}) authentication_service = mock(AuthenticationService) authentication_service.should_not_receive(:authenticate) controller = ATMController.new view , authentication_service controller.handle :card_inserted, {:account_id => 1234} end
  • 27. so, as the controller keeps handling new events...
  • 28. so, as the controller keeps handling new events... ๏ handle method keeps getting bloated
  • 29. so, as the controller keeps handling new events... ๏ handle method keeps getting bloated ๏ which means higher complexity
  • 30. so, as the controller keeps handling new events... ๏ handle method keeps getting bloated ๏ which means higher complexity ๏ adding new events requires changing the controller implementation
  • 31. so, as the controller keeps handling new events... ๏ handle method keeps getting bloated ๏ which means higher complexity ๏ adding new events requires changing the controller implementation ๏ addition of new receivers also affects existing test cases
  • 32. let’s see how we can simplify by refactoring to the Command
  • 35. Before def handle event, params case event when :card_inserted @view.render :login, {:account_id => params[:account_id]} when :authenticate if @authentication_service. authenticate(params[:account_id], params[:pin]) @view.render :withdraw_menu end else raise quot;cannot handle event #{event}quot; end end
  • 36. After def handle event, params case event when :card_inserted handle_card_inserted params when :authenticate handle_authenticate params else raise quot;cannot handle event #{event}quot; end end
  • 38. Before def handle_authenticate params if @authentication_service. authenticate(params[:account_id], params[:pin]) @view.render :withdraw_menu end end
  • 39. After def handle_authenticate params action = AuthenticateAction.new @view, @authentication_service action.execute params end
  • 41. class Action def execute params raise quot;not implemented!quot; end end class AuthenticateAction < Action def initialize view, authentication_service @view = view @authentication_service = authentication_service end def execute params if @authentication_service. authenticate(params[:account_id], params[:pin]) @view.render :withdraw_menu end end end
  • 42. configure the controller with map of actions
  • 43. class ATMController def initialize map @actions = map end def handle event, params if @actions.include? event @actions[event].execute params else raise quot;cannot handle event #{event}quot; end end end
  • 44. now, even the tests are simpler!
  • 45. describe quot;an instance of quot;, ATMController do it quot;should execute the action for the eventquot; do params = {'foo' => 'bar'} action = mock(Action) action.should_receive(:execute).with(params) controller = ATMController.new({:foo_event => action}) controller.handle(:foo_event, params) end it quot;should raise error for unknown eventquot; do controller = ATMController.new({}) lambda {controller.handle(:foo, {})}. should raise_error quot;cannot handle event fooquot; end end
  • 46. some points for discussion • Do we need a command pattern in dynamic languages ? • can we get away with using a block/ closure • What are the different ways in which these commands could be configured?