Smell Detail

Duplicate Code

重复代码

Dispensables

The same code structure appears repeatedly in multiple places.

Define

Introduction

Duplicate code is one of the most common code smells. When the same code appears in multiple places, any change must be made in several locations, making omissions likely and increasing maintenance cost.

Key Identifiers

  • Identical or very similar code fragments appear multiple times
  • Changes require synchronized edits across multiple places
  • Inconsistent modifications easily slip in
  • Increases the overall size of the codebase

Refactoring Suggestions

  1. Extract Method: Pull duplicated code into a single method
  2. Extract Class: Create a new class to hold related duplicated behavior
  3. Template Method Pattern: Extract the common structure of an algorithm
  4. Strategy Pattern: Handle similar logic that varies slightly

Explanation

The validation logic is duplicated in two methods and should be extracted into a single validation method. Then changes to the validation rules need to be made only once.

Code Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
class UserService {
private Database database;
public void createUser(String name, String email) {
// Input validation (duplicate code starts)
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException("Name cannot be empty");
}
if (email == null || email.isEmpty()) {
throw new IllegalArgumentException("Email cannot be empty");
}
if (!email.contains("@")) {
throw new IllegalArgumentException("Invalid email format");
}
if (name.length() < 2) {
throw new IllegalArgumentException("Name too short");
}
// Input validation (duplicate code ends)
User user = new User(name, email);
database.save(user);
}
public void updateUser(int id, String name, String email) {
// Input validation (duplicate code starts)
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException("Name cannot be empty");
}
if (email == null || email.isEmpty()) {
throw new IllegalArgumentException("Email cannot be empty");
}
if (!email.contains("@")) {
throw new IllegalArgumentException("Invalid email format");
}
if (name.length() < 2) {
throw new IllegalArgumentException("Name too short");
}
// Input validation (duplicate code ends)
User user = database.findById(id);
user.setName(name);
user.setEmail(email);
database.update(user);
}
}
// Supporting classes for demonstration
class User {
private String name;
private String email;
public User(String name, String email) {
this.name = name;
this.email = email;
}
public void setName(String name) { this.name = name; }
public void setEmail(String email) { this.email = email; }
public String getName() { return name; }
public String getEmail() { return email; }
}
class Database {
public void save(User user) { /* implementation */ }
public void update(User user) { /* implementation */ }
public User findById(int id) { return new User("", ""); }
}