상속보다 조합(Composition Over Inheritance) 적용하기
빠른 시작
- 변화의 축 식별: 데이터 변형, 알고리즘, 횡단 관심사, 또는 프레임워크 제약.
- 기본적으로 조합을 선택하되, 상속은 치환 가능성(substitutability)과 안정성(stability)이 명확히 입증되는 경우에만 사용.
- 변형 집합이 닫혀 있고(closed) 데이터 형태라면, 개방형 상속보다 ADT/봉인된(sealed) 타입을 선호.
- 테스트, 롤아웃 순서, 리뷰 체크포인트가 포함된 구체적인 마이그레이션 계획을 수립.
참조 라우팅 (점진적 공개)
현재 작업에 필요한 파일만 읽으세요:
- 기초 및 메커니즘 선택 → references/01-foundations-and-decision-making.md
- ADT, 조합 패턴, 프론트엔드 조합 → references/02-adts-patterns-and-frontend-composition.md
- 단계별 마이그레이션 및 코드 리뷰 체크리스트 → references/03-refactoring-and-review-checklist.md
- CI 메트릭, 커스텀 정적 검사, 팀 채택 → references/04-metrics-and-adoption.md
기본 워크플로우
-
현재 모델 평가
- 베이스 클래스, 서브클래스 개수, 계층 깊이, 알려진 문제점을 나열합니다.
- 각 변형을 데이터 변형, 행동 전략, 인프라 관심사 중 하나로 표시합니다.
-
메커니즘 선택 (기본 우선)
- 행동 변화, 런타임 교체, 다축 변경에는 조합을 선택합니다.
- 닫혀 있고 데이터를 포함하는 변형에 대해 완전한 처리가 필요한 경우 ADT/봉인된 타입을 선택합니다.
- 다음 조건을 모두 만족할 때만 상속을 선택합니다: 진정한 is-a 관계, 리스코프 치환 원칙을 준수하는 치환 가능성, 안정적인 계층 구조.
-
대상 설계
- 최소한의 협력자 계약을 정의합니다. 변동성, 다중 구현, 독립적인 테스트가 필요한 경우 인터페이스/프로토콜을 도입합니다.
- 필수 협력자에 대해서는 생성자 주입을 사용합니다.
- 상속 깊이를 얕게 유지합니다 (목표: 피할 수 없는 프레임워크 베이스 아래로 ≤2).
-
점진적으로 마이그레이션 계획
- 먼저 특성화(characterization) 테스트를 추가합니다.
- 내부를 교체하기 전에 이음새(seam, 인터페이스/퍼사드)를 도입합니다.
- 한 번에 하나의 서브클래스 경로씩 마이그레이션합니다.
- 동등성 검사가 통과된 후에만 죽은 계층 조각을 제거합니다.
-
검증 및 가드레일 설정
- 체크리스트 기반 리뷰를 실행합니다.
- DIT, 재정의 비율, 데코레이터 깊이에 대한 CI 메트릭/검사를 추가합니다.
- 프레임워크에서 요구하는 상속에 대해서는 명시적 면제(waiver)를 기록합니다.
불가침 기본값 (Non-negotiable defaults)
- 기본적으로 조합을 우선합니다.
- 코드 재사용만을 위해 상속을 도입하지 마십시오.
- 협력자 인터페이스는 좁게 유지하십시오.
- 서비스 로케이터 패턴을 피하십시오. 의존성은 명시적이어야 합니다.
- 깊은 데코레이터 스택(>3)과 넓은 상속 트리는 설계 냄새로 간주합니다.
출력 계약
지침을 요청받으면 다음 섹션을 순서대로 반환하십시오:
- 결정: 조합, ADT, 또는 상속.
- 이유: 결합도, 변경 축, 런타임 요구사항, 테스트 용이성 관련 영향.
- 설계 스케치: 대상 인터페이스/타입 및 조합 루트.
- 마이그레이션 단계: 검증 지점이 포함된 작고 되돌릴 수 있는 단계들.
- 리뷰/CI 검사: 체크리스트 항목 및 측정 가능한 임계값.
엣지 케이스
- 프레임워크에서 강제하는 상속: 경계에서 상속을 유지하고 내부는 조합을 사용하십시오.
- 언어에 위임(delegation)을 위한 문법 설탕이 부족한 경우: 전달(forwarding)을 위해 작은 헬퍼 생성기/템플릿을 사용하십시오.
- 성능이 중요한 경로: 간접 참조(indirection)를 추가하기 전에 디스패치 오버헤드를 측정하십시오.
- 작고 안정적인 도메인: 완전한 처리(exhaustiveness)가 필요할 때는 봉인된 상속이 허용될 수 있습니다.
예시
입력: "BaseReport에 12개의 서브클래스가 있고 새로운 형식이 추가될 때마다 서브클래스가 하나 더 늘어납니다. 어떻게 해야 할까요?"
출력 (형태):
- 결정: 계층 구조를 조합(Strategy + 선택적 Decorator)으로 대체.
- 이유: 다축 변형과 재정의가 많은 서브클래스는 분류 체계의 표류(taxonomy drift)를 나타냄.
- 설계 스케치:
ReportRenderer,HeaderPolicy,FooterPolicy,OutputFormatter인터페이스를 하나의ReportService에서 조합. - 마이그레이션: 특성화 테스트 → 전략 추출 → 서브클래스별 마이그레이션 → 서브클래스 삭제.
- 가드레일: DIT 경고 >3, 재정의 비율 경고 >0.5, 데코레이터 깊이 경고 >3.