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

TuanhdotnetTuanhdotnet
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.