Skip to main content

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

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("プロフィール表示");
}
}

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

PatternOverviewMain Refactoring Approach
FacadeProvide a unified interface to a complex systemSimplifies and unifies the process invocation
ProxyIntermediates access to add or control behaviorUseful for caching, access control, or lazy initialization
IteratorEncapsulates traversal logic over a collectionAbstracts and standardizes iteration over complex data