카테고리 없음

C++ 결합도

dkuen 2026. 3. 17. 22:12

결합도는 모듈 또는 클래스 간의 의존성을 나타냅니다.

일반적으로 결합도는 낮을수록 좋은 코드입니다.

 

결합도가 높으면 각 모듈 간 의존성이 강해져, 하나의 모듈이 변경될 때, 다른 모듈도 영향을 받게 됩니다.

 

결합도 실제 예시

자동차와 엔진의 관계를 코드로 구현해 봅시다.

  1. 자동차는 초기에 Engine이 장착되어 있습니다.
  2. 자동차 시동이 걸리면 엔진이 동작한다고 출력합니다.
    하지만 이제 엔진의 종류가 다양해졌고, 자동차가 여러 종류의 엔진을 지원해야 합니다.

결합도가 높은 코드

자동차 클래스가 디젤 엔진 클래스를 직접 포함합니다.

이 구조는 아래와 같은 문제점이 있습니다.

  1. 새로운 전기 엔진을 추가하려면 자동차 클래스도 수정해야합니다
  2. 변경이 잦은 경우 수정 범위가 커지고 유지 보수가 어려워집니다.
//기능 추가 전 예시코드

#include <iostream>
#include <string>

using namespace std;

// 기존 Engine 클래스
class Engine {
public:
    string state;

    Engine() : state("off") {}

    void start() {
        state = "on";
        cout << "Engine started" << endl;
    }
};

class Car {
public:
    Engine engine;

    void startCar() {
        if (engine.state == "off") {
            engine.start();
            cout << "Car started" << endl;
        }
    }
};
//기능 추가 후 예시코드

#include <iostream>
#include <string>

using namespace std;

// 기존 Engine 클래스
class Engine {
public:
    string state;

    Engine() : state("off") {}

    void start() {
        state = "on";
        cout << "Engine started" << endl;
    }
};

// 새로운 ElectricEngine 클래스 (기존 Engine과는 별도)
class ElectricEngine {
public:
    string state;

    ElectricEngine() : state("off") {}

    void start() {
        state = "on";
        cout << "Electric Engine running silently" << endl;
    }
};

// 기존 Car 클래스 수정
class Car {
public:
    Engine engine; // Car 클래스는 여전히 Engine 클래스에 강하게 의존

    void startCar() {
        if (engine.state == "off") {
            engine.start();
            cout << "Car started" << endl;
        }
    }
};

 

결합도가 높기 때문에 자동차 클래스를 직접 수정해야하고, 기능이 추가되어도 수정하기 어렵습니다.

 

결합도가 낮은 코드

결합도를 낮추기 위해 자동차 클래스가 특정 엔진을 직접 포함하지 않고 인터페이스를 활요하는 방법을 사용할 수 있습니다.

  1. 자동차 클래스는 엔진 인터페이스에만 의존하므로, 새로운 엔진을 추가해도 자동차 코드를 수정할 필요가 없습니다.
  2. 확장성이 높아지며, 다양한 엔진을 유연하게 지원할 수 있습니다.
//기능 추가 전 예시코드

#include <iostream>
#include <memory>
#include <string>

using namespace std;

class Engine {
public:
    virtual void start() = 0;
    virtual ~Engine() = default;
};

class DieselEngine : public Engine {
public:
    void start() {
        cout << "Diesel Engine started" << endl;
    }
};

class Car {
private:
    unique_ptr<Engine> engine; // 인터페이스에 의존하여 결합도 감소

public:
    Car(unique_ptr<Engine> eng) : engine(move(eng)) {}

    void startCar() {
        engine->start();
        cout << "Car started" << endl;
    }
};

int main() {
    auto engine = make_unique<DieselEngine>();
    Car myCar(move(engine));
    myCar.startCar();
    return 0;
}
//기능 추가 후 예시코드

#include <iostream>
#include <memory>

using namespace std;

// 공통 인터페이스 정의
class Engine {
public:
    virtual void start() = 0;
    virtual ~Engine() = default;
};

// DieselEngine 구현
class DieselEngine : public Engine {
public:
    void start() {
        cout << "Diesel Engine started" << endl;
    }
};

// 새로운 ElectricEngine 구현
class ElectricEngine : public Engine {
public:
    void start() {
        cout << "Electric Engine started silently" << endl;
    }
};

// Car 클래스는 Engine 인터페이스에만 의존
class Car {
private:
    unique_ptr<Engine> engine;

public:
    Car(unique_ptr<Engine> eng) : engine(move(eng)) {}

    void startCar() {
        engine->start();
        cout << "Car started" << endl;
    }
};

int main() {
    // DieselEngine을 사용하는 경우
    auto dieselEngine = make_unique<DieselEngine>();
    Car dieselCar(move(dieselEngine));
    dieselCar.startCar();

    // ElectricEngine을 사용하는 경우
    auto electricEngine = make_unique<ElectricEngine>();
    Car electricCar(move(electricEngine));
    electricCar.startCar();

    return 0;
}