SOLID 원칙 SRP

4200 단어 JavaJava

SOLID 원칙

객체지향 설계원칙

객체지향 설계 5대 원칙이라 부르는데

  • SRP (단일 책임 원칙)
  • OCP (개방-폐쇄 원칙)
  • LSP (리스코프 치환 원칙)
  • ISP (인터페이스 분리 원칙)
  • DIP (의존 역전 원칙)

을 말하고 앞자를 따서 SOLID 원칙 이라고 부른다

SOLID 원칙의 목적

  • 중간 수준의 소프트웨어 구조가 아래와 같도록 만드는 데 있다.
    이 원칙을 모듈 수준에서 작업할 때 적용 할 수 있다는 뜻이다.
    즉, 코드 수준보다는 조금 상위에서 적용되며 모듈과 컴포넌트 내부에서 사용되는 소프트웨어 구조를 정의하는 데 도움을 준다.

  • 변경에 유연하다.

  • 이해하기 쉽다.

  • 많은 소프트웨어 시스템에 사용될 수 있는 컴포넌트의 기반이 된다.

단일 책임 원칙(Single Responiblity Principle)

SRP란

  • 하나의 모듈은 하나의, 오직 하나의 액터(actor)에 대해서만 책임져야 한다.
  • 단일 모듈은 변경의 이유가 하나, 오직 하나뿐 이어야 한다!
  • 소프트웨어 시스템은 사용자와 이혜관계자를 만족시키기 위해 변경된다.

모듈이란?

  • 가장 단순한 정의는 '소스 파일'이다.
  • 하지만 일부 언어와 개발 환경에서는 코드를 소스 파일에 저장하지 않는데, 이러한 경우 모듈은 단순히 함수와 데이터구조로 구성된 응집된 집합이다.

SRP 위반사례1: 우발적 중복

이미지 출처 : https://ryanpark.dev/750043c5-4901-4101-87f7-cdc9070a7edc

Employee 클래스에 있는 세 가지 메소드의 역할

  • calculatePay() : 회계팀에서 기능을 정의하며, CFO 보고를 위해 사용한다.
  • reportHours() : 인사팀에서 기능을 정의하고 사용하며, COO 보고를 위해 사용한다.
  • save() : 데이터베이스 관리자가 기능을 정의하고, CTO 보고를 위해 사용한다.

문제점

  • 이 세개의 메소드를 Employee라는 단일 클래스에 배치하여 쎄 액터(CFO,COO,CTO)가 서로 결합되어 버렸다.
  • 이 결합으로 인해 CFO 팀에서 결정한 조치가 COO 팀이 의존하는 무언가에 영향을 줄 수 있다.

예를들어 calculatePay() 메소드와 reportHours() 메소드가 초과 근무를 제외한 업무 시간을 계산하는 알고리즘을 공유한다고 생각해보자.
개발자는 코드 중복을 피하기 위해 이 알고리즘을 regularHours() 라는 메소드에 넣었다고 해보자.

이미지 출처 : https://ryanpark.dev/750043c5-4901-4101-87f7-cdc9070a7edc

만약 CFO 팀에서 초과 근무를 제외한 업무 시간을 계산하는 방식을 약간 수정하기로 결정했고,
인사담당하는 COO팀에서는 초과 근무를 제외한 업무 시간을 CFO 팀과는 다른 목적으로 사용하기 때문에 이 같은 변경을 원치 않는다면 어떻게 될까?

  • 이 변경을 적용 하는 업무를 할당 받은 개발자는 calculatePay() 메소드가 regularHours()를 호출한다는 사실을 발견한다.
  • 하지만 이 함수가 reportHours() 메소드에서도 호출된다는 사실은 눈치채치 못한다.
  • 개발자는 변경사항을 테스트한다
  1. CFO 팀의 테스트 검증이 통과되면 시스템은 배포된다.
  2. 그러나 COO 팀에서는 이러한 일이 벌어지고 있다는 사실을 모른다.
  3. COO 팀 직원은 reportHours() 메소드가 생성한 보고서를 여전히 이용한다.
  4. 보고서의 수치들은 엉터리가 된다 -> SRP는 서로 다른 액터가 의존하는 코드를 서로 분리하라고 말한다.

SRP 위반사례2: 병합

  • CTO 팀에서 데이터베이스의 Employee 테이블 스키마를 약간 수정한다.

  • COO 팀에서 reportHours() 메소드의 보고서 포맷을 변경한다.

  • 두 명의 서로 다른 개발자가 (각각 CTO,COO 팀) Employee 클래스를 체크아웃 받은 후 변경사항을 적용한다.

  • 이들 변경사항은 충돌하여 병합이 발생한다.

    	어떤 도구도 병합이 발생하는 모든 경우를 해결할 수 는 없다.
  • 이러한 징후는 모두 많은 사람이 서로 다른 목적으로 동일한 소스 파일을 변경하는 경우에 해당한다.

  • 이 문제를 벗어나는 방법은 서로 다른 액터를 뒷받침하는 코드를 서로 분리하는 것이다.

해결책

  1. 첫번째 해결책 - 클래스 분리

    이미지 출처 : https://ryanpark.dev/750043c5-4901-4101-87f7-cdc9070a7edc
  • EmployeeData 클래스를 만든다.
  • 세 개의 클래스가 공유하도록 한다.
  • 각 클래스는 자신의 메소드에 반드시 필요한 소스 코드만을 포함한다.
  • 세 클래스는 서로의 존재를 몰라야한다. -> 우연한 중복을 피할 수 있다.
  • 그러나 개발자가 세 가지 클래스를 인스턴스화 하고 추적해야 한다는 단점이 있다.
  1. 두번째 해결책 - 파사드(Facade) 패턴

    이미지 출처 : https://ryanpark.dev/750043c5-4901-4101-87f7-cdc9070a7edc
  • EmployeeFacade 코드는 거의 없다.
    이 클래스는 세 클래스의 객체를 생성하고, 요청된 메소드를 가지는 객체로 위임하는 일을 책임진다.
  1. 두번째 해결책 - 파사드(Facade) 패턴

    이미지 출처 : [https://ryanpark.dev/750043c5-4901-4101-87f7-cdc9070a7edc](https://wedonttalknemore.tistory.com/13)
  • Employee 클래스를 덜 중요한 나머지 메서드들에 대한 파사드로 사용한다.

좋은 웹페이지 즐겨찾기