Lesson 1
Refactoring and Code Smells in Ruby
Topic Overview

Welcome to the world of refactoring! We're learning about Code Smells, patterns in code that hint at potential problems. Our mission is to help you spot these smells and understand how to improve them, or in programming terms, how to refactor them. We'll delve into the concept of code smells, examine different types, and apply real-world code examples to solidify your understanding. Let's get started!

Introduction to Code Smells

Code smells are signs that something could be amiss in our code. You could compare them to an unpleasant smell in a room. But instead of indicating rotten food or a dirty sock, they signal that our code may not be as readable, efficient, or manageable as it could be.

Consider this bit of code:

Ruby
1def calculate(quantity, price) 2 quantity * price 3end 4 5total = calculate(5, 3)

The method name calculate is too vague. What exactly does it calculate? For whom? This ambiguity is a sign of a 'bad naming' code smell.

Duplicate Code

If you notice the same piece of code in more than one place, you may be looking at an example of the Duplicate Code smell. Duplicate code leaves room for errors and bugs. If you need to make a change, you might overlook one instance of duplication.

Here's an example:

Ruby
1total_apples_price = quantity_apples * price_apple - 5 2total_bananas_price = quantity_bananas * price_banana - 5

This code performs the same operation on different data. Instead of duplicating the operation, we can create a method to handle it:

Ruby
1def calculate_price(quantity, price) 2 discount = 5 3 quantity * price - discount 4end 5 6total_apples_price = calculate_price(quantity_apples, price_apple) 7total_bananas_price = calculate_price(quantity_bananas, price_banana)

With this solution, if we need to change the discount or the formula, we can do so in one place: the calculate_price method.

Too Long Method

A method that does too many things or is too long is harder to read and understand, making it a prime candidate for the Too Long Method smell.

Consider this example:

Ruby
1def process_order(order) 2 puts "Processing order..." 3 if order.valid? 4 puts "Order is valid" 5 if order.payment_type == "credit_card" 6 process_credit_card_payment(order) 7 send_order_confirmation_email(order) 8 elsif order.payment_type == "paypal" 9 process_paypal_payment(order) 10 send_order_confirmation_email(order) 11 elsif order.payment_type == "bank_transfer" 12 process_bank_transfer_payment(order) 13 send_order_confirmation_email(order) 14 else 15 puts "Unsupported payment type" 16 return false 17 end 18 puts "Order processed successfully!" 19 true 20 else 21 puts "Invalid order" 22 false 23 end 24end

This function handles too many aspects of order processing, suggesting a 'Too Long Method' smell. A better approach could involve breaking down the functionality into smaller, more focused methods.

For example, the updated code can look like this:

Ruby
1def process_payment(payment_type, order) 2 case payment_type 3 when "credit_card" 4 process_credit_card_payment(order) 5 when "paypal" 6 process_paypal_payment(order) 7 when "bank_transfer" 8 process_bank_transfer_payment(order) 9 else 10 puts "Unsupported payment type" 11 return false 12 end 13 true 14end 15 16def process_order(order) 17 puts "Processing order..." 18 unless order.valid? 19 puts "Invalid order" 20 return false 21 end 22 23 if process_payment(order.payment_type, order) 24 send_order_confirmation_email(order) 25 puts "Order processed successfully!" 26 true 27 else 28 false 29 end 30end
Comment Abuse

Comments within your code should provide useful information. However, remember, too much of a good thing can be a problem. Over-commenting can distract from the code itself and, more often than not, it's a sign the code isn't clear enough.

Consider this revised method, which calculates the area of a triangle, now with comments:

Ruby
1def calculate_triangle_area(base, height) 2 # Calculate the area of a triangle 3 # Formula: 0.5 * base * height 4 area = 0.5 * base * height # Area calculation 5 area # Return the result 6end

While comments explaining the formula might be helpful for some, the code itself is quite straightforward, and the comments on the calculation itself might be seen as unnecessary. If the method's name and parameters are clear, the need for additional comments can be minimized.

Bad Naming

Finally, we have Bad Naming. As the name suggests, this smell occurs when names don't adequately explain what a variable, method, or class does. Good names are crucial for readable, understandable code.

Take a look at the following example:

Ruby
1def func(a, b) 2 a * 10 + b 3end

The names func, a, and b don't tell us much about what is happening. A better version could be this:

Ruby
1def calculate_score(base_score, extra_points) 2 base_score * 10 + extra_points 3end

In this version, each name describes the data or action it represents, making the code easier to read.

Lesson Summary and Practice

We've discovered Code smells and studied common types: Duplicate Code, Too Long Method, Comment Abuse, and Bad Naming. Now you can spot code smells and understand how they can signal a problem in your code.

In the upcoming real-world example-based practice sessions, you'll enhance your debugging skills, and improve your code's efficiency, readability, and maintainability. How exciting is that? Let's move ahead!

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.