본문 바로가기

Java

객체지향적인 설계?

최근에 객체지향적인 설계와 객체지향적인 생각

이런 것들에 대한 생각이 많아져서 고민을 하던차에 풍대리님께 부탁을 드려서

이것에 대한 얘기를 들을 수 있는 기회가 생기게 되었다.

그 내용을 간략하게 정리해보고자 한다.

풍대리님의 강의 스타일은 소설처럼 풀어가시는 스타일이다. 그

리고 그런 스타일이 내가 참 좋아하는 스타일의 강의이기도 하다.

(소설같은 자바, 소설같은 JSP를 괜히 두세번씩 읽은게 아닌것이다.)

하지만 덕분에 정리를 하려면 힘들다. ㅋ 왜냐면 전체적인 흐름은 기억에 남는데

정리에 필요한 세부적인 내용은 잘 기억에 남지 않는다. 그래서 조금이라도

머리에 뭔가 남아있을 때 이렇게 정리를 해두어야 한다. -_-


일단 객체지향적인 설계라는 것이 무어냐. 내가 가끔 하는 일단 구현을 하고 그 구현된

클래스들 중에서 중복되는 메서드나 멤버변수들을 뽑아내어 하나의 클래스로 만들어

상속 혹은 implements를 하는 것이 객체지향적인 구현이냐...

객체지향적인 사고라는 것은 어떠한 공통된 "행위"를 뽑아 내는 것이고 서로의

연관관계를 가급적 최소화 시키는 방향으로 생각되어야 한다.

클래스간에 서로 참조, 변경, 의존을 최소화 시키고 이러한 것들이 생기면 그것을

객체로 꺼내는 것이다.

의존관계가 생기면 서로 밀집도가 높아지게 되고 이것은 나중에 서비스의 추가라던가

변화에 대해 빠르게 대응하지 못하는.. 하나를 고치면 그에 의존하고 있는 수십,

수백개의 클래스들을 모두 수정해야 하는 (오염도가 높아지는) 현상이 생기게 되는

것이다.

풍대리님이 예를 들어주신 것을 보면

USER가 있고 배송이 있다고 할 때 USER에는 이름,나이,성별,주소.. 등등의

행위패턴들이 포함되어 있을 것이고 배송에는 주소,이름,배송업체 .. 뭐 이런 것들이

포함되어 있을 것이다.

이때 서로 공통되는 것 "주소" 라는 것이 나왔을때 이것을 "주소"라는 객체로 끄집어

내게 되면 나중에 주소라는 클래스에 "우편번호"가 추가되게 된다 하더라도 주소

클래스에 우편번호를 추가하고

이것을 구현 혹은 사용하고 있는 USER나 배송에서는 그것을 가져다 쓰는 부분만을

구현해주면 되는 것이다.

(오염도가 낮아진다.)

아니면, 필요없는 곳에서는 구현을 아예 안 해줘도 되는 것이다.

만약, USER도 주소를 가지고 있고, 배송도 주소를 가지고 있어서 각자 자기

것을 사용하고 있다고 하면 추가된 우편번호는 USER에도 배송에도 추가를 해줘야

하고 이 것은 버그를 낼 수 있는 가능성이 높아지게 된다.

물론 USER클래스에 주소를 포함시키고, 배송에서 USER.주소 이런식으로 사용을 해도

틀린 것은 아니지만, 지금 얘기하고 싶은 것은 행위를 기반으로 이런식으로

객체의 의존관계를 먼저 도출해 내고 이를 바탕으로 객체화 시키는 방법을 얘기하고

싶은 것이다.

중요한 것은

구현을 먼저 하지 말 것
의존관계와 차이점을 찾아낼것
그것을 바탕으로 객체화 시킬것
인터페이스/추상클래스를 도출해볼 것

한번 설명을 들었다고해서 나도 역시 사실 감도 안오기는 하지만 그래도 어떤식으로

생각하면 되겠구나.... 하는 생각의 방향은 잡을 수 있었던것 같다.

그리고 추상클래스라던가 인터페이스라는 것은 일반적으로 책에 나와있는

TV라는 인터페이스를 가지고 삼성TV, LGTV, 대우TV등을 TV 인터페이스를  상속해

만드는 예처럼 , 공통적으로 사용하는 메서드(켜다, 끄다, 채널을 돌리다 등)를

하나로 통합하는 것이 주 목적은 아니라는 생각이 든다.

정말 인터페이스가 필요한 이유는 개체간의 상호 의존도를 줄이기 위해

필요한 것이라는 생각이 들기 시작했다. 풍대리님의 설명과 최근 읽은 책들을 보면서...

즉, buy(삼성TV tv), buy(LGTV tv), buy(대우TV tv) 라는 메서드가

buy(TV tv) 하나로 바뀔 수 있다는 것이다. 전자의 경우는 구현되어있는 클래스와

직접적인 의존도가 생기기 때문에 만약 소니TV라는 클래스가 생기게 된다면,

buy(소니TV tv)라는 메서드도 추가되어야 하고, 메서드 뿐아니라 저렇게 직접적으로

구현된 클래스가 연관되어있는 곳은 다 찾아 다니면서 소니TV에 대한 로직을

추가해 줘야 한다는 것이다.

하지만, buy(TV tv)라면 그러한 직접적인 의존도가 생기지 않기 때문에 훨씬

융통성이 있게 되는 것이다.

만일 인터페이스란 개념이 없다면 IoC에 대한 것도 없을 것이고, 여러가지 디자인

패턴에 대한 내용도 나올 수 없을 것이다.

자바의 Comparable 인터페이스 역시 TreeSet에 객체를 add할 때 

Comparable객체간의 순서를 결정하기 위해 사용된 인터페이스라고 생각한다.
 
Comparable 인터페이스가 없다면, add(Object obj)를 할 때 어떠한 객체가 들어올지

전혀 모르기 때문에, 순서를 결정 할 수 없을 것이다. 하지만 Comparable을 구현한

객체라면 공통적으로 compareTo를 구현하고 있을 것이고 그렇기 때문에 이것을

이용하여 어떤 객체라도 객체간의 순서 비교를 할 수 있게 되는  것이다.

처음 자바를 시작하고, 저 Comparable을 봤을때 compareTo를 구현하면 객체간의

순서를 결정 할 수 있다는데, Comparable은 인터페이스고 compareTo를 구현한다

해도 어떻게 이게 순서를 구현하는데 사용되는건지 전혀 알 수 없었다.

(인터페이스가 단순히 공통된 메서드를 뽑아낸 것. 이라고 알고 있던 상황이니

도저히 알 수 없었을 것이다..)

그리고 요즘 패턴책들을 다시 읽고, 사례책들을 읽고 있는데 결국 패턴은 인터페이스를

사용하여 각 객체간의 의존도와 복합성을 줄이려는 노력들이구나 라는 생각이 들고

이 의존도를 줄이는 것이 대체적으로 서비스를 발전시키고, 수정하고 하는데 도움이

된다는 내용들이었다.

인터페이스, 그리고 객체등에 대해 생각의 전환을 할 수 있는 굉장히 좋은 시간들이었다.

그리고 상속관계 생성자에 대해서도 들었는데 이는 내 블로그에도 이미 포스트를 해 놓

았으니 참고하면 되겠다.


special thanks to 풍D님