Duplicated Logic
Description
What does it look like?
- Similar logic is copy-pasted in multiple places
- Slight variations are manually modified after duplicating a base implementation
- Although it may look readable, maintainability and consistency are compromised
Why is it a problem?
- When changes are needed, every copy must be found and updated
- If even one is missed, it can lead to bugs
- Increases the effort for testing and code reviews, reducing overall reliability
Bad Example of the Anti-pattern
- TypeScript
- PHP
- Python
class PdfExporter {
export(data: string) {
console.log("開始ログ");
console.log(`PDF出力: ${data}`);
console.log("完了ログ");
}
}
class CsvExporter {
export(data: string) {
console.log("開始ログ");
console.log(`CSV出力: ${data}`);
console.log("完了ログ");
}
}
class XmlExporter {
export(data: string) {
console.log("開始ログ");
console.log(`XML出力: ${data}`);
console.log("完了ログ");
}
}
<?php
class PdfExporter {
public function export(string $data): void {
echo "開始ログ\n";
echo "PDF出力: {$data}\n";
echo "完了ログ\n";
}
}
class CsvExporter {
public function export(string $data): void {
echo "開始ログ\n";
echo "CSV出力: {$data}\n";
echo "完了ログ\n";
}
}
class XmlExporter {
public function export(string $data): void {
echo "開始ログ\n";
echo "XML出力: {$data}\n";
echo "完了ログ\n";
}
}
class PdfExporter:
def export(self, data: str):
print("開始ログ")
print(f"PDF出力: {data}")
print("完了ログ")
class CsvExporter:
def export(self, data: str):
print("開始ログ")
print(f"CSV出力: {data}")
print("完了ログ")
class XmlExporter:
def export(self, data: str):
print("開始ログ")
print(f"XML出力: {data}")
print("完了ログ")
Issues:
- All exporters repeat the same start and finish logging
- The only variation is the output logic, yet the full structure is rewritten every time
- Any change to logging or formatting must be reflected across all exporters
Refactoring by Pattern
Design patterns that can address this
Pattern | Overview | Main Refactoring Approach |
---|---|---|
Template Method | Standardize flow and define only differences in subclasses | Centralize the “template” of processing |
Strategy | Inject the varying behavior externally | Enable dynamic swapping of logic |
Decorator | Wrap and add or override functionality | Stack reusable enhancements around core behavior |
Visitor | Separate logic from data structure | Externalize logic to support multiple output formats |
Prototype | Clone instances from a template | Replace manual rewriting with instance duplication |