저자는 delegated_type의 현재 구조가 몇 가지 도메인 모델링 문제를 내포하고 있다고 설명합니다. 가장 큰 문제점은 Message나 Comment와 같은 내부 타입이 Entry와 같은 외부 타입 없이는 독립적으로 존재할 수 없음에도 불구하고, 코드 상에서는 이러한 제약이 명확히 드러나지 않는다는 점입니다. 이는 개발자가 내부 타입을 독립적인 최상위 모델로 오인하게 만들 수 있습니다. 저자는 이러한 내부 타입들을 Entry::Message 및 Entry::Comment와 같이 외부 타입의 네임스페이스 내에 두어 실제 도메인 모델링을 반영해야 한다고 주장합니다. 그러나 현재 delegated_type은 이러한 네임스페이스를 사용할 경우 entry_comment와 같은 어색한 접두사 메서드를 생성하는 문제가 있습니다.
이에 대한 개선 방안으로 저자는 다음과 같은 제안을 합니다:
- 명시적 제약 조건 추가: 내부 타입이 외부 타입 없이는 존재할 수 없음을 명확히 하기 위해
has_one :entry, as: :entryable, touch: true, required: true와 같이required: true옵션을 추가하고,delegated_type에는inverse_of: :entry, dependent: :destroy를 수동으로 할당해야 한다고 제안합니다. - 네이밍 컨벤션 개선:
entryable과 같은-able접미사 사용에 대한 불만을 표하며, 이는 잘못된 네이밍의 신호라고 지적합니다. 대신delegate와 같이 기능의 본질을 더 잘 나타내는 이름을 사용할 것을 제안합니다. 예를 들어,delegated_type :delegate, types: %w[Message Comment], dependent: :destroy와 같이 변경할 수 있습니다. - 추상 부모 클래스 도입 및 네임스페이스 활용:
ActiveSupport::Concern모듈을 사용하는 대신, 내부 타입들이 상속받을 추상 부모 클래스인Entry::Delegate를 도입할 것을 제안합니다.Entry::Delegate는self.abstract_class = true를 설정하고has_one :entry, as: :delegate, touch: true, required: true를 포함하여,Message나Comment같은 내부 타입들이 이를 상속받도록 합니다. 이는Entry네임스페이스가 자신의 위임된 타입 정의를 소유하게 하여 불필요한 보일러플레이트를 줄이고, 애플리케이션 내의 여러delegated_type패턴에 일관성을 부여합니다. 또한,delegate_type컬럼 이름이delegate_type으로 명명되어 패턴의 일관성을 강화합니다. - 네임스페이스 지원 강화:
delegated_type이 각 타입에 대해 메서드를 생성할 때,Entry::Message와 같은 네임스페이스 접두사를 자동으로 제거하여 생성된 메서드 이름이 불필요한 접두사를 가지지 않도록 수정하는 방안을 제시합니다. 이를 통해app/models/entry디렉토리에서 위임된 타입들을 직접 찾을 수 있게 되어 코드 탐색이 용이해집니다. - 명칭 재고: 저자는
delegated_type이라는 이름이 기능의 핵심을 충분히 전달하지 못한다고 판단하여,composed_with_delegate와 같은 대안적인 명칭을 제안하며, 이는Entry가 내부의 가변적인 타입들과 구성된다는 점을 강조합니다. - 렌더링 개선:
Entry모델에render_in메서드를 정의하여render entry와 같이 호출할 때delegate타입에 따라_message.html.erb또는_comment.html.erb와 같은 적절한 부분 템플릿을 자동으로 렌더링하도록 개선하는 방안을 제시합니다. 이는 뷰 레이어에서delegated_type을 다루는 방식을 간소화합니다.