Whiteship's Note


[AspectJ] Extension and Implementation

AOP : 2009.06.08 20:16


http://www.eclipse.org/aspectj/doc/released/progguide/semantics-declare.html#extension-and-implementation

    declare parents: EmpDao extends GenericDao<Emp, EmpParams>;
    declare parents: EmpDaoImpl extends HibernateGenericDao<Emp, EmpParams>;
    declare @type: EmpDaoImpl: @org.springframework.stereotype.Repository;

EmpDao 클래스가 GenericDao 클래스를 상속 받도록 설정.
EmpDaoImpl 클래스가 HibernateGenericDao 클래스를 상속 받도록 설정.
EmpDaoImpl 클래스에 @Repository 애노테이션 추가.

문법이 복잡해 보였는데 막상 사용해보니 간단 간단 하네요.

public interface EmpDao {

}

public class EmpDaoImpl implements EmpDao {

}

이런 기초적인 코드만 존재하지만..

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"/applicationContext.xml", "/applicationContext-datasource.xml"})
@Transactional
public class EmpDaoImplTest {

    @Autowired
    EmpDaoImpl daoImpl;

    @Test
    public void daoInterface() throws Exception {
        assertNotNull(daoImpl);
        daoImpl = new EmpDaoImpl();
        GenericDao<Emp, EmpParams> gdao = daoImpl;
        HibernateGenericDao<Emp, EmpParams> hgdao = daoImpl;
    }

    @Test
    public void crud() throws Exception {
        Emp emp = new Emp();
        daoImpl.add(emp);
        daoImpl.flush();
        assertEquals(1, daoImpl.getAll().size());
    }

}

이런 테스트를 돌릴 수 있다는거...



top

Write a comment.


EJ2E Item 20. 태그가 있는 클래스 대신 클래스 계층구조를 선호하라.

Java : 2009.03.13 20:09


참조: Effective Java 2nd Edition. Prefer class hierarchies to tageed classes

사용자 삽입 이미지

위와 같은 클래스의 단점:
- enum, switch 문, 태그 필드로 인해 지져분하다.
- 여러 구현체를 하나의 클래스로 합쳐놓았기 때문에 가독성이 떨어진다.
- 불필요한 필드까지 가지고 인스턴스를 만들어야 하기 떄문에 메모리 풋프린트가 증가한다.
- 생성자에서 불필요한 필드까지 초기화하지 않는 이상 필드를 final로 선언할 수 없다.
- 생성자에서 초기화를 잘못했을 때 컴파일 시점에 이것을 알 수 없다.
- 새로운 종류를 추가했을 때 switch문에 case를 추가해야 한다는 것을 기억해야 한다. 안그러면 런타임 에러가 발생한다.
- 인스턴스 데이터 타입이 실제 타입을 알려주지 못한다.
=> 즉 장황하고, 에러가 발생할 여지가 많고, 비효율적이다.

먼저 추상 클래스를 만들어서 일반적인 것들을 이 클래스로 이동시키고,
구체적인 하위 클래스를 정의한다.
해당 하위 클래스에서 추상 매서드를 구현한다.

사용자 삽입 이미지

이렇게 구성하면
- 깨끗하고 간단하다.
- 특정 타입에 관련된 속성은 해다 클래스가 가지게 된다. 따라서 불필요한 필드가 없다.
- 모든 필드를 final로 선언할 수 있다.
- 컴파일 시점에 생성자에서 데이터 필드를 초기화 하는지, 추상 매서드를 구현했는지 확인할 수 있다.

top

Write a comment.


상속에 대하여...

Java : 2006.11.20 11:07


