Skip to content

Instantly share code, notes, and snippets.

@alvinncx
Last active October 10, 2020 08:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alvinncx/58ef6b9bfd88dcea6da9c70b1293e08c to your computer and use it in GitHub Desktop.
Save alvinncx/58ef6b9bfd88dcea6da9c70b1293e08c to your computer and use it in GitHub Desktop.
Refactoring exercise #1
class Price
def price_code; end
def charge; end
def frequent_renter_points
1
end
class Childrens
def price_code; Movie::CHILDRENS; end
def charge(days_rented)
result = 1.5;
if days_rented > 3
result = result + (days_rented - 3) * 1.5
end
return result
end
end
class NewRelease
def price_code; Movie::NEW_RELEASE; end
def charge(days_rented)
result = days_rented * 3
end
def frequent_renter_points
days_rented > 1 ? 2 : 1
end
end
class RegularPrice
def price_code; Movie::REGULAR; end
def charge(days_rented)
result = 2;
if days_rented > 2
result = result + (days_rented - 2) * 1.5
end
return result
end
end
end
class Movie < ActiveRecord::Base
has_many :rentals
CHILDRENS = 2
REGULAR = 0
NEW_RELEASE = 1
attribute :title, :string
attribute :price_code, :int
attr_accessor :price
def initialize
case price_code
when REGULAR
@price = Price::Regular.new
when CHILDRENS
@price = Price::Childrens.new
when NEW_RELEASE
@price = Price::NewRelease.new
end
end
def price_code
@price.price_code
end
def frequent_renter_points(days_rented)
@price.frequent_renter_points(days_rented)
end
def charge(days_rented)
@price.charge(days_rented)
end
end
class Rental < ActiveRecord::Base
belongs_to :movie
belongs_to :customer
attribute :days_rented, :int
def frequent_renter_points
movie.frequent_rental_points(days_rented)
end
def charge
movie.charge(days_rented)
end
end
class Customer < ActiveRecord::Base
has_many :rentals
attribute :name, :string
def total_charge
rentals.map(&:charge).sum
end
def total_frequent_renter_points
rentals.map(&:frequent_renter_points).sum
end
def statement
result = "Rental Record for #{name} \n"
rentals.for_each { |rental|
result << "\t#{rental.movie.title}\t#{rental.charge}\n"
}
result << "Amount owed is #{total_charge}\n"
result << "You earned #{total_frequent_renter_points} frequent renter points"
return total_amount
end
end
@alvinncx
Copy link
Author

alvinncx commented Oct 10, 2020

Play though the Gist Revisions to see each refactoring step

Tried to refactor the piece of code introduced in the opening chaper of Refactoring: Improving the Design of Existing Code by Martin Folwer. It was originally in Java, I've tried to follow the exercise in Ruby.

Techniques used here

  • Extract Method
  • Move Method
  • Replace Conditional with Polymorphism
  • Replace Type Code with State
  • Delegation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment