모듈화
독립적인 기능이 있는 논리적 묶음(조각)에 해당하는 모듈로 소프트웨어 시스템을 구성하는 접근 방식모듈화의 중요성
1. 변경사항 반영의 편의성2. 재사용 가능성 향상
소프트웨어 모듈에는 독립적인 기능이 있기 때문에 추후 다른 소프트웨어 개발에서 쉽게 재사용될 수 있음3. 추적성 증진
기능 개선이나 변경을 반영하기 위한 작업을 수행할 때,
모듈화 구조는 요구사항 분석부터 설계 및 구현까지 일관성 있고 체계적인 모듈 간의 연결 구조를 제공할 수 있음
내적 요소의 관련성
내적요소(변수, 함수, 연산 등) 상호 관련성이 있는 것들로 묶여 있어야 함
간결한 상호작용
모듈 간의 상호작용이 가능한 한 간단한 형태로 구성되어야 함
복잡한 상호작용은 유지보수를 어렵게 만듦, 오류 발생 가능성을 높임
모듈 간의 의존적 관계를 나타내는 척도
결합력이 작을수록 좋은 설계
독립적 기능: 불필요한 중복을 제거하는 것이 중요
상호작용 최소화: 가능한 모듈 간 상호작용을 줄여 의존성을 낮추는 것이 좋음
결합력 최소화의 이점
1. 시스템 구성 요소 간 결합이 느슨해짐
2. 변경에 의한 파동효과를 막을 수 있음
3. 소프트웨어에 대한 이해도를 높임
4. 모듈의 인터페이스가 단순해짐
1. 메시지 결합력
결합의 정도가 가장 느슨한 유형, 객체지향 프로그래밍에서 나타남
- 객체 내 변수들은 Public 및 Private을 통해 캡슐화
- 서로 다른 상태를 갖는 객체가 서로 다른 모듈로 간주될 수 있음
- 객체 간 상호작용은 메시지 전달이라는 한 가지 개념으로 이루어짐
2. 데이터 결합력
2개의 모듈이 정수형, 문자형 등의 단순한 기본 데이터타입(원자 형태 데이터)를 갖는 변수들을 통해 상호작용하는 경우
3. 스탬프 결합력
복합 데이터 상호작용
두 모듈이 구조체와 같은 복합 데이터를 이용하여 상호작용
구조체 정의 시 의미상 상호 관련성 있는 데이터들을 묶음으로 정의불필요한 데이터까지 모두 전달하면
실행 시간이나 메모리 사용 측면에서 손실이 발생함
관련성이 적은 의미 없는 데이터를 묶지 않도록 주의해야함
4. 제어 결합력
한 모듈에서 다른 모듈로 매개변수를 전달할 때,
그 매개변수가 호출되는 함수의 내부 행위를 제어하는 역할을 한다면 이 두 모듈은 제어 결합력 관계에 있음플래그 변수
5. 외부 결합력
2개의 모듈이 외부에 존재하는 다른 정보를 공유하고 있을 때 발생,
파일, 디바이스, 인터페이스, 프로토콜 등이 해당다른 모듈의 변수 변경이나 동시 접근으로 인한 데드락 등의 문제가 발생할 수 있어 주의가 필요함
6. 공유 결합력
2개의 모듈이 전역변수를 공유하고 있을 때 발생하는 결합 관계
장점: 공유변수 사용은 메모리 사용량을 줄이고, 프로그램을 간단하게 작성할 수 있다
단점: 모듈 간의 의존성을 높이는 문제가 생김꼭 필요한 변수만 광역 변수(전역 변수)로 선언해야 함
7. 내용 결합력
한 모듈이 다른 모듈의 내부 구현에 직접 의존하는 가장 강한 형태의 결합력 (안좋음)
직접 참조: 한 모듈에서 다른 모듈의 내부를 직접 참조할 때 내용 결합 관계가 발생
GOTO 명령어
절차적 언어에서 'goto'명령어가 내용 결합을 유발최악의 결합
결합력 중 가장 강한 형태, 절대 피해야 함현대 프로그래밍
현대 프로그래밍 언어와 패러다임에서는 내용 결합력이 거의 발생하지 않음
모듈을 구성하는 내적 요소 간의 기능적 관련성의 강도를 측정하는 척도
높은 응집력이 좋음
응집력이 높은 모듈은 결합력이 낮은 경향이 있음
1. 기능 응집력
모듈을 구성하는 모든 요소가 단지 하나의 기능을 구현, 모듈이 명확한 단일 책임을 가짐
2. 순차 응집력
모듈을 구성하는 문장 관계에서, 한 문장의 실행 결과가 다음 문장의 입력으로 사용되는 경우
순차 응집력이 서로 입출력 관계에 있는 문장으로 구성되었다고 하더라도, 마지막 문장이 기능 응집력을 충족하지 못한다면 응집력의 효과는 저하됨
3. 교환 응집력
모듈을 구성하는 모든 요소가 동일한 입력 또는 출력을 사용한다면 존재하는 응집력
같은 데이터에 대해 서로 다른 작업을 수행하는 기능들이 하나의 모듈에 포함됨
각 정보를 개별적으로 처리하는 함수로 분리하는 것이 좋음
4. 절차 응집력
모듈을 구성하는 문장들이 의미상 서로 관련이 없지만 제어 흐름의 순서가 있는 경우
5. 시간 응집력
모듈을 구성하는 각 문장이 소프트웨어 실행의 특정 시간과 관련이 있는 것으로만 구성된 경우
6. 논리 응집력
모듈을 구성하는 모든 요소가 논리적으로 같은 유형의 외부 동작들로 구성되는 경우
모든 입력 처리를 하나의 모듈에, 모든 출력 처리를 다른 하나의 모듈에 넣는 방식
7. 우연 응집력
가장 나쁜 응집력, 무작위적 구성
소프트웨어 복잡도 측정 지표, 순환 복잡도
사이클로매틱 복잡도 계산 방법
간선 노드 방식
V(G) = E - N + 2
분기점 기반 방식
V(G) = P + 1
분기점은 if, for, while, case 등 프로그램의 흐름을 여러 방향으로 나누는 지점을 의미
사이클로매틱 복잡도가 높을수록 코드의 복잡성이 증가하고, 테스트와 유지보수가 어려워짐
1~10 : 관리하기 쉬움
11~20 : 리펙토링 권장
21~50 : 결함 가능성 높음
50 ~ : 테스트 거의 불가능
사이클로매틱 복잡도의 실무적 활용
테스트 케이스 수 결정
복잡도가 N이면, 코드의 모든 실행 경로를 커버하기 위해 최소 N개의 테스트 케이스가 필요
모듈 분리 기준
복잡도 11이상일 경우 모듈을 더 작은 단위로 분해하는 것이 권고
코드 품질 관리
정적 분석 도구를 통해 복잡도를 지속적으로 측정하고 모니터링함으로써 코드 품질을 관리할 수 있음
사이클로매틱 복잡도의 장단점
장점
- 수치화된 복잡도 평가가 가능, 객관적인 코드 품질 측정 지표로 활용
- 설계 단계에서부터 적용이 용이하여 초기단계에서 복잡도 관리 가능
- 테스트 케이스 수 결정에 명확한 기준 제공
- 자동화된 도구를 통해 쉽게 측정 가능
- 코드 리펙토링의 필요성을 판단하는 객관적 근거 제공
단점
- 데이터 복잡성의 반영이 부족하며, 주로 제어 흐름에만 초점
- Switch-case문에서 복잡도 값이 급증하는 문제 발생
- 모든 조건문을 동일한 가중치로 처리하여 실제 복잡성 차이 반영 못함
- 코드의 기능적 복잡성이나 알고리즘 복잡성 측정에 한계
- 상속, 다형성 등의 복잡성 측정에 제한적
사이클로매틱 복잡도 권장사항
마이크로소프트 기준
- 사이클로매틱 복잡도를 25이하로 유지할 것을 권장
사이클로매틱 복잡도는 10이하가 안정적
S
단일 책임 원칙 (SRP)
단 하나의 책임만 가져야 함
O
개방 폐쇄 원칙 (OCP)
기존 코드를 변경하지 않으면서 기능을 추가할 수 있어야 함
L
리스코프 대입 원칙 (LSP)
자식 클래스는 부모 클래스의 기능을 대체할 수 있어야 함선조건 관계 : 하위타입은 더 까다로운 선조건을 추가하면 안됨
오히려 선조건을 완화해야 함후조건 관계 : 하위 타입은 더 강력한 결과를 보장할 수 있어야 함
I
인터페이스 분리 원칙 (ISP)
클라이언트는 자신이 사용하지 않는 인터페이스에 의존하지 않아야 함
- 인터페이스를 클라이언트에 특화되도록 분리시키는게 목적
- 클라이언트는 자신이 이용하지 않는 기능에 영향을 받지 않아야 함
ISP위반의 문제점
- 불필요한 구현
- 테스트 어려움
- 의존성 문제
- 변경의 영향
D
의존성 역전 원칙 (DIP)
상위 모듈은 하위 모듈에서 의존해서는 안되며 둘 다 추상화에 의존해야 함구체적인 클래스보다 인터페이스나 추상 클래스에 의존관계를
맺어야 함
추상적인 클래스가 중요함
DIP의 장점
결합도 감소
클래스간의 결합도가 낮아져 변경에 유연해짐재사용성 증가
컴포넌트를 쉽게 교체할 수 있음변경 보호
한 부분의 변경이 다른 부분에 영향을 미치지 않음테스트 용이성
목(Mock)객체를 이용한 테스트가 쉬워짐
디자인 패턴
재사용 가능한 해결책
특정 맥락에서 자주 발생하는 문제들에 대한 검증된 해결책공통 언어
개발자들 간의 효율적인 의사소통을 가능하게 함경험 공유
경험 많은 엔지니어들의 지식을 쉽게 습득할 수 있음
GoF 디자인패턴
생성 패턴
객체 생성 매커니즘을 다루는 패턴들구조 패턴
클래스와 객체를 더 큰 구조로 조합하는 패턴들행위 패턴
객체 간의 커뮤니케이션을 다루는 패턴들
위의 내용 요약