Refactoring is the process of restructuring existing code without changing its external behavior to improve its readability, maintainability, and performance. Here are some refactoring exercises that will help you practice and enhance your refactoring skills:
1. Extract Method
void processOrder(Order order) {
// Validate order
if (order.items.isEmpty) {
throw Exception('Order is empty');
}
// Calculate total
double total = 0;
for (var item in order.items) {
total += item.price * item.quantity;
}
// Print receipt
print('Receipt for Order:');
for (var item in order.items) {
print('${item.name}: ${item.quantity} x ${item.price}');
}
print('Total: $total');
}
void processOrder(Order order) {
validateOrder(order);
double total = calculateTotal(order);
printReceipt(order, total);
}
void validateOrder(Order order) {
if (order.items.isEmpty) {
throw Exception('Order is empty');
}
}
double calculateTotal(Order order) {
double total = 0;
for (var item in order.items) {
total += item.price * item.quantity;
}
return total;
}
void printReceipt(Order order, double total) {
print('Receipt for Order:');
for (var item in order.items) {
print('${item.name}: ${item.quantity} x ${item.price}');
}
print('Total: $total');
}
2. Inline Method
void processOrder(Order order) {
double total = calculateTotal(order);
print('Total: $total');
}
double calculateTotal(Order order) {
return order.items.fold(0, (sum, item) => sum + item.price * item.quantity);
}
void processOrder(Order order) {
double total = order.items.fold(0, (sum, item) => sum + item.price * item.quantity);
print('Total: $total');
}
3. Rename Variable
void calculateTotal(List<Item> items) {
double t = 0;
for (var item in items) {
t += item.price * item.quantity;
}
print('Total: $t');
}
void calculateTotal(List<Item> items) {
double total = 0;
for (var item in items) {
total += item.price * item.quantity;
}
print('Total: $total');
}
3. Replace Magic Number with Named Constant
double calculateFinalPrice(double price) {
return price * 0.85;
}
const double discountRate = 0.85;
double calculateFinalPrice(double price) {
return price * discountRate;
}
5. Encapsulate Field
class Person {
String name;
}
class Person {
String _name;
String get name => _name;
set name(String value) {
if (value.isNotEmpty) {
_name = value;
} else {
throw Exception('Name cannot be empty');
}
}
}
6. Introduce Expalining Variable
void calculateFinalPrice(double price, double discount) {
print(price - price * discount * 0.01);
}
void calculateFinalPrice(double price, double discount) {
double discountAmount = price * discount * 0.01;
double finalPrice = price - discountAmount;
print(finalPrice);
}
7. Simplify Conditional Expression
double calculateShippingCost(double weight) {
if (weight < 5) {
return 10;
} else {
return 20;
}
}
double calculateShippingCost(double weight) {
return weight < 5 ? 10 : 20;
}
8. Replace Nested Conditional With Guard Clauses
double calculateDiscount(double price, bool isMember) {
if (isMember) {
if (price > 100) {
return price * 0.1;
} else {
return price * 0.05;
}
} else {
return 0;
}
}
double calculateDiscount(double price, bool isMember) {
if (!isMember) {
return 0;
}
if (price > 100) {
return price * 0.1;
}
return price * 0.05;
}
9. Remove Duplicate Code
void renderAdminPage() {
print('Header');
print('Admin Content');
print('Footer');
}
void renderUserPage() {
print('Header');
print('User Content');
print('Footer');
}
void renderPage(String content) {
print('Header');
print(content);
print('Footer');
}
void renderAdminPage() {
renderPage('Admin Content');
}
void renderUserPage() {
renderPage('User Content');
}
10. Replace loop with Collection Operations
List<int> doubleValues(List<int> values) {
List<int> result = [];
for (var value in values) {
result.add(value * 2);
}
return result;
}
List<int> doubleValues(List<int> values) {
return values.map((value) => value * 2).toList();
}