요즘('2010.08) 내가 하는 작업은
공통컴포넌트의 개발 뒤 개발된 프로그램간의 재활용율 또는 프로그램간 의존도를 체크하는 것이다.
즉 만들어진 프로그램을 중심으로 재사용되었는지
또는 개발된 프로그램간에 잘못 연결된 무한 반복 의존관계등이 존재하는가 조사하는 것이다.
자바의 부분에선 이걸 훌륭히 수행하는 똑똑한 툴이 있다.
그게 바로 Eclipse plugin 인 JDEPEND이다.
이런 관련 프로그램을 30개쯤 조사했는데 이게 젤 사용이 편하다.
참고로
-- 모듈간 dependency 확인을 위해 테스트해본 tool
1. jdepend(http://clarkware.com/software/JDepend.html)
-. eclipse plugin : http://andrei.gmxhome.de/jdepend4eclipse/
-. 주요특성 : 설치방법, 사용방법이 무난함, 객체가 연관관계 추적시 상세한 정보가 부족하다는 느낌
-. eclipse plug-in으로 무료 도구
2. sonarj(http://www.hello2morrow.com)
-. 상용, 개발자에 한해 기간제한된 라이센스를 제공
-. 주요특성 : eclipse plug-in 제공, 설치나 사용방법이 다소 어려움
-. 소스단위까지의 연관관계 추적 가능
3. structure101(http://www.headwaysoftware.com)
-. 상용, 짧은 체험판 제공
-. 주요특성 : 상위 2개의 툴에 비해 다양한 정보 제공, class, package, 설계 단계별 Matrix제공
-. 단 설치가 어렵다. 비싸다
등의 상용소스도 존재한다.
우선 자바를 설계, 개발하면서 알아야 할 "5대" 코드 분석 영역이 있다.
- 코딩 표준
- 코드 중복
- 코드 커버리지
- 의존성 분석
- 복잡성 모니터링
이러한 분석 영역들은 다음과 같은 Eclipse 플러그인을 사용한다.
CheckStyle: 코딩 표준
PMD의 CPD: 코드 중복 발견
Coverlipse: 코드 커버리지 측정
JDepend: 의존성 분석 제공
Eclipse Metrics 플러그인: 복잡성 탐지
툴 | 목적 | Eclipse 플러그인 URL |
CheckStyle | 코딩 표준 분석 | http://eclipse-cs.sourceforge.net/update/ |
Coverlipse | 코드 커버리지 테스트 | http://coverlipse.sf.net/update |
CPD Copy/Paste | 탐지 | http://pmd.sourceforge.net/eclipse/ |
JDepend | 패키지 의존성 분석 | http://andrei.gmxhome.de/eclipse/ |
Metrics | Complexity monitoring | http://metrics.sourceforge.net/update |
이중 JDepend 에 대해서 알아보자.
[설치방법]
1. 이클립스를 실행한 다음 Help | Software Updates 을 선택한다
2. Search for new features to install 라디오 버튼을 선택하고 Next를 클릭한다
3. New Remote Site를 클릭하고, 원하는 플러그인의 이름과 URL을 입력한다.
OK를 클릭한 다음 Finish를 클릭하면 Eclipse Update Manager가 디스플레이 된다.
4. Eclipse Update Manager에서, 플러그인의 다양한 측면을 볼 수 있는 옵션이 있다.
일반적으로 위에 있는 것을 선택한다. 선택을 하고 Finish를 클릭한다.
Eclipse는 이때 플러그인을 설치한다. Eclipse 인스턴스를 재시작 해야 한다.
[사용방법]
소스 폴더를 오른쪽 클릭하고, Run JDepend Analysis를 선택하여 JDepend용 Eclipse 플러그인을
사용하는 방법을 보여준다. 소스 코드를 갖고 있는 폴더를 선택하라.
그렇게 하지 않으면, 메뉴 옵션을 볼 수 없다.
결과는 다음과 같은 화면이 출력된다
조금 복잡한대
그렇다고 놀랄 내가 아니~~지~
천천히 살펴보면 화면이 크게 세 부분으로 구성되어 있는 것을 볼 수 있다.
왼쪽 위에는 패키지들 (소스와 패키지)
왼쪽 아래에는 이상한 그래프(Metrics)
오른쪽에는 종속성 관련 뷰로
다시 네 종류의 정보(현재 선택한 패키지,
사이클을 가지고 있는 패키지,
선택한 패키지에서 사용하고 있는 패키지,
선택한 패키지를 사용되고 있는 패키지)를 담고 있다.
또한 영어로 쓰여있는 부분은 다음과 같다.
CC :: Concrete Class의 약자로 인터페이스나 추상 클래스가 아닌 말그대로 Concrete Class의 갯수 이다.
AC :: Abstract Class의 약자로 추상 클래스나 인터페이스의 갯수를 나타내며 확장성의 척도가 된다.
Ca :: Afferent Couplings을 나타냅니다. 직역하면 당하는 커플링.
즉 현재 패키지의 클래스들에 종속성을 가지는 패키지의 갯수를 나타낸다. 책임의 척도가 된다.
Ce :: Efferent Couplings을 나타낸다.
위와 반대로 이번에는 현재 패키지의 클래스들이 종속하고 있는 패키지의 갯수를 나타낸다. 독립성의 척도가 된다.
A :: 추상화 정도를 나타내며 0 부터 1 사이의 값을 가지며
0은 완전 구체적인 패키지
1은 추상적인 패키지를 나타낸다.
I :: 변화에 대한 탄력도를 나타낸다.
0 부터 1 사이의 값을 가지며
0은 외부 변화에도 끄떡 없는 패키지이며
1은 작은 변화에도 쉽게 흔들릴 수 있는 패키지를 나타낸다.
D :: Main Sequence로 부터의 거리를 나타낸다.
Main Sequence란 이상적인 패키지로 완전 추상적이면서 안정적이거나
완전 구체적이면서 불안정한 패키지를 나타낸다.
0 부터 1 사이의 값을 가지며 0은 Main Sequence와 완전 가까우며 1은 완전 먼 상태이다.
Cycle : 패키지들 상호 간에 종속성을 가지고 있을 때 발생한다.
이 값이 많을 수록 안좋은 상황이기 때문에 경고 아이콘으로 보여진다.
결국, 가장 중요한 값은 D이며, D가 낮을수록 인터페이스 기반의 개발을 한 것으로 Coupling이 적다고 해석하면 된다.
결국 모든 데이터는 D 를 산출하기 위해 필요한 데이타 라고 보아도 될 것 같다.
그만큼 D가 중요하니 좀 더 살펴보겠다. 이상적인 상황을 Main Sequence라고 하고 있다. 즉 이상적인 상황이라고 말했던 두 경우는 다음과 같다.
- 완전 추상화 일때는 완전 안정적
- 완전 구체화 일때는 완전 불안정적
즉
'추상화 클래스가 많은 패키지'는 다른 패키지에 의존하지 말고 다른 패키지들이 이 패키지에 의존하여야 하며
'구체 클래스가 많은 패키지'는 다른 패키지들이 이 패키지에 의존하지 말아야 하며
이 패키지의 클래스들이 다른 패키지에 의존성을 가져야 하는 것이 이상적이라는 것이다.
또한 그래프가 의미하는 것은 이런 내용을 한눈에 들어오게 표현한 것이다.
이렇듯 JDEPEND를 사용하면 현재 패키지가 얼마만큼 패키지간 의존성이 있는지 확인할 수 있고
Cyclic Dependency 같은 문제점도 찾아낼 수 있다.
무엇보다 개발완료가 아닌 개발중에도 문제점을 체크할 수 있어 사용이 용이하다.
또한 이론적인 덧붙임은 다음과 같다.
아키텍처 설계와 구조화에 관한 기술은 여러가지가 있다.
그 중에서 코드의 구성을 어떻게 할 것인가도 매우 중요하다.
코드를 쉽게 읽고 네비게이션 할 수 있고 손쉽게 이해하려면 구조적으로 잘 설계된 패키징이 필요하다.
자바는 코드를 계층화된 package라는 논리적인 단위로 구분할 수 있도록 해서 이를 돕고 있다.
대부분의 시스템의 코드는 초기구조를 그대로 유지하는 것이 아니라 대부분 지속적으로 추가되고 발전된다는 특징이 있다.
즉 이전버전과의 호환성에 장애가 될 수 있다.
개발시 사용하는 라이브러리나 프레임워크가 수십개에 달하는 요즘 개발방식을 볼 때
코드의 외부 라이브러리의 버전에 관한 의존관계는 매우 복잡해지고 있다.
수시로 새 버전이 나오는 오픈소스 프레임워크의 경우 그 문제가 한층 더 심각하다.
그 해결 방법은 가장 먼저 생각할 것은 내가 만들고 있는 시스템 또는 프레임워크의 내부의존관계에 대한 정립이다.
또 아키텍처를 가진 설계와 접근, 검증과정의 도입이다.
자바의 초보과정에서 반드시 배우는 것에 package가 포함되어있다.
Package는 단순히 클래스명의 충돌을 막기 위한 naming space만은 아니다.
Package는 코드 organization의 기반과 경계가 된다.
하지만 자바를 배우는 개발자들은 기껏해야 com.companyname.systemname….
따위의 패키지네임 컨벤션만을 배웠을 뿐이지
그 안에서 어떻게 패키지를 구분하고 설계할지에 대해서는 제대로 배운적이 없다.
기껏해야 간단한 패키징 룰 정도를 정해서 사용하고 있을 뿐이다.
코드의 발전에 package구분이 미치는 영향은 매우 크다.
사실 복잡한 시스템 설계나 코드설계에서 제일 주의해야 할 것은 의존관계의 복잡성이다.
Package구조에서도 의존관계의 복잡성을 가지게 되면 여러가지 문제를 일으킨다.
지나치게 복잡한 의존관계로 서로 얽혀 있는 시스템이라면 무엇인가 설계에 결함이 있다고 생각할 수 있다.
Package간에서도 마찬가지이다.
그래서 Package레벨의 의존관계(사실은 그 안에 속한 Class간의 의존관계)에 대한 분석을 통해서
시스템 아키텍처를 검토하려는 많은 시도들이 있다.
JDepend같은 툴은 그런면에서 많은 도움이 될 수 있는 분석도구이다.
의존관계 분석에서 중요한 것 중의 하나는 순환의존관계(Cyclic Dependency)이다.
Cyclic Dependency는 많은 문제를 일으키는 안좋은 설계의 대표적인 예이다.
Cyclic Dependency가 일으킬 수 있는 문제점은 매우 다양하다.
위에서 얘기한 onJava의 아티클이나 Krkk의 블로그에 그 이유들이 잘 설명되어있다.
상식적으로도 컴포넌트나 패키지, 모듈이 순환적인 의존관계를 가지면 안된다는 것은 쉽게 이해할 수 있다.
많은 사람들이 추구했던 것이 결국 잘못된 의존관계로 인해서 매우 지저분하게 coupling된 시스템을 피하자는 것이었다.
원래 설계에서 의도하지 않았던 의존성들이 모듈을 나누다 보면 생길 수 있다
왜 단방향 의존성이 중요한가?
- 즉, 왜 순환 참조(Cycle Dependency)가 안 좋을까?
- 코드를 악화 시킨다,.
- 패키지 재사용에 제한이 생긴다.
- B를 사용하려면 A를 컴파일 해야 하는데 A는 다시 B를 컴파일 해야 하는 상황 발생한다.
그러니까
- CD를 없애라.
- 패키지들을 개념적인 모듈로 묶어라.
- 모듈을 만들어 낼 땐 개념적인 경계와 더불어 배포도 고려해야 한다.
모두 내가 쓴 글이면 좋겠지만 분석하신 좋은 분들의 글이 있어서 정리해보았다.
출처 : http://erfile.tistory.com/80?srchid=BR1http%3A%2F%2Ferfile.tistory.com%2F80
http://benelog.egloos.com/2208368
http://whiteship.me/967?srchid=BR1http%3A%2F%2Fwhiteship.me%2F967
좋은 툴이 있다는 건 그만큼 고생한 누군가가 있다는 것이겠지.
다음엔 더 자세히 사용예를 통해 설명을 해보리라.