Agile Java 스터디에서 상속에 대한 논의가 시작되었습니다. 논의는 처음 상속이 필요한가? 아니면 지양해야 하는가? 이렇게 시작을 하려했지만 이미 그러한 논의는 옛날 부터 있었던 것이고 Object-Based가 아닌 Object-Oriented에서는 상속이 특징으로 꼽히기 때문에 굳이 유용한 기능을 지양할 필요는 없다고 생각합니다. API에서도 이미 상속을 사용하여 많은 클래스들을 구현해 놓았고 다형성은 어떻게 할 것이며 제네릭 같은 템플릿은 상속이 없으면 과연 존재 의미가 있기나 한건지 생각하게 됩니다. 아 다시 생각해보니 제네릭과 상속은 별 상관이 없겠네요. 콜렉션의 타입을 제약하는 기능을 하는거기 때문에 하지만 역시 다형성을 사용못한다는 건 큰 손실이라고 생각이 됩니다.

Situation

그래서 인지 아닌지 논의의 초점은 바뀌었습니다. Abstract 클래스만을 상속하도록 제한되어야 하는가? 아니면 어떤 클래스든 상속을 자유롭게 사용해야 하는가?로  바뀌었습니다. 이 둘중에 어느 한쪽 만을 굳이 선택해야 한다면 전 자유로운 상속을 택하겠습니다. 둘의 가장 큰 차이는 상위 타입의 객체를 만들 수 있느냐 없느냐인 것 같은데 물론 경우에 따라서 상위 타입의 객체 생성을 자제 해야하는 경우도 있겠지만 Abstract 클래스만 상속하도록 제한한다면 개발이 형식에 얽매여서 필요없는 일까지 하게될 상황이 발생하게 될 수 있다는 생각을 해봅니다.

Abstact 클래스만 상속하도록 바껴야 한다. 라는 규율? 규칙이 있는 환경에서 개발을 한다고 생각해보면 다음과 같은 클래스 구조가 생길 것입니다.
어디선가는 객체를 써야 하기 때문에 결국 클래스를 만들게 되겠지요. 이렇게 시스템을 만들어 둔 상태에서 새로운 요구사항이 생겨서 정삼각형, 직각 삼각형 등을 추가하게 됐다면 어떻게 고쳐야 할까요?

상속을 자유롭게 사용하자

당연히 이렇게 되어야 한다고 생각합니다. 기존에 Triangle 객체를 사용하던 사람들도 여전히 사용할 수 있고 새로 추가된 RegularTriangle과 RightTriangle 객체도 사용할 수 있게됐으니 말이죠.

Abstract 클래스만 상속해야 한다.

하지만 Abstract 클래스만 상속 받아야 한다면 어떻게 해야할까요?
이렇게 하지 않을까요? 이렇게 하면 기존의 Triangle에 있던 멤버들과 중복이 발생하게 되는 것 아닐까요? 아니면 다음과 같이 기존의 Triangle 클래스를 Abstract로 바꿀수도 있습니다.(주로 성일이형이 말씀하시던게 바로 이 그림이 아닐런지 생각해 봅니다.)
이렇게 되면 Triangle에 있는 자원을 재사용 할 수 있게 되어 괜찮지 않을까 생각할 수 있지만 기존에 Triangle 클래스를 사용하던 소스코드들은 그럼 전부 어떻게 되는거죠? 따라서 Abstract 클래스만 상속을 하도록 제약하는 것은 개발을 너무 힘들게 하는 일이라고 생각합니다.


