Forced Compatibility
Descriptionβ
What does it look like?β
- New code directly calls legacy (outdated) interfaces
- The caller manually adapts to differences in API specifications, cluttering the logic
- Despite mismatched formats or behavior, the integration is forced for the sake of functionality
Why is it a problem?β
- The calling side takes on the responsibility of adapting/transforming the data, blurring design boundaries
- Any change in the API or specification ripples across many parts of the codebase
- Makes testing or replacing the dependency difficult
Bad Example of the Anti-patternβ
- TypeScript
- PHP
- Python
// γ¬γ¬γ·γΌAPIοΌζ§δ»ζ§οΌ
class LegacyPrinter {
printText(text: string) {
console.log(`*** ${text} ***`);
}
}
// ζ°γγγ³γΌγ
class ReportGenerator {
printSummary(text: string) {
const printer = new LegacyPrinter(); // β η΄ζ₯δΎεοΌγ€γ³γΏγΌγγ§γΌγΉδΈδΈθ΄οΌ
// η‘ηγγζ§APIγ«εγγγ
const legacyFormat = text.toUpperCase();
printer.printText(legacyFormat); // β γγΌγγ³γΌγγ£γ³γ°
}
}
<?php
// γ¬γ¬γ·γΌAPIοΌζ§δ»ζ§οΌ
class LegacyPrinter {
public function printText(string $text): void {
echo "*** {$text} ***\n";
}
}
// ζ°γγγ³γΌγοΌη‘ηγγζ₯ηΆοΌ
class ReportGenerator {
public function printSummary(string $text): void {
$printer = new LegacyPrinter(); // β ε€γγ―γ©γΉγη΄ζ₯δ½Ώγ£γ¦γγ
$legacyFormat = strtoupper($text); // β η‘ηγγδ»ζ§γ«εγγγ
$printer->printText($legacyFormat); // β γγΌγγ³γΌγγ£γ³γ°
}
}
// ε©η¨δΎ
$report = new ReportGenerator();
$report->printSummary("ζ欑γ¬γγΌγ");
# γ¬γ¬γ·γΌAPIοΌζ§δ»ζ§οΌ
class LegacyPrinter:
def print_text(self, text: str):
print(f"*** {text} ***")
# ζ°γγγ³γΌγοΌη‘ηγγζ₯ηΆοΌ
class ReportGenerator:
def print_summary(self, text: str):
printer = LegacyPrinter() # β η΄ζ₯δΎε
legacy_format = text.upper() # β η‘ηγγδ»ζ§γ«εγγγ
printer.print_text(legacy_format) # β ε€γγ€γ³γΏγΌγγ§γΌγΉγ«γγΏδΎε
# ε©η¨δΎ
report = ReportGenerator()
report.print_summary("ζ欑γ¬γγΌγ")
Issues:β
ReportGenerator
is tightly coupled toLegacyPrinter
βs method names and formatting- Interface mismatch is not abstracted; legacy and modern design philosophies are mixed
- Logic like converting text to uppercase is embedded in
ReportGenerator
, violating the SRP - Cannot easily switch to a new printer class or external printing API
- Cannot replace with a mock printer during testing
- As usage of
LegacyPrinter
increases, similar transformation logic is duplicated throughout the codebase - Any change to the legacy interface impacts all usage sites
Refactoring by Patternβ
Design patterns that can address thisβ
Pattern | Overview | Main Refactoring Approach |
---|---|---|
Adapter | Acts as a βbridgeβ to match interface differences | Adds a translation layer between old and new APIs |
Facade | Hides subsystem complexity and provides a clean entry point | Use when you want to simplify usage |
Proxy | Controls access to objects | Useful for access control, caching, or lazy calls |