Duplication Removal Via Extraction
by @quochungto
Remove duplicated code across methods and classes by extracting small shared utilities first and letting larger structure (superclass, Template Method) emerg...
Example 1: LoginCommand + AddEmployeeCmd β Command Superclass
Situation: Two Java command classes both contain the repeated pair outputStream.write(field.getBytes()); outputStream.write(0x00); for every string field they write. Both classes write header, command char, fields, footer β same structure, different fields.
Step 2 β Smallest fragment: The two-line write-and-terminate pair. Name: writeField(OutputStream, String).
Step 3 β Extract locally in LoginCommand:
private void writeField(OutputStream outputStream, String field) throws Exception {
outputStream.write(field.getBytes());
outputStream.write(0x00);
}
Replace all write/0x00 pairs in LoginCommand.write() with writeField(...) calls. Tests pass.Step 4 β Replicate in AddEmployeeCmd: Same method, identical signature. Replace its pairs. Tests pass.
Step 5 β Introduce superclass: Create abstract Command class. Both classes extend it. Tests pass.
Step 6 β Pull up: Move writeField to Command. Delete local copies. Tests pass.
Step 8 β Emergence: After writeField is shared, both write() methods are structurally identical: header β size β commandChar β writeBody() β footer. Extract writeBody() as abstract. Pull write() to Command. Pull shared constants (header, footer, SIZE_LENGTH). The subclasses reduce to constructor + writeBody() + getCommandChar().
Final state: Command holds all protocol logic. Adding a new command is one subclass, no copy-paste.
Example 2: Two Validators with Repeated Null-Check Pattern
Situation: UserValidator and OrderValidator both open with:
if (input == null) {
throw new IllegalArgumentException("input must not be null");
}
The guard is identical across both classes and three other validators as well.Step 2 β Smallest fragment: The three-line null guard. Candidate name: requireNonNull(Object, String).
Steps 3β4: Extract to local method in UserValidator, replicate in OrderValidator. Tests pass in both.
Step 5: Check β do the validators share a parent? If they all extend a BaseValidator, pull up there. If not, decide: introduce AbstractValidator or extract to a shared utility class (ValidationUtils.requireNonNull). Choose based on whether validators truly share an identity or are only incidentally similar.
Step 8 β Observe: After the guard is shared, look at whether the remaining validation logic also shares structure. If all validators do: guard β validate fields β aggregate errors β return result, Template Method is emerging. Extract validateFields() as abstract and pull the outer structure up.
Example 3: Coincidental Similarity β Do NOT Extract
Situation: FilePermissionChecker and DatabaseConnectionPool each contain:
if (count < 0) {
throw new IllegalArgumentException("count must be non-negative");
}
Analysis: FilePermissionChecker checks the number of retries. DatabaseConnectionPool checks the pool minimum size. These are semantically unrelated. The two classes have nothing in common β no shared parent makes sense, no shared utility class is appropriate.
Decision: do not extract. The similarity is coincidental. If the retry validation rule changes (e.g., to allow 0 retries), you would change FilePermissionChecker but not DatabaseConnectionPool. Coupling them would create false dependencies and make both harder to change.
The test: "If one copy needed to change, would the other need to change too?" Answer here: no. Leave them independent.
clawhub install bookforge-duplication-removal-via-extraction