# 7장 SRP: 단일 책임 원칙

SOLID 원칙 중 의미가 가장 잘 전달되지 못한 원칙이다. `함수는 반드시 하나의 일만 해야 한다` 는 원칙은 함수를 리팩토링하는 저수준에서 사용하는 원칙이다. **이것은 SRP가 아니다.**

역사적으로 SRP는 다음과 같다.

> 단일 모듈은 변경의 이유가 하나 뿐이어야 한다.

여기서 '변경의 이유'는 **해당 변경을 요청하는 한 명 이상의 사람(액터)** 을 가리킨다.

따라서 최종적으로 SRP는 다음과 같다.

> 하나의 모듈은 하나의 액터에 대해서만 책임져야 한다.

'모듈'은 **소스 파일**을 말한다. 코드를 소스 파일에 저장하지 않는 경우엔 함수와 데이터 구조로 구성된 **응집된 집합**을 말한다.

응집(cohesive)이라는 단어가 SRP를 암시한다. 단일 액터를 책임지는 코드를 묶어주는 힘이 **응집성(cohesion)** 이다.

원칙을 위반하는 징후들을 통해 원칙을 이해해보자.

## 징후 1: 우발적 중복

급여 애플리케이션의 Employee 클래스는 3가지 메서드 `calculatePay()`, `reportHours()`, `save()` 를 가진다. 3가지 메서드는 서로 다른 3명의 액터를 책임진다.

* `calculatePay()` : 회계팀에서 CFO 보고를 위해 사용
* `reportHours()` : 인사팀에서 COO 보고를 위해 사용
* `save()` : DBA가 CTO 보고를 위해 사용

따라서 Employee 클래스는 SRP를 위반한다.

3가지 메서드가 단일 클래스에 배치해서 결합되었기 때문에 CFO의 요구사항이 COO가 의존하는 무언가에 영향을 줄 수 있다.

이러한 문제는 서로 다른 액터가 의존하는 코드를 가까이 배치했기 때문에 발생한다. SRP는 서로 다른 액터가 의존하는 코드를 서로 분리하라고 말한다.

## 징후 2: 병합

서로 다른 개발자가 Employee 클래스를 변경하려고 할 때 이들의 변경사항은 서로 충돌한다. 많은 사람이 서로 다른 목적으로 동일한 소스를 변경하는 경우 충돌이 일어난다. 따라서 서로 다른 액터를 뒷받침하는 코드는 분리되어야 한다.

## 해결책

가장 확실한 해결책은 **데이터와 메서드를 분리하는 것**이다. 메서드가 없는 `EmployeeData` 클래스를 만들어 `PayCalculator`, `HourReporter`, `EmployeeSaver` 클래스가 공유하도록 만들고 세 클래스가 서로의 존재를 모르게 만들면 '우연한 중복'을 피할 수 있다.

이 방법은 개발자가 3가지 클래스를 인스턴스화하고 추적해야 한다는 단점이 있다. 이때 **파사드(facade) 패턴** 을 사용한다. EmployeeFacade 클래스를 만들어서 3가지 클래스의 객체를 생성하고 요청된 메서드를 갖는 객체로 위임하는 일을 책임진다.

중요한 비즈니스 규칙을 데이터와 가깝게 유지하려고 하는 경우, `Employee` 클래스에 중요한 메서드를 그대로 유지하고 `Employee` 클래스를 덜 중요한 나머지 메서드들에 대한 파사드로 사용할 수 있다.

이 경우 `Employee` 클래스에서 `HourReporter`, `EmployeeSaver` 클래스의 객체를 생성하고 메서드를 해당 객체로 위임한다.

## 결론

단일 책임 원칙은 메서드와 클래스 수준의 원칙이다.
