Hardcoded Variability
Description
What does it look like?
- The variable part of the logic is hardcoded directly and not separated from the fixed part
- “Slightly different” behaviors are mixed into a common flow, making reuse difficult
- Even though the overall flow is the same, the entire logic is duplicated for small differences
Why is it a problem?
- Without clear separation between shared and differing parts, changes are hard to make
- Similar but slightly different code grows, increasing the risk of bugs and maintenance overhead
- The code lacks flexibility, making feature extension and switching difficult
Bad Example of the Anti-pattern
- TypeScript
- PHP
- Python
class NotificationService {
sendEmail(user: string, message: string) {
console.log(`件名: お知らせ`);
console.log(`本文: ${message}`);
console.log(`宛先: ${user}@example.com`);
}
sendSlack(user: string, message: string) {
console.log(`Slack宛: ${user}`);
console.log(`内容: ${message}`);
}
}
<?php
class NotificationService {
public function sendEmail(string $user, string $message): void {
echo "件名: お知らせ\n";
echo "本文: {$message}\n";
echo "宛先: {$user}@example.com\n";
}
public function sendSlack(string $user, string $message): void {
echo "Slack宛: {$user}\n";
echo "内容: {$message}\n";
}
}
// 利用例
$notifier = new NotificationService();
$notifier->sendEmail("hiroshi", "メッセージ1");
$notifier->sendSlack("hiroshi", "メッセージ2");
class NotificationService:
def send_email(self, user: str, message: str):
print("件名: お知らせ")
print(f"本文: {message}")
print(f"宛先: {user}@example.com")
def send_slack(self, user: str, message: str):
print(f"Slack宛: {user}")
print(f"内容: {message}")
# 利用例
notifier = NotificationService()
notifier.send_email("hiroshi", "メッセージ1")
notifier.send_slack("hiroshi", "メッセージ2")
Issues:
- Email and Slack notifications mix shared structure with their differences
- Every time a new channel (e.g., LINE, SMS) is added, similar methods are created again
- The shared logic becomes cluttered, resulting in poor testability and maintainability
Refactoring by Pattern
Design patterns that can address this
Pattern | Overview | Main Refactoring Approach |
---|---|---|
Template Method | Standardize the flow and define differences in subclasses | Prevent duplication and improve reusability |
Strategy | Allow behavior to be swapped | Easier to replace and test |
Bridge | Separate abstraction from implementation | Clarify axes of change and enable flexibility |
Flyweight | Share common state to reduce object count | Minimize redundant data |
Prototype | Clone instances from a template | Reuse initialization and generate variations efficiently |