컴퓨터/소프트웨어 공학

[소프트웨어 공학] 소프트웨어 설계 원칙/응집도, 결합도, 복잡도의 특성과 측정

도도새 도 2022. 12. 17. 18:45

응집도, 결합도, 복잡도의 특성과 측정

 

 

 소프트웨어의 설계는 요구사항(Requirements)를 바탕으로 (분석 과정을 거쳐) 진행된다.

 

 이 과정에서 유지보수성을 생각한다면 응집도, 결합도, 복잡도를 설계 원칙으로 하여야한다. 또한 여기에 더해 객체지향 설계를 한다면 SOLID(SRP, OCP, LSP, ISP, DIP) 디자인 패턴 역시 고려하여야한다.

 

이번에는 이 중 응집도 결합도 복잡도의 개념과 측정을 정리한다.

 

분석과 설계의 차이

: 요구사항 중 기능적 요구사항만을 고려하면 분석, 추가적으로 비기능적 요구사항 역시 고려하면 설계라고 한다.

 

*요구사항 : 시스템이 갖추어야 할 요건을 정리한 것, 요구사항의 내용은 기능적 요구사항과 비기능적 요구사항으로 나눌 수 있다.

*기능적 요구 사항 : 시스템이 어떤식으로 작동해야하는 가에 대한 요구사항, 측정가능하며 구체적이라는 특징 가짐 ex)버튼을 클릭했을 때 a페이지가 떠야한다.

*비기능적 요구사항 : 시스템 기능에 대한 조건과 제약사항에 관한 요구사항 ex) 시스템을 실행할 때 n초 안에 실행되어야 한다.

 

응집도(Cohesion)

 

대상 내부 요소들(ex 클래스 내부 메서드) 간에 기능적으로 얼마나 관련성이 있는가를 나타낸 것. 기능적으로 관련이 높을수록 응집도가 높다. 응집도는 높을수록 바람직하다.

-Function cohesion

-Class cohesion

-Packagea cohesion

-Componenet cohesion

등 다양한 기준의 응집도가 존재한다.

 

응집도 예시

int sumOrMul(int flag, int a, int b){

if(flag = 0) return a *b;

else return a + b;

}

flag값에 따라 add나 mul연산을 한다. 하지만 add를 하는 부분과 mul를 하는 부분은 서로 어떠한 연관관계도 가지지 않는다. 즉, 내부의 구성요소가 기능적으로 관련이 없으므로 응집도가 떨어진다고 할 수 있다.

 

 

Class Cohesion Metrics – LCOM(Lack of Cohesion of Methods)

 

클래스의 응집도를 정량적으로 측정하는 방법 중 하나이다.

P는 I라는 operation과 J라는 operation이 접근하는 attribute의 집합이 공집합인 것의 쌍

Q는 I라는 operation과 J라는 operation이 접근하는 attribute의 집합이 공집합이 아닌 것의 쌍.

즉, P는 서로 공유하는 변수(혹은 attribute)가 있는 메서드(혹은 operation), Q는 서로 공유하는 요소가 없는 메서드이다.

 

LCOM은 P - Q(음수일 경우 결과값은 0)으로 계산된다. 값이 클수록 응집도가 나쁘다는 것을 나타낸다.

 

LCOM 예시 1

LCOM 예시

M1과 M2는 V1에 동시에 접근하므로 Q이다.

M1과 M3는 동시에 접근하는 v가 없으므로 P이다.

M2와 M3는 동시에 접근하는 v가 없으므로 P이다.

결과값은 2 - 1인 1이다.

 

LCOM 예시 2

LCOM 예시2

M1과 M2는 V1에 동시에 접근하므로 Q이다.

M1과 M3는 동시에 접근하지 않으므로 P이다.

M2와 M3는 v2에 접근하므로 Q이다.

결과값 : 1 - 2 = -1이므로 0이다.

 

단 이 경우, 메서드의 쌍의 수에 비례해서 최대값이 계속해서 커진다. 그것을 해결하기 위한 변형 방법이 존재한다.

LCOM Variants

LCOM = 1 - (sum(MF)/M*F) : [0..1]

LCOM HS = [M-sum(MF/F] / (M -1) : [0..2]

 

결합도(Coupling)

 

요소 간의 의존성이 얼마나 강하냐를 나타냄, 예를 들어 B클래스가 A클래스에 얼마나 의존하고 있는가이다. 가능하면 결합도를 낮추어 독립적으로 각 요소를 구성하는 것이 바람직하다.

 

불필요한 관계, 사용하지 않아도 되는 클래스, 함수등을 삭제하여야한다.

 

Fan out : 어떤 모듈에 의해 제어(호출)되는 모듈의 수

Fan in : 어떤 모듈을 제어(호출)하는 모듈의 수

 

일반적으로 결합도를 이야기할 때는 Fan out을 의미한다. 즉, 해당 모듈이 의존하는 모듈의 수를 의미한다.

 

 

RFC(Response For Class) 

 

메서드 호출이라는 관점에서 결합도를 측정한다.

- 클래스 내부의 메서드 수 + 클래스의 메서드가 호출하는 클래스 외부 메서드 수

 

CBO(Coupling Between Objects)

 

클래스의 관점에서 결합도를 측정한다.

해당 클래스가 의존 및 이용하는 클래스의 수(Fan out) + 해당 클래스를 의존, 이용하는 클래스 수(Fan in)

 

예시 CBO 예시 

클래스 B의 CBO 측정

CBO측정

클래스 B의 경우 E와 A에 의존한다. Fan Out이 2이다.

또한 C와 D가 B에 의존한다. Fan In이 2이다.

따라서 Fan out + Fan in = 4 즉, CBO = 4이다.

 

패키지 결합도

 

Efferent Couplings (Ce) : Fan out

패키지 내부의 클래스를 의존하는 다른 패키지 내의 클래스 수

 

Afferent Couplings(Ca) : Fan in

다른 패키지 내부의 클래스가 의존하는 내부 패키지의 수

 

복잡도(Complexity)

 

클래스, 함수, 메서드 등의 복잡도를 나타낸다. 복잡도는 낮을수록 바람직하다.

 

복잡도 측정 방법

 

Cyclomatic Complexity(CC)

 

단순하게 문장 내의  Decision의 수를 세어 복잡도를 측정하는 방법이다.

CC = number of decision + 1

즉, 분기를 유발하는 문장 + 1로 복잡도를 계산한다. decision에는 if문, for문 등이 들어간다.'

 

CC예시 1

if(i >= 1)...//분기를 유발

else...

CC= 2;

 

CC예시 2

for(int i = 0; i < 10; i ++){

if(i>= 3)...

if(i >= 5)...

}

CC = 4;

 

CC값에 따른 복잡도의 기준은 아래와 같다.

CC Type of procedure Risk
1–4  A simple procedure Low
5–10  A well structured and stable procedure Low
11–20 A more complex procedure  Moderate
21–50 A complex procedure, alarming High
>50  An error-prone, extremely troublesome, untestable procedure  Very high

 

결론

 

응집도는 올려야하고, 결합도는 떨어뜨려야하고, 복잡도 역시 떨어뜨려야한다.

 

*이클립스의 metric plug-in을 이용하면 응집도, 결합도, 복잡도를 계산할 수 있다.