10 Common Code Smells: How to Spot, Avoid, and Fix Them Effectively

5 min read

1. Long Method
Problem
Methods that are too long often become difficult to understand, debug, and maintain. They typically try to do too much, violating the Single Responsibility Principle.
Example
public class OrderProcessor {
public void processOrder(Order order) {
validateOrder(order);
calculateDiscounts(order);
applyShipping(order);
logOrderDetails(order);
sendConfirmationEmail(order);
// More functionality continues...
}
}
Solution
Break down large methods into smaller, more focused helper methods. Each method should handle a specific responsibility.
Refactored Code
public class OrderProcessor {
public void processOrder(Order order) {
validateOrder(order);
applyDiscounts(order);
calculateShipping(order);
logOrder(order);
notifyCustomer(order);
}
private void validateOrder(Order order) { /.../ }
private void applyDiscounts(Order order) { /.../ }
private void calculateShipping(Order order) { /.../ }
private void logOrder(Order order) { /.../ }
private void notifyCustomer(Order order) { /.../ }
}
2. Large Class
Problem
A large class often takes on too many responsibilities, making it harder to maintain, test, and scale.
Example
public class Vehicle {
private Engine engine;
private String gpsLocation;
private String radioStation;
// Methods related to all features of the vehicle, including navigation, engine control, and entertainment...
}
Solution
Apply the Single Responsibility Principle by splitting the class into multiple classes, each handling a specific feature.
Refactored Code
public class Vehicle {
private Engine engine;
private NavigationSystem navigationSystem;
private EntertainmentSystem entertainmentSystem;
// Core vehicle methods only
}
public class NavigationSystem { /.../ }
public class EntertainmentSystem { /.../ }
3. Duplicated Code
Problem
Duplicate code appears when similar code snippets are scattered throughout the application, leading to inconsistencies and a higher likelihood of bugs.
Example
public void printReport() {
System.out.println("Report generated at: " + new Date());
}
public void printSummary() {
System.out.println("Report generated at: " + new Date());
}
Solution
Extract duplicate logic into a shared helper function that can be reused.
Refactored Code
private void printGeneratedTime() {
System.out.println("Report generated at: " + new Date());
}
public void printReport() {
printGeneratedTime();
}
public void printSummary() {
printGeneratedTime();
}
4. Feature Envy
Problem
Feature Envy occurs when a method in one class seems to interact more with another class than its own.
Example
public class OrderProcessor {
public double calculateDiscount(Order order) {
return order.getPrice() * order.getDiscountRate();
}
}
Solution
Move the method to the class it most heavily interacts with.
Refactored Code
public class Order {
public double calculateDiscount() {
return this.price * this.discountRate;
}
}
5. Data Clumps
Problem
Data clumps appear when certain fields tend to appear together across various parts of the code, suggesting they belong in their own object.
Example
public void createOrder(String product, int quantity, double price) {
// order creation logic
}
Solution
Encapsulate related data into an object.
Refactored Code
public void createOrder(Product product) {
// order creation logic
}
public class Product {
private String name;
private int quantity;
private double price;
}
6. Switch Statements
Problem
Frequent switch statements with multiple cases make code hard to extend or update.
Example
public double calculateShippingCost(String country) {
switch (country) {
case "USA":
return 10.0;
case "Canada":
return 12.0;
// Additional cases...
}
}
Solution
Use polymorphism to eliminate the need for switch statements.
Refactored Code
public interface ShippingCalculator {
double calculateCost();
}
public class USAShipping implements ShippingCalculator {
public double calculateCost() { return 10.0; }
}
public class CanadaShipping implements ShippingCalculator {
public double calculateCost() { return 12.0; }
}
7. Lazy Class
Problem
A lazy class is a class that isn’t doing enough to justify its existence, typically because its functionality is too limited.
Solution
Merge lazy classes into others where possible to reduce complexity.
8. Primitive Obsession
Problem
Using primitive types instead of creating a specific class can lead to disorganized and unclear code.
Solution
Replace primitives with a class that better represents the concept.
9. Inappropriate Intimacy
Problem
Classes that are overly familiar with each other’s details violate encapsulation.
Solution
Reduce interdependencies by encapsulating the data in a specific class.
10. Message Chains
Problem
Message chains occur when one method calls a method on another object, which then calls another, and so on.
Solution
Simplify interactions by hiding internal logic or dependencies.
11. Conclusion
These code smells are just some of the many that can subtly degrade the quality of your code over time. Spotting and addressing them can lead to better maintainability, scalability, and readability. Whenever you come across a new code smell, try to analyze its root cause and refactor the code accordingly. If you have questions or want to discuss these code smells further, feel free to leave a comment below!
Read more at : 10 Common Code Smells: How to Spot, Avoid, and Fix Them Effectively
0
Subscribe to my newsletter
Read articles from Tuanhdotnet directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Tuanhdotnet
Tuanhdotnet
I am Tuanh.net. As of 2024, I have accumulated 8 years of experience in backend programming. I am delighted to connect and share my knowledge with everyone.