트레이트 – 02.수평적 재사용

PHP의 수평적 재사용(Horizontal Reuse)

클래스 계층 구조로부터 독립적으로 행위(behavior)를 재사용하는 수평적 방법의 주요 동기는 명확한 개념적 배경과 최적의 코드 재사용을 동시에 사용하여 클래스 및 클래스 계층을 모델링 할 수 있는 더 넓은 기회를 제공하는 것입니다. 또한, 다른 접근 방식과의 주요 차이점은 복잡한 재사용 시나리오에서 인터페이스가 겹쳐지면서 발생하는 충돌을 명시적으로 방지한다는 것입니다.

수평적 재사용이 필요한 이유

코드 재사용은 객체 지향 언어가 상속을 통해 달성하려는 주요 목표 중 하나입니다. 불행히도 종종 개발자로 하여금 코드 재사용 또는 개념적인 클린 클래스 계층 구조(clean class hierarchy)을 위해서는 단일 상속을 사용해야 한다는 결정을 내리도록 강요합니다. 코드 재사용을 달성하기 위해서는 메소드를 복제하거나 클래스 계층 구조의 루트 근처로 이동해야 하지만, 이로 인해 코드의 이해 가능성(understandability)과 유지 보수성(maintainability)이 저하됩니다.

코드 재사용은 객체 지향 언어가 상속을 통해 달성하려는 주요 목표 중 하나입니다. 불행히도 종종 개발자로 하여금 코드 재사용 또는 개념적인 클린 클래스 계층 구조(clean class hierarchy)을 위해서는 단일 상속을 사용해야 한다는 결정을 내리도록 강요합니다. 코드 재사용을 달성하기 위해서는 메소드를 복제하거나 클래스 계층 구조의 루트 근처로 이동해야 하지만, 이로 인해 코드의 이해 가능성(understandability)과 유지 보수성(maintainability)이 저하됩니다.

이 문제를 피하기 위해 다중 상속(multiple inheritance)과 믹스인(Mixin)이 발명되었습니다. 그러나 둘 다 복잡하고 이해하기 어렵습니다. PHP 5는 명확하고 성공적인 Java 모델을 염두에 두고 명시적(explicitly)으로 설계되었습니다. 단일 상속이지만 다중 인터페이스입니다. 이 결정은 C++의 예와 같이 알려진 문제를 피하기 위해 취해졌습니다. 제시된 접근 방식은 이러한 문제를 피하고 디자이너가 코드 재사용이나 복잡성 문제를 고려할 필요 없이 개념적으로 클린 클래스 계층 구조(clean class hierarchy)을 구축 할 수 있도록 설계되었지만, 우선 실제 문제 영역과 유지 보수성(maintainability)에 초점을 맞추고 있습니다.

다중 상속의 경우, 상속 받은 여러 기반 클래스에 같은 이름의 멤버가 존재할 가능성과 하나의 클래스를 간접적으로 두 번 이상 상속 받을 가능성이 있는 등 클래스들의 상속 관계가 모호해질 수 있습니다. 이와 같이 클래스들의 상속 관계의 모호성을 제거함으로 상속 관계가 명확한 계층 구조, 즉 클린 클래스 계층 구조(clean class hierarchy)를 얻을 수 있습니다.

다중 상속에서의 상속 관계 모호성

단일 상속 언어에서 재사용에 대한 한계

다중 상속을 지원하지 않는 PHP에서 재사용과 관련된 몇 가지 문제가 있습니다. 가능한 많이 재사용하려면 상속 계층 구조에서 메소드를 가능한 높게 이동해야 합니다. 이 시점에서 클래스는 필요하지 않은 메소드를 갖기 시작하기 때문에 개념적 일관성(conceptual consistency)과 재사용(reuse) 간에 절충점을 찾게 됩니다. 따라서 클래스 모델의 이해 가능성(understandability)으로 인해 개념적 일관성이 더 중요하다고 판단되면 코드 중복을 감수하거나 위임(delegation) 같은 일을 해야 합니다. 이러한 일들은 클래스 트리에서 구현된 메소드 만큼이나 항상 좋은 선택은 아닙니다.

(참고) 위임(delegation) – 위임이란 ‘어떤 메소드의 처리를 다른 인스턴스의 메소드에 맡긴다’는 의미입니다. 자신과 다른 클래스 사이에 연관 관계가 크지 않으면 상속(inheritance) 시키지 않고 다른 클래스의 메소드를 불러다가 자신의 메소드를 처리합니다. 즉 자신이 처리해야 할 일을 다른 객체에서 대신 처리 해주는 행위임으로, 처리해야 할 일을 다른 객체에게 위임하는 행위입니다.

위임에 의한 코드 재사용

개념적 문제 외에도 수정할 수 없거나 수정을 원치 않는 제 3자 코드(third-party code)에 대한 문제가 있습니다. 다음 코드는 문서 주석 블록에 대한 상세한 액세스를 제공하는 PHP 리플렉션 API의 확장 버전의 구현을 보여줍니다. ReflectionMethod 및 ReflectionFunction은 리플렉션 API의 클래스이며 정확히 동일한 코드로 확장되어야 합니다. 이 경우 리플렉션 API 클래스 자체는 언어의 일부로서 C로 구현되어 있어 개발자가 임의로 변경할 수 없습니다.

따라서 결국, 원래의 확장 클래스를 확장하는 두 클래스 모두에서 많은 중복 코드를 갖게 됩니다.

트레이트에 의한 코드 재사용

트레이트는 단일 상속 언어에서의 코드 재사용에 대한 한계를 극복하고자 설계되었습니다.

트레이트에 의한 코드 재사용

트레이트와 위임은 부모와 자식 간의 상속이라는 수직적 관계가 아닌 수평적 관계를 보여줍니다. 그러나 PHP의 트레이트가 컴파일 시간에 처리되는 반면에 위임은 런타임 시간에 동적으로 이루어집니다.

답글 남기기