모듈화(Modularization)
- 소프트웨어 개발에서 코드를 각 기능별로 나누는 것
- 프로그램이 효율적으로 관리될 수 있도록 시스템을 분해하고 추상화함으로써 소프트웨어 제품의 성능을
향상시키거나 시스템의 수정 및 재사용, 유지 관리를 용이하게 하는 기법
모듈(Module)
- 기능별로 나누어진 모듈화의 결과
- 소프트웨어 내의 프로그램 또는 작업 단위
독립성
- 모듈은 주어진 기능만을 독립적으로 수행하며 다른 모듈과 적게 연관되어야 함
- 모듈의 결합도와 응집도로 측정
- 결합도는 낮고, 응집도가 높을수록 독립성이 높음
- 독립성이 높을수록 좋은 모듈
- 해당 모듈을 수정해도 다른 모듈에 미치는 영향이 감소하기 때문
결합도(Coupling)
- 서로 다른 모듈 간 상호 의존하는 정도 또는 두 모듈 사이의 연관된 관계
- 낮을수록 좋음
단계 종류
세기 | 종류 | 내용 |
약함 ↓ 강함 |
자료 결합도 (Data Coupling) |
모듈간의 인터페이스로 전달되는 파라미터(데이터)를 통해서만 상호 작용이 일어나는 경우 결합도가 제일 낮고 제일 좋은 형태이다. |
스탬프 결합도 (Stamp Coupling) |
모듈간의 인터페이스로 배열이나 객체, 자료 구조 등이 전달되는 경우 | |
제어 결합도 (Control Coupling) |
어떤 모듈이 다른 모듈 내부의 논리적인 흐름을 제어하는 제어 요소를 전달하는 경우 | |
외부 결합도 (External Coupling) |
어떤 모듈이 외부에 있는 다른 모듈의 데이터를 참조하는 경우 (데이터, 통신 프로토콜 등) | |
공통 결합도 (Common Coupling) |
여러 개의 모듈이 하나의 공통 데이터 영역(전역 변수 참조 및 갱신)을 사용하는 경우 | |
내용 결합도 (Content Coupling) |
어떤 모듈 내부에 있는 변수나 기능을 다른 모듈에서 사용하는 경우 결합도가 제일 높고 제일 좋지 않은 형태이다. |
1. 자료 결합도(Data Coupling)
- 모듈끼리 단순히 데이터를 주고 받는 경우
- 한 모듈을 변경하더라도 다른 모듈에는 영향을 끼치지 않는 결합 형태
# 모듈 1
def calculate_square(num):
return num * num
# 모듈 2
def main():
data = 5
squared_num = calculate_square(data)
print("Result:", squared_num)
# 모듈 1과 모듈 2는 data 변수를 통해 데이터를 주고받고 있음
2. 스탬프 결합도(Stamp Coupling)
- 두 모듈이 인터페이스로 배열이나 오프젝트와 같은 동일한 자료 구조를 참조하는 형태의 결합도
- 모듈에 쓰일 자료구조 형태가 변경되면 참조하는 모든 모듈에 영향을 주게 됨
// 모듈 1
public class Module1 {
public void processData(int[] data) {
for (int i = 0; i < data.length; i++) {
data[i] = data[i] * 2;
}
}
}
// 모듈 2
public class Module2 {
public void printData(int[] data) {
for (int num : data) {
System.out.print(num + " ");
}
System.out.println();
}
}
// 모듈 3
// 모듈 3이 모듈1과 모듈2에게 array라는 스탬프를 전달하여 처리를 수행
public class Main {
public static void main(String[] args) {
int[] array = { 1, 2, 3, 4, 5 };
Module1 module1 = new Module1();
module1.processData(array);
Module2 module2 = new Module2();
module2.printData(array); // 출력 결과: 2 4 6 8 10
}
}
3. 제어 결합도(Control Coupling)
- 단순 처리할 대상인 값만 전달되는게 아니라 어떻게 처리를 해야 한다는 제어 요소가 전달되는 경우
- 한 모듈이 다른 모듈의 실행 흐름을 직접 제어하는 결합도
# 모듈 1
def calculate_square(num):
return num * num
# 모듈 2
def main():
data = 5
squared_num = calculate_square(data)
print("Result:", squared_num)
# 모듈 2가 모듈 1의 결과에 따라 다른 동작을 수행하도록 제어 결합됨
if squared_num > 10:
print("The result is greater than 10.")
else:
print("The result is not greater than 10.")
4. 외부 결합도(External Coupling)
- 모듈이 외부 환경과 상호작용하는 결합도
-> 파일, 데이터베이스, 네트워크 등 외부 자원과의 연동을 의미
# 모듈 1
# 데이터를 파일에 쓰는 함수를 제공
def write_to_file(filename, data):
with open(filename, 'w') as file:
file.write(data)
# 모듈 2
# 파일로부터 데이터를 읽는 함수 제공
def read_from_file(filename):
with open(filename, 'r') as file:
data = file.read()
return data
# 모듈 3
def main():
filename = "data.txt"
user_input = input("Enter some data: ")
write_to_file(filename, user_input)
# 모듈 3에서 모듈 2의 함수를 사용하여 외부 파일에서 데이터를 읽어옴
data_from_file = read_from_file(filename)
print("Data from file:", data_from_file)
5. 공통 결합도(Common Coupling)
- 여러개의 모듈이 하나의 공통 데이터 영역을 사용하는 결합도
- 대표적으로 전역 변수를 예로 들 수 있음
- 공통 데이터 영역의 내용을 조금만 변경하더라도 이를 사용하는 모든 모듈에 영향을 미침
// 모듈 1
public class CounterModule {
private static int counter = 0;
public static void incrementCounter() {
counter++;
}
public static int getCounter() {
return counter;
}
public static void resetCounter() {
counter = 0;
}
}
// 모듈 2
public class PrinterModule {
public static void printCounterValue() {
int counterValue = CounterModule.getCounter();
System.out.println("Counter: " + counterValue);
}
}
// 모듈 3
public class Main {
public static void main(String[] args) {
CounterModule.incrementCounter();
CounterModule.incrementCounter();
PrinterModule.printCounterValue(); // Output: Counter: 2
CounterModule.resetCounter();
PrinterModule.printCounterValue(); // Output: Counter: 0
}
}
6. 내용 결합도(Content Coupling)
- 가장 높은 결합도를 갖으며, 가장 좋지 않은 결합 형태
- 어떤 모듈이 사용하려면 다른 모듈의 내부 기능과 데이터를 직접 참조해 그대로 가져와 사용하거나 수정하는 경우
// 모듈 1
public class Module1 {
public int processData(int num) {
return num * 2;
}
}
// 모듈 2
public class Module2 {
public void printData(int num) {
System.out.println("데이터: " + num);
}
}
// 모듈 3
// 모듈1의 메서드를 호출하며 데이터를 처리하고 그 결과를 모듈2의 메서드에 인자로 전달하여 처리
public class Main {
public static void main(String[] args) {
int number = 5;
Module1 module1 = new Module1();
int processedData = module1.processData(number);
Module2 module2 = new Module2();
module2.printData(processedData); // 출력 결과: 데이터: 10
}
}
응집도(Cohesion)
- 모듈 내부에서 구성 요소 간에 밀접한 관계를 맺고 있는 정도
- 높을수록 좋음
단계 종류
세기 | 종류 | 내용 |
강함 ↓ 약함 |
기능적 응집도 (Functional Cohesion) |
모듈 내부의 모든 기능이 단일 목적을 위해 수행되는 경우 응집도가 제일 높고 제일 좋은 형태이다. |
순차적 응집도 (Sequential Cohesion) |
모듈 내에서 한 활동으로부터 나온 출력 값을 다른 활동이 사용할 경우 | |
교환적 응집도 (Communication Cohesion) |
동일한 입력과 출력을 사용해 다른 기능을 수행하는 활동들이 모여있을 경우 | |
절차적 응집도 (Procedural Cohesion) |
모듈이 다수 관련 기능을 가질 때 모듈 안의 구성요소들이 그 기능을 순차적으로 수행할 경우 | |
시간적 응집도 (Temporal Cohesion) |
연관된 기능이라기 보단 특정 시간에 처리되어야 하는 활동들을 한 모듈에서 처리할 경우 | |
논리적 응집도 (Logical Cohesion) |
유사한 성격을 갖거나 특정 형태로 분류되는 처리 요소들이 한 모듈에서 처리되는 경우 | |
우연적 응집도 (Coincidental Cohesion) |
모듈 내부의 각 구성요소들이 연관이 없을 경우 응집도가 제일 낮고 제일 좋지 않은 형태이다. |
1. 기능적 응집도(Functional Cohesion)
- 가장 응집도가 높은 형태로 가장 좋은 형태
- 모듈 내부의 모든 기능이 단일 목적을 위해 수행되는 경우
- 대입되는 변수가 공통적으로 사용되는 경우
public class FunctionalCohesionExample {
public int addNumbers(int a, int b) {
// 두 숫자를 더하여 결과를 반환
return a + b;
}
public int subtractNumbers(int a, int b) {
// 두 숫자를 빼서 결과를 반환
return a - b;
}
public int multiplyNumbers(int a, int b) {
// 두 숫자를 곱해서 결과를 반환
return a * b;
}
public int divideNumbers(int a, int b) {
// 두 숫자를 나누어 결과를 반환
return a / b;
}
}
// 각 메서드들이 독립적인 기능을 수행하며, 서로 다른 기능을 담당
2. 순차적 응집도(Sequential Cohesion)
- 모듈 내에서 한 활동으로부터 나온 출력값이 다음 활동의 입력 데이터로 사용할 경우
public class SequentialCohesionExample {
private int result;
public void stepOne() {
// Step One 작업 수행
result = 1;
}
public void stepTwo() {
// Step Two 작업 수행 (Step One에서 얻은 결과 활용)
result += 2;
}
public void stepThree() {
// Step Three 작업 수행 (Step Two에서 얻은 결과 활용)
result *= 3;
}
public int getResult() {
return result;
}
public static void main(String[] args) {
SequentialCohesionExample example = new SequentialCohesionExample();
example.stepOne(); // Step One 작업 수행
example.stepTwo(); // Step Two 작업 수행
example.stepThree(); // Step Three 작업 수행
int finalResult = example.getResult();
System.out.println("최종 결과: " + finalResult); // 출력 결과: 최종 결과: 9
}
}
3. 교환적 응집도(Communication Cohesion)
- 동일한 입력과 출력을 사용하여 다른 기능을 사용하는 활동들이 모여있는 경우
- 메소드 호출에 공통된 파라미터가 입력되는 경우
- 순차적 응집도와 차이점은 처리 순서가 중요하지 않음
public class CommunicationCohesionExample {
private int sharedData;
public void setData(int data) {
this.sharedData = data;
}
public int getData() {
return sharedData;
}
public void processData() {
// sharedData를 이용하여 처리 작업 수행
System.out.println("Processed data: " + sharedData);
}
public void displayData() {
// sharedData를 출력
System.out.println("Data: " + sharedData);
}
}
// 모든 메서드들이 sharedData라는 공유 데이터를 활용하고, 서로 데이터를 주고 받으며 상호작용한다
4. 절차적 응집도(Procedural Cohesion)
- 모듈이 다수 관련 기능을 가질 때 모듈 안의 구성요소가 그 기능을 순차적으로 수행할 경우
- 하나의 클래스에 있는 메서드들을 여러 개 호출하는 경우
public class ProceduralCohesionExample {
public void stepOne() {
// Step One 수행
System.out.println("Step One");
}
public void stepTwo() {
// Step Two 수행
System.out.println("Step Two");
}
public void stepThree() {
// Step Three 수행
System.out.println("Step Three");
}
public void processSteps() {
// 절차적으로 순차적으로 Step들 수행
stepOne();
stepTwo();
stepThree();
}
public static void main(String[] args) {
ProceduralCohesionExample example = new ProceduralCohesionExample();
example.processSteps(); // 출력 결과: Step One, Step Two, Step Three
}
}
5. 시간적 응집도(Temporal Cohesion)
- 각 기능 요소들이 순서에 상관없이 특정 시점에 반드시 수행되는 경우
- 연관된 기능이라기보단 특정 시간에 처리되어야 하는 활동들을 한 모듈에서 처리할 경우
public class TemporalCohesionExample {
private int counter = 0;
public void incrementCounter() {
// 카운터 값을 1 증가시킴
counter++;
}
public void displayCounter() {
// 현재 카운터 값을 출력함
System.out.println("Counter: " + counter);
}
public static void main(String[] args) {
TemporalCohesionExample example = new TemporalCohesionExample();
// 동일한 시간에 incrementCounter()와 displayCounter()가 호출되고 있음
example.incrementCounter(); // 카운터 값을 1 증가시킴
example.displayCounter(); // 현재 카운터 값을 출력함
}
}
6. 논리적 응집도(Logical Cohesion)
- 유사한 성격을 갖거나 특정 형태로 분류되는 처리 요소들이 한 모듈에서 처리되는 경우
- 논리적으로 비슷한 기능을 수행하지만 서로의 관계는 밀접하지 않은 형태
public class LogicalCohesionExample {
private int sum;
private int average;
private int count;
public void addNumber(int number) {
// 숫자를 합계에 추가
sum += number;
// 추가된 숫자 개수 증가
count++;
}
public void calculateAverage() {
// 합계에서 평균을 계산
average = sum / count;
}
public int getAverage() {
// 평균 값을 반환
return average;
}
public static void main(String[] args) {
LogicalCohesionExample example = new LogicalCohesionExample();
example.addNumber(10);
example.addNumber(20);
example.addNumber(30);
example.calculateAverage();
int averageResult = example.getAverage();
System.out.println("평균: " + averageResult); // 출력 결과: 평균: 20
}
}
// 메서드들이 같은 도메인인 숫자 처리를 수행하며, 공통된 목적인 평균 계산을 가지고 있다
7. 우연적 응집도(Coincidental Cohesion)
- 가장 좋지 않은 응집도
- 모듈 내부의 각 구성 요소들이 서로 관련 없는 요소로만 구성된 경우
public class CoincidentalCohesionExample {
public void printName(String name) {
// 이름을 출력하는 기능
System.out.println("이름: " + name);
}
public int addNumbers(int a, int b) {
// 두 숫자를 더하여 결과를 반환
return a + b;
}
public void sendMessage(String message) {
// 메시지를 전송하는 기능
System.out.println("메시지: " + message);
}
public void processUserData(String name, int age) {
// 사용자 데이터를 처리하는 기능
System.out.println("이름: " + name + ", 나이: " + age);
}
public static void main(String[] args) {
CoincidentalCohesionExample example = new CoincidentalCohesionExample();
// 모듈 내의 메서드들이 관련 없이 무작위로 호출됨
example.printName("John");
int result = example.addNumbers(10, 20);
example.sendMessage("Hello");
example.processUserData("Alice", 25);
}
}
참고 블로그
[SW공학] 결합도(Coupling)와 응집도(Cohesion)
[설계 용어] 응집도(Cohesion)와 결합도(Coupling)
'CS(Computer Science)' 카테고리의 다른 글
클라우드 (0) | 2023.08.10 |
---|---|
저장 프로시저(Stored Procedure) (0) | 2023.08.06 |
[데이터베이스] 데이터베이스 설계 단계 (0) | 2023.07.16 |
[데이터베이스] 이상 현상(Anomolay) (0) | 2023.07.09 |
CS Study : 11주차 - 프로세스 동기화 (0) | 2023.01.29 |