top

  1. Favicon of http://kebie.linuxstudy.pe.kr/blog.html BlogIcon kebie 2006.11.20 13:49 PERM. MOD/DEL REPLY

    정적타입의언어에서의 상속은 꼭 필요한 기능이라고 생각합니다. 하지만, 추상클래스를 상속받는 것으로 인하여 발생하는 코드의 중복을 상속으로 해결하기보다는 다른 객체와의 합성으로 해결하는 것이 더 바람직하다고 생각됩니다.

    많은 경우에 상속이 필요하게 되는 클래스는 설계가 비효율적인 경우가 많기 때문으로 여겨집니다. 설계를 잘만하면 중복되는 코드는 다른 클래스의 객체로 통합할 수 있는 여지가 많다고 생각합니다. 디자인패턴의 브릿지 패턴이 그러한 것중 하나가 아닐까 생각이 됩니다...

    Favicon of https://whiteship.tistory.com BlogIcon 기선 2006.11.20 17:08 신고 PERM MOD/DEL

    예 물론 Composition을 사용해서 재사용 할 수도 있습니다. 하지만 그럴 경우 다형성이라는 OO의 매우 큰 특징이자 장점을 활용할 수 없게 됩니다.

    위의 예제는 Abstract 클래스만 상속할 것이냐? 아니면 좀더 자유롭게 상속을 사용해야 하느냐에 초점을 맞추었기 때문에 구성이냐 상속이냐를 논하기엔 적당하지 않아 보입니다. 아마 그 둘중에 무엇을 사용할 것이냐 라고 해도 전 물론 위의 경우에서는 상속을 택했을 것이지만요. :)

    중복 해결 만이 초점이 아니였는데 본문을 다시 보니 중복 해결 방법으로만 써놓은 것 같이도 보이네요. :P

    Favicon of http://kebie.linuxstudy.pe.kr/blog.html BlogIcon kebie 2006.11.21 10:22 PERM MOD/DEL

    음... 추상클래스(자바에서라면 인터페이스?)를 상속받더라도 다형성을 활용하는데 큰 문제가 없지 않을까요? 추상클래스가 아닌 일반 클래스를 상속받는 경우라면 되도록 불변의 concrete class 일 필요가 있는데, 이경우 필요한 공통 메소드가 갖춰지기 때문에 추상클래스만 상속받고 중복코드는 합성을 이용해서 해결하면 다형성도 살리면서 상속의 깊이도 줄일 수가 있게 된다고 생각합니다.

    말씀하신대로 처음부터 이런 인터페이스를 완벽히 정하는 것이 개발의 부담이기 때문에 어쩔 수 없이 2단계이상의 깊이의 상속이 허용될 수 밖에 없는 경우가 많다고 생각합니다. 이때는 (다형성을 활용하기 위해서) 어뎁터패턴등을 이용해서 공통인터페이스만들고 상위 클래스를 추상클래스로 만드는 리펙토링과정이 들어가야 한다고 생각합니다. 최종적으로 2단계 이상의 깊이의 상속은 상속받은 클래스가 수정의 여지가 전혀 없다고 단정할 수 없기 때문에 나중에 유지보수할때 문제가 되니가요. :)

    Favicon of https://whiteship.tistory.com BlogIcon 기선 2006.11.21 10:50 신고 PERM MOD/DEL

    예 맞습니다. 추상 클래스를 상속 받더라도 다형성을 사용할 수가 있지요. 제가 윗 글에서 말하고자 한것은 "추상 클래스만 상속 할 수 있도록 제약 하는 것"은 효율적이지 않다는 것입니다.

    "어댑터패턴등을 이용해서 공통인터페이스만들고 상위 클래스를 추상클래스로 만드는 리펙토링과정이 들어가야 한다고 생각합니다." 이 부분은 짧은 글로는 이해하기는 어렵네요. 글로 포스팅 해서 트랙백을 달아주시기를 바라면 과한 부탁일까요? ^^;;

    어댑터 패턴 그림을 보면 "클래스 어댑터"아 아닌 "객체 어댑터"의 경우에는 Composition의 장점을 살리고 있는것 같아서요...

    Favicon of http://kebie.linuxstudy.pe.kr/blog.html BlogIcon kebie 2006.11.21 22:58 PERM MOD/DEL

    아직은 경험도 적고 배우는 입장이라 그부분에 대해 덧글보다 더 나은 글을 쓸 자신은 없어서 그냥 공부하면서 하면서 생각했던 내용들을 트랙백으로 남겼습니다. :)

    Favicon of https://whiteship.tistory.com BlogIcon 기선 2006.11.22 13:23 신고 PERM MOD/DEL

    늦었지만 트랙백과 댓글 감사합니다. :)

Write a comment.