본문 바로가기

CS(Computer Science)

결합도(Coupling)와 응집도(Cohesion)

모듈화(Modularization)

  • 소프트웨어 개발에서 코드를 각 기능별로 나누는 것
  • 프로그램이 효율적으로 관리될 수 있도록 시스템을 분해하고 추상화함으로써 소프트웨어 제품의 성능을
    향상시키거나 시스템의 수정 및 재사용, 유지 관리를 용이하게 하는 기법

모듈(Module)

  • 기능별로 나누어진 모듈화의 결과
  • 소프트웨어 내의 프로그램 또는 작업 단위

 

독립성

  • 모듈은 주어진 기능만을 독립적으로 수행하며 다른 모듈과 적게 연관되어야 함
  • 모듈의 결합도와 응집도로 측정
    • 결합도는 낮고, 응집도가 높을수록 독립성이 높음
  • 독립성이 높을수록 좋은 모듈
    • 해당 모듈을 수정해도 다른 모듈에 미치는 영향이 감소하기 때문

 

결합도(Coupling)

  • 서로 다른 모듈 간 상호 의존하는 정도 또는 두 모듈 사이의 연관된 관계
  • 낮을수록 좋음

결합도가 높은 B 모듈의 경우 모듈 안에 있는 기능을 수정하게 되면 연관된 다른 모듈들의 소스도 확인하면서 해야 하는 단점이 있다.

단계 종류

 

세기 종류 내용
약함




   





강함
자료 결합도
(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)

  • 모듈 내부에서 구성 요소 간에 밀접한 관계를 맺고 있는 정도
  • 높을수록 좋음

a라는 기능이 A 모듈 안에 모여있으면 수정하기 편하지만 다른 모듈에 흩어져 있으면 수정하기가 힘들어 진다.

 

단계 종류

세기 종류 내용
강함







   








약함
기능적 응집도
(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)

 


결합도와 응집도.pptx
0.37MB