> [원문](https://ubiklab.net/posts/low-coupling-high-cohesion/?source=post_page-----d36369fb1be9--------------------------------)
![[Pasted image 20250211091342.png]]
좋은 설계는 **낮은 결합도(low coupling)**와 **높은 응집도(high cohesion)**를 가진다. 이는 프로그램의 구성요소가 적은 수의 외부 의존성을 가지며, 의미적으로 유사한 작업들의 처리를 담당한다는 것을 의미한다.
## 결합도(Coupling)
![[Pasted image 20250211091604.png]]
**결합도(coupling)** - 프로그램 모듈 간의 상호 의존성의 방식과 정도를 나타낸다. 이는 모듈 간의 연결 강도이며, 서로 다른 서브프로그램이나 모듈이 얼마나 상호 의존적인지를 측정하는 척도이다.
**높은 결합도(High coupling)** - 심각한 단점으로 간주된다. 모듈의 로직 이해를 어렵게하고, 수정이 까다로우며, 독립적인 테스트와 개별적인 재사용이 어렵기 때문이다.
**낮은 결합도(Low coupling)** - 반대로 잘 구조화되고 잘 설계된 시스템의 특징이며, **높은 응집도(high cohesion)**와 결합될 때 전반적으로 좋은 가독성과 유지보수성을 제공한다.
**낮은 결합도(Log Coupling)**는 시스템 간의 결합도를 낮게 유지하면서 객체들 간의 책임을 분배할 수 있게 해주는 원칙이다.
**결합의 정도(coupling)**는 한 요소가 다른 요소들과 얼마나 강하게 연결되어 있는지, 또는 다른 요소들에 대해 얼마나 많은 정보를 가지고 있는지를 측정하는 척도이다.
낮은 결합도(또는 약한 결합)를 가진 요소는 적은 수의 다른 요소들에 의존하며 다음과 같은 특징을 가진다:
- 클래스(서브 시스템) 간의 의존성이 적음
- 한 클래스(서브시스템)가 다른 클래스(서브시스템)의 변경에 덜 영향을 받음
- 서브시스템의 재사용성이 높음
## 결합도의 종류(Types of Coupling)
![[Pasted image 20250211092149.png]]
출처: https://www.javatpoint.com/software-engineering-coupling-and-cohesion
**내용 결합도(content coupling)**
* 한 모듈이 다른 모듈의 내부 구현에 의존하거나 이를 변경함 (예: 다른 모듈의 로컬 데이터를 사용)
* 두 번째 모듈의 동작이 변경되면 첫 번째 모듈을 다시 작성해야 함
**공통 결합도(common coupling)**
* 두 모듈이 공통 데이터를 사용함 (예: 전역 변수)
* 공유 자원이 변경되면 이를 사용하는 모든 모듈의 변경이 필요함
**외부 결합도(external coupling)**
* 두 모듈이 외부에서 강제된 데이터 형식, 통신 프로토콜 등을 사용
* 일반적으로 외부 요소(도구, 장치 등)로 인해 발생
**제어 결합도(control coupling)**
* 한 모듈이 다른 모듈의 동작을 제어함
* 무엇을 어떻게 해야 하는지에 대한 정보가 전달됨
**스탬프 결합도(stamp coupling/data-structured coupling)**
* 모듈들이 동일한 데이터 구조를 사용하지만 각각 일부분만 사용
* 구조 변경 시 변경된 부분을 사용하지 않는 모듈까지 수정이 필요할 수 있음
**데이터 결합도(data coupling)**
* 모듈들이 매개변수 등을 통해 데이터를 공유
* 작은 기본 단위의 데이터만 모듈 간에 공유됨
**메시지 결합도(message coupling)**
* 모듈들이 오직 매개변수나 메시지 전달을 통해서만 통신
* 상태가 분산되어 있음
**무결합(no coupling)**
* 모듈들 간에 전혀 상호작용이 없음
## 데메테르의 법칙
_**최소 지식 원칙**_
![[Pasted image 20250211092954.png]]
**데메테르의 법칙(Law of Demeter, LoD)**은 소프트웨어 개발, 특히 객체지향 프로그래밍에서 객체(모듈) 간의 상호작용에 제한을 두는 설계 규칙들의 집합이다.
일반적으로, 데메테르의 법칙은 **느슨한 결합도(loose coupling)**의 특수한 경우다. 이 규칙들은 1987년 말 미국 매사추세츠 주 보스턴의 노스이스턴 대학교에서 제안되었다.
간단히 말해서, 각 프로그램 모듈은:
* 다른 모듈들에 대해 제한된 지식만을 가져야 함: 이 모듈과 "직접적인" 관련이 있는 모듈들만 알아야 함
* 자신이 알고 있는 "친구" 모듈들과만 상호작용해야 하며, 모르는 모듈들과는 상호작용하지 말아야 함
* 직접적인 "친구"들에게만 접근해야 함
![[Pasted image 20250211093056.png]]
일반적인 규칙 설명: ***객체 A가 객체 B에 접근할 수 있고 객체 B가 객체 C에 접근할 수 있다고 해서, 객체 A가 객체 C에 직접 접근할 수 있어서는 안 됩니다.***
따라서, `a.b.Method()`와 같은 코드는 데메테르의 법칙을 위반하는 반면, `a.Method()`와 같은 코드는 올바른 것이다.
**장점**
데메테르의 법칙을 준수하여 개발된 코드는 테스트 작성이 더 쉬워지고, 개발된 소프트웨어의 유지보수가 덜 복잡하며, 코드 재사용 가능성이 더 높아진다. 객체들이 다른 객체들의 내부 구조에 덜 의존하기 때문에, 호출하는 객체(클라이언트)의 수정 없이도 객체 컨테이너를 변경할 수 있다.
**단점**
데메테르의 법칙의 단점은 내부 컴포넌트들에 대한 메서드 호출을 전달하기 위해 많은 수의 작은 어댑터 메서드(위임자)를 만들어야 할 때가 있다는 것이다.
## 응집도(Cohesion)
![[Pasted image 20250211093256.png]]
출처: [https://medium.com/the-ready/human-networks-coupling-cohesion-encapsulation-1f415e775820](https://medium.com/the-ready/human-networks-coupling-cohesion-encapsulation-1f415e775820)
**응집도**나 **응집력**(cohesion)은 모듈 내부 요소들 간의 연관성 정도를 나타내는 척도이다. 이는 특정 프로그램 모듈이 수행하는 작업들이 서로 얼마나, 그리고 어떤 방식으로 연관되어 있는지를 나타낸다.
![[Pasted image 20250211093344.png]]
> 스티브 맥코넬의 말을 인용하자면, "응집도는 클래스의 모든 메서드나 메서드의 모든 부분이 주요 목적에 얼마나 잘 부합하는지, 즉 클래스가 얼마나 잘 초점이 맞춰져 있는지를 특징짓습니다."
**높은 응집도**(High cohesion)를 가진 객체(서브시스템)는 책임들이 서로 잘 조화를 이루며, 과도한 양의 작업을 수행하지 않는 것으로 간주된다.
**낮은 응집도**(low cohesion)를 가진 클래스는 서로 연관성이 없는 많은 이질적인 기능이나 책임들을 수행한다. 이러한 클래스들은 다음과 같은 문제들을 야기하므로 만들지 않는 것이 좋다:
* 이해하기 어려움
* 재사용이 복잡함
* 유지보수가 어려움
* 신뢰성이 낮고 지속적인 변경에 노출됨
낮은 응집도를 가진 클래스들은 일반적으로 너무 "**추상적**"이거나 다른 객체들에게 쉽게 분배할 수 있는 책임들을 수행한다.
## 응집도의 종류(Types of Cohesion)
**우연적 응집도(coincidental cohesion)**
* 모듈의 부분들이 아무런 의미 없이 무작위로 그룹화됨
* 모듈이라는 것 자체 외에는 이들을 묶는 것이 없음
**논리적 응집도(logical cohesion)**
* 모듈의 부분들이 논리적으로 같은 문제와 관련됨
* 하지만 부분들의 성격은 서로 다를 수 있음
**시간적 응집도(temporal cohesion)**
* 모듈의 부분들이 프로그램에서 보통 같은 시간에, 인접해서 사용됨
**절차적 응집도(procedural cohesion)**
* 모듈의 부분들이 항상 특정한 순서로 사용됨
**통신적 응집도(communication cohesion)**
* 모듈의 부분들이 같은 데이터를 다룸
**순차적 응집도(sequential cohesion)**
* 한 모듈 부분의 출력이 다른 부분의 입력 데이터가 됨
**기능적 응집도(functional cohesion)**
* 모듈의 부분들이 모듈이 담당하는 하나의 명확한 작업을 해결하는데 집중됨
#CleanCode