설계 원칙

좋은 SW 시스템은 깔끔한 코드로부터 시작한다.
좋은 벽돌을 사용하지 않으면 아키텍처가 좋고 나쁨은 중요치 않다.
반대로 좋은 벽돌을 사용하더라도 엉망으로 만들 수 있다.

-> 따라서 좋은 벽돌로 좋은 아키텍처를 정의하는 원칙이 필요한데...
그것이 SOLID이다.

SOLID 원칙은 함수와 데이터 구조를 클래스로 배치하는 방법 그리고 이들 클래스를 서로 결합하는 방법을 설명해준다.

SOLID의 목적

  • 변경에 유연하다
  • 이해하기 쉽다
  • 많은 SW 시스템에 사용할 수 있는 컴포넌트의 기반이 된다.

'중간 수준'이라 함은 프로그래머가 이들 원칙을 모듈 수준에서 작업할 때 적용할 수 있다는 뜻이다.

SRP

단일 책임 원칙
이름만 들으면 모든 모듈이 단 하나의 일만 해야 한다는 의미로 받아들이기 쉽다.
-> 함수는 하나의 일만 해야 한다 가 정확하다.

모듈 = "소스 파일"

원칙을 위반하는 징후

우발적 중복

급여 App의 Employee Class
해당 클래스는 calculatePay(), reportHours(), save() 메서드를 갖는다.

  • calculatePay() 는 회계팀에서 기능을 정의하며, DFO 보고를 위해 사용
  • reportHours() 는 인사팀에서 기능을 정의하고 사용하며, COO 보고를 위해 사용
  • save() 는 DBA가 기능을 정의하고, CTO 보고를 위해 사용

각각의 메서드를 갖고 있는 Employee라는 단일 클래스에 3종류의 actor가 결합되었다.

예를 들어, calculatePay()와 ㄱeportHours()가 초과근무를 제외한 업무 시간을 계산하는 알고리즘을 공유한다고 해보자
그리고 중복을 회피하기 위해 regularHours()라는 메서드를 넣었다고 가정하자

이제 CFO 팀에서 초과 근무를 제외한 업무 시간을 계산하는 방식을 수정하기로 했다.
반면 인사를 담당하는 COO 팀에서는 초과 근무를 제외한 업무 시간을 CFO 팀과는 다른 목적으로 사용하기에, 변경을 원치 않는다.

  1. 해당 업무를 받은 개발자는 calculatePay() 메서드가 regularHours()를 호출한다는 것을 발견!
  2. 하지만 reportHours() 메서드에서도 호출된다는 것을 발견하지 못함..

개발자는 업무를 테스트하고 변경했다.
CFO 팀에서는 기능을 검증하고 시스템은 배포된다.
하지만 COO 팀에서는 이러한 사실을 알지 못했고, reportHours() 메서드를 사용하고 나서야 잘못된 수치들을 확인한다.

-> 누가, 어떤 목적으로 사용하는지에 대한 기능을 제공을 단일로 책임? , 즉 Class가 단일 actor에 대한 책임을 진다?

병합

소스 파일에 다양하고 많은 메서드를 포함하면 병합이 자주 발생할 것이다.
이들 메서드가 서로 다른 actor를 책임진다면 병합이 발생할 가능성은 더 높다

DBA가 속한 CTO팀에서 DB의 Employee Table Schema를 수정하기로 했다.
동시에 COO 팀에서는 reportHours() 메서드의 보고서 포맷을 변경하기로 했다.

서로 다른 개발자가 Employee Class를 체크아웃 받을 후 적용할 것이다.
이러한 변경사항들은 분명히 충돌한다.

-> 이 문제를 벗어나기 위해서는 서로 다른 actor를 책임지는 코드를 서로 분리하는 것이다.

해결책

가장 확실한 해결책은 데이터와 메서드를 분리하는 방식이다.
즉, 아무런 메서드가 없는 간단한 데이터 구조인 EmployeeData Class를 만들어 세개의 Class가 공유한다.
각 클래스는 자신의 메서드에 반드시 필요한 소스 코드만을 포함한다.
각 클래스는 서로의 존재를 모른다.

하지만 개발자가 3가지 Class를 인스턴스화하고 추적해야 한다는 게 단점이다.
이러한 난관을 피하기 위해 퍼싸드 패턴을 사용한다.

EmployeeFacade에 코드는 거의 없다. 이 클래스는 3개의 클래스의 객체를 생성하고, 요청된 메서드를 가지는 객체로 위임하는 일을 책임진다.

결론

SRP는 메서드와 클래스 수준의 원칙이다. 하지만 이보다 상위 두 수준에서도 다른 형태로 다시 등장한다.
컴포넌트 수준에서는 공통 폐쇄 원칙
아키텍처 수준에서는 아키텍처 경계의 생성을 책임지는 변경의 축이 된다.

+ Recent posts