Created
December 16, 2013 14:01
-
-
Save blake41/7987359 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# You have software to take payment from a customer | |
# There are 4 ways to pay, and they are all very similar. | |
# One day, you are paying by cash, and you realize you never calculated the tax! | |
# So you went in to your code and added order.compute_tax to the pay_by_cash method. | |
# Everything was great, until you realized you forgot to add it to pay_by_check also! | |
# | |
# You fixed this bug already, but the same code is duplicated in many places, | |
# so the bug fix didn't get everything. Frustrated, you decide to refactor your code. | |
# | |
# You see a lot of duplciation, but unfortunately, right in the middle of each of these | |
# pieces of code, is a line or two that changes every time. | |
# | |
# Thinking a little bit, you realize that you could create a method that performs this | |
# boiler plate code, then calls a block which does the custom code. | |
# | |
# You decide to name it pay_by. | |
# | |
# **Create the pay_by method, and refactor each of the four methods below such that they | |
# invoke the pay_by method, and pass it the order, to take care of the code that is all the same | |
# Let them pass a block to take care of the code that is unique.** | |
# | |
# NOTE: This code will only work with the rake tests, which will define the order and current_user | |
# you will not be able to run this code outside of the test | |
def pay_by_visa(order,ccn) | |
order.compute_cost | |
order.compute_shipping | |
order.compute_tax | |
order.payment :type => :visa , :ccn => ccn | |
order.verify_payment | |
order.ship_goods | |
end | |
def pay_by_check(order) | |
order.compute_cost | |
order.compute_shipping | |
order.compute_tax | |
order.payment :type => :check , :signed => true | |
order.ship_goods | |
end | |
def pay_by_cash(order) | |
order.compute_cost | |
order.compute_shipping | |
order.compute_tax | |
order.payment :type => :cash | |
order.ship_goods | |
end | |
def pay_by_store_credit(order) | |
order.compute_cost | |
order.compute_shipping | |
order.compute_tax | |
order.payment :type => :store_credit | |
current_user.store_credit -= order.cost # current_user is a method with no params (ie, the customer) | |
order.ship_goods | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require_relative "using_blocks_refactoring_solution" | |
describe 'refactoring' do | |
describe 'original methods with pay_by intercepted' do | |
before :each do | |
@order = double :order | |
stub!(:pay_by) | |
end | |
it 'should invoke nothing for pay_by_visa' do | |
ccn = double :ccn | |
pay_by_visa @order , ccn | |
end | |
it 'should invoke nothing for pay_by_check' do | |
pay_by_check @order | |
end | |
it 'should invoke nothing for pay_by_cash' do | |
pay_by_cash @order | |
end | |
it 'should invoke nothing for pay_by_store_credit' do | |
current_user = double :current_user | |
pay_by_store_credit @order , current_user | |
end | |
end | |
describe 'pay_by' do | |
it 'should have a method pay_by that receives the order, computes boiler plate code, and invokes the block' do | |
@order = double :order | |
@order.should_receive(:compute_cost).once | |
@order.should_receive(:compute_shipping).once | |
@order.should_receive(:compute_tax).once | |
@order.should_receive(:ship_goods).once | |
block_called = double(:block_called) | |
block_called.should_receive :block_was_called | |
yielded = [] | |
pay_by @order do |order| | |
yielded << order | |
block_called.block_was_called | |
end | |
yielded.should eq([@order]) | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def pay_by(order) | |
order.compute_cost | |
order.compute_shipping | |
order.compute_tax | |
yield order | |
order.ship_goods | |
end | |
def pay_by_visa(order,ccn) | |
pay_by order do |order| | |
order.payment :type => :visa , :ccn => ccn | |
order.verify_payment | |
end | |
end | |
def pay_by_check(order) | |
pay_by(order) {|order| order.payment :type => :check , :signed => true } | |
end | |
def pay_by_cash(order) | |
pay_by(order) {|order| order.payment :type => :cash } | |
end | |
def pay_by_store_credit(order,current_user) | |
pay_by order do |order| | |
order.payment :type => :store_credit | |
current_user.store_credit -= order.cost | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment