EJ2E Item 16. 상속보다 컴포지션을 선호하라

참조: Effective Java 2nd Edition Item 16: Favor composition over inheritence

상속
– 상속은 코드 재사용을 하는 강력한 방법이지만 항상 최선의 방법은 아니다. 무분별하게 사용했다가는 연약한 소프트웨어가 된다.

– 상속은 동일한 패키지 내에서 하위 클래스와 상위 클래스 구현을 같은 프로그래머가 관리할 때 안전하다. 또한 상속은 상속하려는 클래스가 확장을 고려해서 설계되었고 문서화 되어 있을 때 안전하다.

– 이 책에서 말하는 상속은 구현체 간의 상속이지 인터페이스 상속을 말하는 건 아니다.

– 메소드 호출과 달리 상속은 캡슐활르 위반한다. 즉 하위 클래스가 상위 클래스의 구현에 의존한다.  상위 클래스의 구현 내용이 배포를 거듭하면서 바뀔 수 있는데.. 이로 인해 하위 클래스 코드는 건드리지도 않았는데 깨질 수가 있다.

– 오직 “is-a” 관계가 성립할 때만 적당하다. 자바 플랫폼에서 이를 위반 한 사례: Stack이 Vector를 상속받았다. Properties가 Hashtable을 상속 받았다.

컴포지션
– 컴포지션을 사용하면 앞서 말한 문제(깨지기 쉬운 코드, 상위 클래스에 새로운 메소드 추가 필요)를 해결할 수 있다.

– 포워딩(흔히 역할 위임이라고 일컫는 작업을 나타내는 듯)을 한다.

– 구현의 구체적인 내용과는 의존성이 없다.

– 래퍼(wrapper) 클래스와 데코레이터 패턴

– 래퍼 클래스 단점: 래퍼 클래스는 콜백 프레임워크에서 사용하기 적당하지 않다. 래퍼 클래스로 감싼 객체는 자기가 누구한테 감싸였는지 모르기 때문에 itself(this) 형태로 호출해도 래퍼는 무시된다. (만약 상속이었다면? 다형성 때문에 결국 상위 클래스를 상속받은 하위 클래스의 객체가 넘어갔겠지만..) => SELF problem

SWF Chapter 1

참조: 스프링 웹 플로우 레퍼런스 1 장

1. 소개

1.1 이 가이드가 다루고 있는 것

이 가이드는 스프링 웹 플로우와 관련된 모든 것을 다룬다. 최종-사용자 애플리케이션의 플로우를 구현하는 방법과 기능 들을 사용하는 방법을 다룬다. 또한 프레임워크를 확장하는 방법과 전체적인 아키텍처 모델도 다룬다.

1.2. 웹 플로우를 실행할 때 필요로 하는 것

자바 1.4 이상

스프링 2.5.4 이상

1.3 지원을 받을 수 있는 곳

생략

1.4. 개발을 주도 할 수 있는 곳

생략

1.5. 웹 플로우 구성 요소를 스프링소스 번들 저장소에서 얻는 방법

각각의 웹 플로우 배포판의 jar 파일들은 스프링소스 엔터프라이즈 번들 저장소에서 얻을 수 있다. 이 jar 파일들에 메이븐이나 Ivy 의존성 관리자를 사용하여 접근할 수 있다.

1.5.1. 메이븐으로 웹 플로우에 접근하기

메이븐을 사용하여 jar에 접근 하려면 다음 저장소를 메이븐 pom에 추가하라.

<repository>
    <id>com.springsource.repository.bundles.release</id>
    <name>SpringSource Enterprise Bundle Repository – SpringSource Releases</name>
    <url>http://repository.springsource.com/maven/bundles/release</url>
</repository>

<repository>
    <id>com.springsource.repository.bundles.external</id>
    <name>SpringSource Enterprise Bundle Repository – External Releases</name>
    <url>http://repository.springsource.com/maven/bundles/external</url>
</repository>
           

그런 다음 다음의 의존성을 추가하라.

<dependency>
    <groupId>org.springframework.webflow</groupId>
    <artifactId>org.springframework.binding</artifactId>
    <version>2.0.5.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework.webflow</groupId>
    <artifactId>org.springframework.js</artifactId>
    <version>2.0.5.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework.webflow</groupId>
    <artifactId>org.springframework.webflow</artifactId>
    <version>2.0.5.RELEASE</version>
</dependency>

       
그리고 만약 JSF(JavaServerFaces)를 사용하고 있다면 다음을 추가하라.

