응집도와 결합도를 알아가기 전 모듈에 대하여 알고 들어가 봅시다.
모듈(Module)
응집도와 결합도는 프로그램의 모듈과 모듈간의 관의 관계에 대한 개념입니다. 따라서 프로그램에 있어서 모듈의 개념을 이해하는 것이 먼저입니다.
모듈은 프로그램에서 하나의 기능을 수행하는 단위입니다.
프로그래밍 관련 용어들을 레고에 빗대어 이해해보도록 합니다. 프로그램 코드 한 줄 한 줄이 레고 블럭 하나라면, 모듈은 그 블럭들을 조립하여 만든 하나의 '기능'을 수행하는 덩어리라고 할 수 있습니다. 이러한 모듈들이 합쳐져서 하나의 큰 레고 작품이 탄생하는 것입니다.
즉 프로그램의 기능을 독립적인 부품으로 분리한 것이 모듈이라고 할 수 있다. 프로그램을 짤 때 모듈화 한다는 것은, 작은 기능 단위들을 모듈화하여 유지 보수와 타 프로그램에서의 코드 재사용을 손쉽게 하고자 하는 것을 의미합니다.
사람이라는 프로그램을 만들 때, 걷기 기능, 뛰기 기능, 공부하기 기능 등과 신체 부위로 모듈을 만들어서 main 메소드에 합치면 그게 사람을 실체화 하는 것이라고 생각이 됩니다.
응집도(Cohesion)
응집도는 한 모듈 내에 존재하는 함수, 데이터 등의 구성 요소들 사이의 밀접한 정도를 나타냅니다. 응집도가 높은 모듈은 하나의 모듈 안에 필요한 함수나 데이터와 같은 구성 요소들이 똘똘 뭉쳐서 존재한다. 반대로 응집도가 낮은 모듈은 모듈 내부에 서로 관련 없는 함수나 데이터들이 존재하거나 관련성이 적은 여러 기능들이 하나의 모듈 안에 있게된다. 가끔 초보 개발자들의 코드를 리뷰하다 보면 하나의 클래스 안에 수천 라인의 온갖 기능들을 때려 넣어서 작성되어 있는 것을 볼 수 있는데, 이는 그 모듈의 정체성이 없으며 응집도가 매우 낮다고 볼 수 있다. 응집도가 가장 높은 모듈은 하나의 모듈이 단일 기능 하나만을 담당하게끔 구성되어 있는 경우이다.
응집도는 정보 은닉과도 관계가 있으며, 응집도가 높은 모듈은 프로그램 전체에서 담당하는 기능을 수행하는 것에 있어서는 다른 모듈과의 상호작용이 거의 없이도 단일 기능을 수행할 수 있게된다.
응집도는 기능적, 순차적, 교환적, 절차적, 시간적, 논리적, 우연적 응집도의 척도로 나타낼 수 있으며, 이에 따라서 모듈의 품질을 측정할 수 있게 된다. 기능적 응집도 쪽으로 갈 수록 좋은 품질이라고 할 수 있으며 우연적 응집도로 갈수록 나쁜 품질이라고 할 수 있다.
응집도에 대한 예시를 볼까요.
예시
public class Employee {
private String name;
private int age;
private int salary;
// 기본 생성자, 게터/세터 메소드 생략
public void increaseSalary(int amount) {
this.salary += amount;
}
public void changeName(String name) {
this.name = name;
}
public void promote(int amount) {
this.increaseSalary(amount);
this.age++;
}
}
위의 코드에서 Employee 클래스는 직원 정보를 저장하는 클래스입니다. 클래스 내부에는 이름(name), 나이(age), 연봉(salary) 변수가 있으며, 이 변수들을 다루기 위한 메소드들이 구현되어 있습니다.
increaseSalary 메소드는 직원의 연봉을 인상하는 메소드이고, changeName 메소드는 직원의 이름을 변경하는 메소드입니다. promote 메소드는 직원의 진급을 처리하는 메소드로, increaseSalary와 age 변수를 변경합니다.
이 경우 increaseSalary, changeName, promote 메소드는 모두 Employee 클래스의 멤버 변수들을 다루는 메소드로, 클래스 내부의 기능적 연관성이 높습니다. 따라서 Employee 클래스의 응집도는 높다고 할 수 있습니다.
반면에, Employee 클래스에 연락처 정보를 다루는 메소드가 있다면, 이는 Employee 클래스와 기능적으로 연관성이 낮기 때문에 응집도가 낮아지게 됩니다.
결합도
결합도는 하나의 모듈이 다른 모듈에 의존하는 정도를 나타냅니다. 결합도를 의존도라고 부르기도 합니다.
완제품 자동차 하나에는 여러 개의 모듈들(핸들, 엔진, 배터리 등)이 들어 있는 것처럼 하나의 프로그램에는 많은 모듈들이 존재합니다. 결합도는 이렇게 하나의 프로그램 안에서 각 모듈들이 서로 관련되어 의존하고 있는 정도를 뜻합니다.
각 모듈이 서로 관련성이 적어 결합도가 낮을수록 모듈간의 독립성이 높아집니다. 독립성이 높은 모듈은 서로의 기능에 영향을 미치지 않고 데이터만을 주고 받습니다. 때문에 전체 프로그램에서 일부 기능을 수정해야 할 때 그 기능을 담당하는 모듈만을 교체하면 되기 때문에 유지보수가 손쉽습니다. 자동차의 예에서 핸들을 교체하는데 엔진의 일부분이 관계가 있어서 엔진까지 같이 손봐야 한다면 이는 결합도가 높은 상태인 것입니다. 결합도가 낮아 모듈간의 독립성이 높아지게끔 설계 하는 것이 좋은 설계라고 할 수 있을 것입니다.
반대로 모듈간의 결합도가 높은 프로그램은 모듈이 기능을 수행하는 것에 여러 모듈들이 연관되어 있기 때문에 기능의 수정이 매우 어렵게 됩니다. 결합도는 자료, 스탬프, 제어, 외부, 공통, 내용 결합도의 척도로 나타낼 수 있습니다. 각 모듈들이 파라미터 등을 통해 데이터만 주고받는 자료 결합도가 가장 낮은 결합도이며 품질이 좋다고 할 수 있습니다. 한 모듈이 다른 모듈의 내부 동작에 관여하는 내부 결합도는 한 모듈이 일부 기능을 변경할 경우 다른 모듈의 변경이 필요하게 되어 결합도가 높으며 품질이 나쁘다고 할 수 있습니다.
예시
높은 결합도 예시
class Volume {
public static void main (String args []) {
Cylinder b = new Cylinder (15, 15, 15);
System.out.println (b.volume);
}
class Cylinder {
public int volume;
Cylinder (int length, int width, int height) {
this.volume = length * width * height;
}
}
}
두 개의 class에서 Cylinder 관련 class의 내용을 변경하게 되면 Volume에 대한 값도 변경되기 때문에 Cylinder class에 있는 volume 구하는 값을 Volume class로 옮겨서 응집도를 높이고 결합도를 낮춰야한다고 생각됩니다.
낮은 결합도 예시
public interface Vehicle {
void move();
}
public class Car implements Vehicle {
@Override
public void move () {
System.out.println ( "Car is moving" );
}
}
public class Traveler {
private Vehicle vehicle;
public Traveler(Vehicle v){
this.vehicle=v;
}
}
Traveler class가 Vehicle interface 에만 의존하고 있습니다. Traveler 클래스는 Vehicle 인터페이스를 매개변수로 받고, 이를 통해 Vehicle 인터페이스를 구현한 클래스들을 받아들일 수 있습니다.
따라서 Traveler 클래스는 Vehicle 인터페이스의 구현체가 무엇인지 알 필요가 없고, 이는 결합도를 낮추는 요소입니다. 또한, 만약 새로운 Vehicle 구현체가 추가되어도 Traveler 클래스를 변경할 필요가 없습니다. 이 또한 결합도를 낮추는 요소입니다.
High Cohesion and Loose Coupling
응집도는 높을수록 좋고 결합도는 낮을 수록 좋다는 "high cohesion loose coupling" 원칙이 항상 유효한 것은 아닙니다. 프로그램의 특성이나 상황에 따라 유연하게 적용해야 할 것입니다. 하지만 시스템 유지보수 측면에 있어서 모듈의 응집도는 높을수록, 결합도는 낮을 수록 유리한 것은 분명합니다. 프로그래밍을 배울 때 가장 먼저 배우게 되는 개념 중 하나지만 실제로 개발할 때 이를 염두하지 않고 코딩하는 사람들이 많다. 자신이 개발을 할 때는 이 중요성에 대해 잘 모를 것입니다. 하지만 남이 개발해놓은 엉망진창인 코드를 유지보수 해야할 때 비로소 체감하게 되는 것이 응집도와 결합도에 대한 것입니다.
여러가지 유명한 디자인 패턴들이 응집도를 높히고 결합도를 낮추기 위한 원칙으로 개발되어 있습니다. 이러한 디자인 패턴을 원칙을 잘 지키면 일단 기본적으로 따르게 될 개념일 것입니다. 하지만 개발자 스스로도 개발을 할 때 마음속에 "high cohesion loose coupling"을 신경 쓴다면 전체 프로그램의 코드 자체가 깔끔해 지고, 훌륭한 설계와 프로그램이 만들어질 것입니다.
소감
이러한 개념들은 직접 개발하면서 확인해봐야겠습니다. 또한 interface에 대한 이해가 전혀 없는데 interface와 class와의 관계에 대해서도 공부해서 더 나은 미래를 만들어 보겠습니다.
높은 응집도! 낮은 결합도를 가슴속에 새기며 개발에 임해보겠습니다.
출처
'코딩 개발 > Java' 카테고리의 다른 글
Java - 캡슐화 (Encapsulation) (0) | 2023.04.03 |
---|---|
Java - Heap & Stack 메모리 (feat. 예제를 통한 이해) (0) | 2023.04.02 |
Java - OOP(Object OrienTed Programming) (0) | 2023.04.02 |
Java - IDE 개념 및 간단한 사용법 (feat. Eclipse) (0) | 2023.04.02 |
Java - 신입 개발자가 알면 좋을 내용?(JDK, JRE, JVM...) (0) | 2023.03.29 |