25 Common Code Smells and Their Refactoring Solutions
This article explains twenty‑five typical code smells—such as duplicated code, long methods, large classes, and excessive parameters—and provides concrete refactoring techniques like Extract Method, Extract Class, and Move Method to improve readability, maintainability, and design quality in object‑oriented software.
1. Duplicated Code
Duplicated code appears in different locations with identical structure, making maintenance difficult because changes must be applied in multiple places.
Three typical scenarios and their optimizations:
Two methods in the same class share the same statements – use Extract Method to create a common method.
Two sibling subclasses contain the same code – extract the common method to the parent class.
Unrelated classes duplicate code – extract the duplicated logic into a new utility class ( Extract Class ).
class A {
public void method1() {
doSomething1
doSomething2
doSomething3
}
public void method2() {
doSomething1
doSomething2
doSomething4
}
} class A {
public void method1() {
commonMethod();
doSomething3
}
public void method2() {
commonMethod();
doSomething4
}
public void commonMethod() {
doSomething1
doSomething2
}
}2. Long Method
Methods that span hundreds of lines are hard to read and understand. The solution is to apply Extract Method to break the method into smaller, well‑named functions.
public class Test {
public void printOwing() {
// print banner
System.out.println("****************");
// calculate totalAmount
double totalAmount = 0.0;
// print details
System.out.println("name:" + name);
System.out.println("amount:" + totalAmount);
}
} public class Test {
public void printOwing() {
printBanner();
double totalAmount = getTotalAmount();
printDetail(totalAmount);
}
void printBanner() { ... }
double getTotalAmount() { ... }
void printDetail(double totalAmount) { ... }
}3. Large Class
A class that does too many unrelated things reduces readability and performance. Apply Extract Class to separate responsibilities.
class A {
void printOrder() { System.out.println("订单"); }
void printGoods() { System.out.println("商品"); }
void printPoints() { System.out.println("积分"); }
} class Order { void printOrder() { ... } }
class Goods { void printGoods() { ... } }
class Points { void printPoints() { ... } }4. Long Parameter List
Methods with many parameters are hard to use and evolve. Group related parameters into a DTO.
public void getUserInfo(String name, String age, String sex, String mobile) { ... } public void getUserInfo(UserInfoParamDTO dto) { ... }
class UserInfoParamDTO { String name; String age; String sex; String mobile; }5. Divergent Change
When a single class requires multiple unrelated modifications, split the class so that related changes stay together. Example: extract an IEngine interface and move brand‑specific logic to subclasses.
public interface IEngine { void start(); }
class HybridEngineImpl implements IEngine { public void start() { ... } }6. Shotgun Surgery
Scattered small changes across many classes can be consolidated by moving fields or methods into a single class.
public class DbUtils { @Value("${db.mysql.url}") private String mysqlDbUrl; }7. Feature Envy
A method that heavily uses another class's data should be moved to that class.
class User { void getFullPhoneNumber(Phone phone) { ... } }8. Data Clumps
When several data items always appear together, encapsulate them into a value object.
class User { private String firstName; private String lastName; private String province; private String city; ... } class User { private UserName username; private Address address; }
class UserName { private String firstName; private String lastName; }
class Address { private String province; private String city; private String area; private String street; }9. Primitive Obsession
Wrap frequently co‑occurring primitive fields into domain objects.
class Order { private String customName; private String address; private Integer orderId; private Integer price; } class Order { private Custom custom; private Integer orderId; private Integer price; }
class Custom { private String name; private String address; }10. Switch Statements
Replace long if…else or switch chains with polymorphism.
interface IMedalService { void showMedal(); }
class GuardMedalServiceImpl implements IMedalService { public void showMedal() { System.out.println("展示守护勋章"); } }11. Parallel Inheritance Hierarchies
When two class hierarchies evolve together, consider removing one inheritance relationship or using composition.
12. Lazy Class
Merge the functionality of a rarely used class into a more relevant class and delete the lazy class.
13. Speculative Generality
Avoid over‑engineering; remove unused abstractions, parameters, or hierarchies.
14. Temporary Field
Eliminate fields that exist only for a short‑lived calculation; compute the value locally instead.
15. Message Chains
Break long chains of calls by introducing delegation methods or moving logic closer to the client.
16. Middle Man
Remove unnecessary forwarding methods; let clients interact directly with the real service.
17. Inappropriate Intimacy
Reduce tight coupling between classes by extracting shared behavior into a common component.
18. Alternative Classes with Different Interfaces
Unify similar functionality by renaming, moving methods, or introducing an abstract superclass.
19. Incomplete Library Class
Wrap or extend third‑party classes when they lack needed features.
20. Data Class
Encapsulate data and related behavior; avoid exposing public fields.
21. Refused Bequest
When a subclass uses only a few inherited members, replace inheritance with delegation or push down unused members.
22. Comments
Prefer self‑describing code over excessive comments; use comments only for complex business rules.
23. Bad Naming
Choose clear, expressive names for variables, methods, and classes.
24. Magic Numbers
Replace unexplained literals with named constants or enums.
25. Chaotic Layer Calls
Maintain proper layering (controller → service → DAO); avoid direct DAO calls from controllers.
References and acknowledgments are listed at the end of the original article.
Code Ape Tech Column
Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.