소프트웨어 엔지니어링에서 변경은 본질적으로 좋지 않으므로 변경을 위한 변경은 삼가야 하지만 변화에 대응할 수는 있어야 합니다. 소프트웨어 제품 마다 비용이 다른 이유 중 하나가 바로 변경에 유연하게 대응할 수 있냐에 따라 큰 비용이 발생할 수 있기 때문입니다. 변경에 필요한 비용이 많이 든 제품의 한 가지 공통점은 하나의 동작을 변경하려고 할 때 다른 모듈까지 변경해야 한다는 것입니다. 한 모듈을 변경할 때 다른 모듈도 변경해야 하는 경우 두 모듈은 특정 변경과 관련하여 강한결합이 있다고 합니다.
예를 들어, 호출 함수는 호출된 함수의 이름 변경과 관련하여 호출된 함수에 결합합니다.
```
class ModuleA {
caller() {
called() // ModuleB의 동작
}
}
calss ModuleB {
called() { // 이 이름을 변경하려면 ModuleA의 caller동작도 변경해야 합니다.
… // 본문 형식을 변경해도 ModuleA의 caller동작의 변경이 필요하지 않습니다.
}
}
```
위의 두 번째 주석은 모듈 간의 결합의 중요한 뉘앙스를 강조합니다. 위의 코드를 보기만 해서 단순히 두 모듈이 결합하여 있다고 말할 수 없으며, 어떤 변경 사항과 관련하여 결합하여 있다고 말해야 모듈 간 결합이 있다고 말할 수 있습니다. 두 모듈 간 절대 일어나지 않는 변화는 마치 언덕 꼭대기에 있는 바위가 마을을 무너뜨리기 위해 굴러 내려오지 않는 것과 같습니다. 하지만 소프트웨어 제품의 수명이 길어지면 길어질수록 변경의 중요도는 높아지기는 합니다.
결합을 분석하는 것은 단순히 프로그램의 소스 코드를 보는 것만으로는 할 수 없다는 것이 중요합니다. 두 요소가 결합하여 있는지를 판단하려면 먼저 어떤 변화가 일어났거나 일어날 가능성이 있는지 알아야 합니다. (프로파일 도구나, 커밋에서 어떤 파일 쌍이 함께 나타나는지 살펴보세요. 이러한 파일은 강한결합 된 파일입니다.)
위 코드처럼 결합이 두 개의 모듈 사이에만 존재한다면 비용이 그리 많이 들지는 않을 것입니다만, 강한결합은 두 가지 속성을 가지고 있습니다.
1️⃣ 1-N : 하나의 모듈 변경과 관련하여 다른 모듈과도 얼마든지 결합할 수 있습니다.
2️⃣ 스노우볼⛄️ : 하나의 모듈에서 다른 모듈로 변화가 파급되면, 변화가 또 다른 변화를 일으킬 수 있다.
1️⃣1-N 같은 경우는 툴링을 통해 어느 정도 해결할 수 있습니다. 함수 이름과 모든 호출자를 변경하는 자동화된 리팩터링이 있다면 한 번에 변경할 수 있습니다. 2️⃣ 스노우볼⛄️🥶은 상당히 더 큰 문제입니다. 말 그대로 스노우볼이 굴러 굴러 집을 무너뜨릴 수 있는 가장 위험한 요인이 될 수 있습니다.
소프트웨어 제품의 지속 가능성을 고려한다면 결합의 1️⃣ 1-N 속성부터 조금씩 바꿔 가는 것이 좋을 것 같고 눈덩이가 크게 불어나지 않는 선에서는 2️⃣ 속성이 제품 어느 곳에 잠재되어 있는지 알아보는 것이 좋을 것 같습니다😀