Hello, explorer! Today is about refactoring. Think of it as organizing your favorite tool chest. We're going to learn about Extract Method
, Rename Method
, and Substitute Algorithm
refactorings in C++. Refactoring helps us tidy up our code, making it cleaner and more maintainable, all while preserving its functionality.
Consider having a complicated blueprint. Refactoring changes it into a clearer drawing. Our code is rearranged to enhance readability and efficiency without altering its behavior. Let's examine a short code snippet before and after refactoring:
C++1// Before refactoring 2double calculate(double total, int quantity) { 3 double price = total / quantity; 4 double tax = price * 0.2; 5 double totalPrice = price + tax; 6 return totalPrice; 7}
C++1// After refactoring 2double calculatePrice(double total, int quantity) { 3 return total / quantity; 4} 5 6double calculateTax(double price) { 7 return price * 0.2; 8} 9 10double calculateTotalPrice(double total, int quantity) { 11 double price = calculatePrice(total, quantity); 12 double tax = calculateTax(price); 13 return price + tax; 14}
Both code versions perform the same function, but the refactored version is simpler and easier to comprehend!
Imagine a large set of instructions for setting up a desktop. The Extract Method
technique is like having separate instructions for the monitor, CPU, keyboard, etc., instead of one large set of instructions. Observe this code:
C++1// Before refactoring 2std::string greetUser(std::string username) { 3 // Prepare the username 4 std::transform(username.begin(), username.end(), username.begin(), ::tolower); 5 username.erase(username.find_last_not_of(" \n\r\t")+1); // Find the last non-whitespace character and erase everything after it 6 std::string message = "Hello, " + username + "!"; // Prepare the message 7 return message; // Return the prepared message 8}
C++1// After refactoring 2std::string cleanUsername(std::string username) { 3 // Returns a cleaned version of the username 4 std::transform(username.begin(), username.end(), username.begin(), ::tolower); 5 username.erase(username.find_last_not_of(" \n\r\t")+1); // Find the last non-whitespace character and erase everything after it 6 return username; 7} 8 9std::string greetUser(std::string username) { 10 username = cleanUsername(username); // Clean the username 11 std::string message = "Hello, " + username + "!"; // Prepare and return the message 12 return message; 13}
Here, we moved the username preparation from greetUser
into its dedicated function cleanUsername
. Neat and organized!
Clear method names make code comprehension easier, just as clear street names simplify city navigation. Let's look at renaming a method:
C++1// Before refactoring 2double fx(double x) { 3 return 3.14 * x * x; // Calculates a value that is pi times the square of x 4}
C++1// After refactoring 2double calculateCircleArea(double radius) { 3 return 3.14 * radius * radius; // Calculates the area of a circle with a given radius 4}
Renaming the function fx
to calculateCircleArea
makes understanding its purpose much easier.
Substitute Algorithm
involves replacing a section of code (an algorithm) with a more efficient one, similar to finding a faster route to a destination. Here's an illustration:
C++1// Before refactoring 2int findSmallest(const std::vector<int>& numbers) { 3 int smallest = numbers[0]; 4 for (int num : numbers) { 5 if (num < smallest) { 6 smallest = num; 7 } 8 } 9 return smallest; 10}
C++1// After refactoring 2int findSmallest(const std::vector<int>& numbers) { 3 return *std::min_element(numbers.begin(), numbers.end()); // Returns the smallest number from 'numbers' 4}
The std::min_element
function in C++ accomplishes the same task as our previous implementation but in a more concise and efficient manner.
Great job! We've learned how to use Extract Method
, Rename Method
, and Substitute Algorithm
to keep our C++ code clean and efficient. Now, it's time for some hands-on practice with real-world examples. Remember, practice is key to mastering a skill. Let's get refactoring!