Exposed Complexity
Description
What does it look like?
- The caller manually executes a series of complex steps
- Multiple components are composed and coordinated every time they are used
- The overall intent is difficult to grasp due to scattered logic
Why is it a problem?
- The same complex logic tends to be repeated across the codebase
- When changes are needed, every usage site must be updated
- The caller takes on too much responsibility, breaking separation of concerns
Bad Example of the Anti-pattern
- TypeScript
- PHP
- Python
class AuthService {
authenticate(userId: string): boolean {
console.log(`ユーザー認証: ${userId}`);
return true;
}
}
class UserProfileService {
load(userId: string): object {
console.log(`プロフィール取得: ${userId}`);
return { name: "Hiroshi", id: userId };
}
}
class AuditService {
log(action: string) {
console.log(`[監査ログ] ${action}`);
}
}
// 呼び出し元が全部自分で処理を組み立てている
function showUserProfile(userId: string) {
const auth = new AuthService();
const profileService = new UserProfileService();
const audit = new AuditService();
if (auth.authenticate(userId)) {
const profile = profileService.load(userId);
console.log(profile);
audit.log("プロフィール表示");
}
}
<?php
class AuthService {
public function authenticate(string $userId): bool {
echo "ユーザー認証: {$userId}\n";
return true;
}
}
class UserProfileService {
public function load(string $userId): array {
echo "プロフィール取得: {$userId}\n";
return ["name" => "Hiroshi", "id" => $userId];
}
}
class AuditService {
public function log(string $action): void {
echo "[監査ログ] {$action}\n";
}
}
// 呼び出し元がすべて処理を組み立てている
function showUserProfile(string $userId): void {
$auth = new AuthService();
$profileService = new UserProfileService();
$audit = new AuditService();
if ($auth->authenticate($userId)) {
$profile = $profileService->load($userId);
print_r($profile);
$audit->log("プロフィール表示");
}
}
// 実行
showUserProfile("user-123");
class AuthService:
def authenticate(self, user_id: str) -> bool:
print(f"ユーザー認証: {user_id}")
return True
class UserProfileService:
def load(self, user_id: str) -> dict:
print(f"プロフィール取得: {user_id}")
return {"name": "Hiroshi", "id": user_id}
class AuditService:
def log(self, action: str):
print(f"[監査ログ] {action}")
# 呼び出し元がすべて処理を組み立てている
def show_user_profile(user_id: str):
auth = AuthService()
profile_service = UserProfileService()
audit = AuditService()
if auth.authenticate(user_id):
profile = profile_service.load(user_id)
print(profile)
audit.log("プロフィール表示")
# 実行
show_user_profile("user-123")
Issues:
- The caller manually coordinates three components — exposing a complex workflow
- Authentication, data fetching, and audit logging are all handled by the caller
- If similar logic is needed elsewhere, code duplication and complexity grow
Refactoring by Pattern
Design patterns that can address this
Pattern | Overview | Main Refactoring Approach |
---|---|---|
Facade | Provide a unified interface to a complex system | Simplifies and unifies the process invocation |
Proxy | Intermediates access to add or control behavior | Useful for caching, access control, or lazy initialization |
Iterator | Encapsulates traversal logic over a collection | Abstracts and standardizes iteration over complex data |