<dependency>
    <groupId>org.springframework.webflow</groupId>
    <artifactId>org.springframework.faces</artifactId>
    <version>2.0.5.RELEASE</version>
</dependency>

          
1.5.2. Ivy로 웹 플로우에 접근하기

Ivy를 사용하여 jar 파일에 접근하려면, 다음 저장소를 Ivy 설정에 추가하라.

<url name=”com.springsource.repository.bundles.release”>
    <ivy pattern=”http://repository.springsource.com/ivy/bundles/release/
                  [organisation]/[module]/[revision]/[artifact]-[revision].[ext]” />
    <artifact pattern=”http://repository.springsource.com/ivy/bundles/release/
                       [organisation]/[module]/[revision]/[artifact]-[revision].[ext]” />
</url>

<url name=”com.springsource.repository.bundles.external”>
    <ivy pattern=”http://repository.springsource.com/ivy/bundles/external/
                  [organisation]/[module]/[revision]/[artifact]-[revision].[ext]” />
    <artifact pattern=”http://repository.springsource.com/ivy/bundles/external/
                       [organisation]/[module]/[revision]/[artifact]-[revision].[ext]” />
</url>
           

그런 다음 다음 의존성을 선언하라.

<dependency org=”org.springframework.webflow” name=”org.springframework.binding”
            rev=”2.0.5.RELEASE” conf=”compile->runtime” />
<dependency org=”org.springframework.webflow” name=”org.springframework.js”
            rev=”2.0.5.RELEASE” conf=”compile->runtime” />
<dependency org=”org.springframework.webflow” name=”org.springframework.webflow”
            rev=”2.0.5.RELEASE” conf=”compile->runtime” />

           

그리고 만약 JSF를 사용한다면 다음을 추가하라.

<dependency org=”org.springframework.webflow” name=”org.springframework.faces”
            rev=”2.0.5.RELEASE” conf=”compile->runtime” />

           
1.6. 메이븐 중앙 저장소에서 웹 플로우 구성 요소 얻는 방법

웹 플로우 배포판의 모든 jar 파일은 메이븐 중앙 저장소에서도 접근할 수 있다.

메이븐 중앙 저장소에 있는 웹 플로우 jar에 접근하려면 다음 의존성을 pom에 추가하라.

<dependency>
    <groupId>org.springframework.webflow</groupId>
    <artifactId>org.springframework.binding</artifactId>
    <version>2.0.5.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework.webflow</groupId>
    <artifactId>org.springframework.js</artifactId>
    <version>2.0.5.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework.webflow</groupId>
    <artifactId>org.springframework.webflow</artifactId>
    <version>2.0.5.RELEASE</version>
</dependency>

       
만약 JSF를 사용한다면 다음을 추가하라.

<dependency>
    <groupId>org.springframework.webflow</groupId>
    <artifactId>org.springframework.faces</artifactId>
    <version>2.0.5.RELEASE</version>
</dependency>

       
1.7. 나이틀리 빌드 얻는 방법

나이틀리 스냅샷 버전의 웹 플로우 트렁크는 스프링 소스 번들 저장소에서 이용할 수 있다. 스냅샷에 접근하려면 다음 저장소를 pom에 추가하라.

<repository>
    <id>com.springsource.repository.bundles.snapshot</id>
    <name>SpringSource Enterprise Bundle Repository – Nightly Snapshots</name>
    <url>http://repository.springsource.com/maven/bundles/snapshot</url>
</repository>
       
그리고 다음 의존성을 선언하라.

<dependency>
    <groupId>org.springframework.webflow</groupId>
    <artifactId>org.springframework.binding</artifactId>
    <version>3.0.0.CI-###</version>
</dependency>

<dependency>
    <groupId>org.springframework.webflow</groupId>
    <artifactId>org.springframework.js</artifactId>
    <version>3.0.0.CI-###</version>
</dependency>

<dependency>
    <groupId>org.springframework.webflow</groupId>
    <artifactId>org.springframework.webflow</artifactId>
    <version>3.0.0.CI-###</version>
</dependency>

           
그리고 만약 JSF를 사용한다면 다음을 추가하라.

<dependency>
    <groupId>org.springframework.webflow</groupId>
    <artifactId>org.springframework.faces</artifactId>
    <version>3.0.0.CI-###</version>
</dependency>

       
위에서 ‘# # #’은 3.0.0.CI-500 같은 빌드 넘버를 나타낸 것이다. 최근 빌드 넘버를 알고 싶다면 나이틀리 빌드 영역을 참조하라.