단일 책임 원칙의 정의
단일 책임 원칙은 '하나의 모듈은 하나의 일만 해야 한다'는 의미로 자주 오해되곤 한다.
이는 흔히 알려진 '하나의 함수는 하나의 일만 해야 한다'는 원칙과의 혼용되어 발생한 문제이다.
위의 원칙은 함수를 설계할 때 사용되는 원칙으로 단일 책임 원칙보다 저수준에서 사용된다.
단일 책임 원칙의 진짜 정의는 아래와 같다.
단일 모듈은 변경의 이유가 하나, 오직 하나뿐이어야 한다.
그렇다면 모듈을 변경하는 이유는 무엇일까?
그것은 바로 사용자가 이 모듈에 기대하는 책임이 변화할 때이다.
만약 사용자가 둘 이상이라 가정하면 모듈이 변화하는 이유는 두 가지 이상이 될 수 있다.
- A 사용자가 이 모듈에 기대하는 책임이 변화한 경우
- B 사용자가 이 모듈에 기대하는 책임이 변화한 경우
즉, 위와 같이 하나의 모듈에 둘 이상의 사용자가 존재할 경우 단일 책임 원칙은 위배된다.
그런데 사용자가 여러 명이어도 단일 책임 원칙이 위배되지 않는 경우가 있다.
그것은 바로 모든 사용자가 이 모듈에 같은 책임을 기대하는 경우이다.
여기서, Actor라는 단어를 정의할 필요가 있다.
Actor는 특정 모듈에 동일한 책임을 기대하는 사용자들의 집합이다.
위의 예시에서 보았듯이 하나의 Actor는 단일 책임원칙을 위배하지 않는다.
단일 책임 원칙을 다시 정의하면 아래와 같다.
단일 모듈은 하나의 Actor에 대해서만 책임져야 한다.
단일 책임 원칙의 위배
문제 1: 우발적 중복
위와 같이 Employee 모듈을 정의한다.
회계팀과 인사팀은 Employee 모듈을 접근하고 CalculatePay와 ReportHours는 모두 CheckTime을 사용한다.
이 클래스의 Actor와 Responsibility를 정리하면 아래와 같다.
Actor | Responsibility |
회계팀 | CalculatePay |
인사팀 | ReportHours |
이 때 회계팀에서 월급 계산 시 시간을 확인하는 방식을 변경한다면 회계팀은 CheckTime 함수를 변경할 것이다.
CheckTime을 ReportHours가 사용한다는 사실을 간과하는 순간 인사팀의 ReportHours 알고리즘은 변경된다.
이 문제는 하나의 모듈에 두 개 이상의 Actor가 존재할 때 발생한다.
단일 책임 원칙은 서로 다른 Actor가 의존하는 코드를 분리하라고 말한다.
문제 2: Merge & Conflict
Merge 중 Conflict은 Git과 같은 형상관리 툴을 사용할 때 흔히 겪는 문제이다.
위의 사례에서 회계팀과 인사팀은 CalculatePay와 ReportHours를 개발하기 위해 Employee 모듈을 CheckOut 할 것이다.
개발 중 CheckTime과 같은 공통적인 함수의 변경이 비슷한 시점에 발생하면 Merge중 Conflict이 발생한다.
Conflict은 수정 과정에서 Bug를 양산하기 쉬우며 개발 속도를 저하시킨다.
즉, 단일 책임 원칙의 위배는 다양한 Bug와 개발 속도 저하를 일으킬 수 있다.
이 문제를 벗어나는 방법은 서로 다른 Actor를 뒷받침하는 코드를 서로 분리하는 것이다.
결론
단일 책임 원칙은 Class와 Method 수준의 원칙이다.
이해를 돕기 위해 이 포스팅에서 모듈이라는 단어를 사용했지만 여기서의 모듈은 Class를 의미한다.
하지만 단일 책임 원칙의 의미는 고수준에서도 다른 형태로 등장한다.
Component 수준에서는 공통 폐쇄 원칙 (Common Closure Principle)이다.
Architecture 수준에서는 Architecture의 경계를 정의하는 변경의 축 (Axis of Change)이다.
'SW Engineering > Architecture' 카테고리의 다른 글
Architecture와 Programming Paradigm (0) | 2021.09.28 |
---|---|
Architecture란? (0) | 2021.09.28 |