DEV Community

Naomi Dennis
Naomi Dennis

Posted on

2

Favorite Refactoring Techniques: Extract Class

The next refactoring technique we'll look at is extracting classes. Extracting classes has a similar thought process as extracting functions. In both cases, we are extracting behavior. For classes however, we are extracting sets of behavior or data.

Say we have the following code:

if item == "Paper"
money = perform_transaction(money, item, 20)
elsif item == "Ball"
money = perform_transaction(money, item, 50)
elsif item == "Book"
money = perform_transaction(money, item, 40)
elsif item == "Chips"
money = perform_transaction(money, item, 4)
else
puts "We don't sell that item"
end

Multiple conditionals that test strings is a perfect code smell that indicates something can be refactored. In this situation, each string in the if statement denotes a name for an item in a shop. The body of each statement is the same; it performs a transaction with said item, the item's value and the money of the person shopping. After the transaction is complete, #perform_transaction() returns the amount of money the shopper has left. The only clause that is different is else, which outputs a message to the shopper that the requested item is not found.

With this information we can split the behavior of the conditionals into two parts: performing a transaction when the item is in the shop and outputting a message when the item is not in the shop. Looking at the transaction portion, we can see that each item not only has its own name, but its own value. We can extract this into a ShopItem class.

class ShopItem
attr_reader :value, :name
def initialize(value, name)
@value = value
@name = name
end
end

With this class, we can rewrite our if statement to more accurately portray the first portion, checking if the item is in the shop and outputting a message if it isn't. Before extracting the class, if the item wasn't apart of the conditional statement, it was seen as not being included in the shop. Now, we can create a list of items and if the item isn't in the list, we can output the message.

def items
[ShopItem.new(20, "Paper"),
ShopItem.new(50, "Ball"),
ShopItem.new(40, "Book"),
ShopItem.new(4, "Chips")]
end
def find_item(item_name)
items.select do | item |
item.name == item_name
end.first
end
item = "Ball"
searched_item = find_item(item)
if searched_item != nil
money = perform_transaction(money, searched_item)
else
puts "We don't sell that item"
end

Now our code tells a concrete story. Search for an item. If the item is found, perform the transaction and return money to the shopper, if the item isn't found then tell the shopper the item isn't being sold.

As it stands, our if statement looks pretty good. However, we can make some minor changes to make it a bit better.

def items
[ShopItem.new(20, "Paper"),
ShopItem.new(50, "Ball"),
ShopItem.new(40, "Book"),
ShopItem.new(4, "Chips")]
end
def find_item(item_name)
items.select do | item |
item.name == item_name
end.first
end
item = "Ball"
searched_item = find_item(item)
unless searched_item.nil?
money = perform_transaction(money, searched_item)
else
puts "We don't sell that item"
end

All in all, our code now looks this (Please note, # -- snip -- is code that wasn't mentioned.) :

class ShopItem
attr_reader :value, :name
def initialize(value, name)
@value = value
@name = name
end
end
# -- snip --
def items
[ShopItem.new(20, "Paper"),
ShopItem.new(50, "Ball"),
ShopItem.new(40, "Book"),
ShopItem.new(4, "Chips")]
end
def find_item(item_name)
items.select do | item |
item.name == item_name
end.first
end
item = "Ball"
searched_item = find_item(item)
unless searched_item.nil?
money = perform_transaction(money, searched_item)
else
puts "We don't sell that item"
end

AWS Q Developer image

Your AI Code Assistant

Ask anything about your entire project, code and get answers and even architecture diagrams. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Start free in your IDE

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay