SOLID - SRP

응집도(cohesion)에 대한 기준

"각 소프트웨어 모듈은 변경의 이유가 단 하나여야만 한다" =="하나의 모듈은 오직 하나의 액터에 대해서만 책임져야 한다"

  • 해결책 : 3개의 클래스로 분리 (액터의 세분화 : Facade패턴 적용 고려)

플러터로 풀어본 SRP 위반 예시 (여러 액터가 한 클래스에 섞인 경우)

예를 들어, 직원(Employee) 정보를 관리하는 클래스가 아래처럼 구성되어 있다고 가정합니다.

class Employee {
  int hoursWorked;

  Employee(this.hoursWorked);

  // 회계팀: 급여 계산
  double calculatePay() {
    // ...
    return hoursWorked * 10000;
  }

  // 인사팀: 근무 시간 보고
  void reportHours() {
    // ...
    print('Reported $hoursWorked hours');
  }

  // 전산팀: 데이터 저장
  void save() {
    // ...
    print('Employee data saved');
  }
}

이 클래스는 회계팀, 인사팀, 전산팀이라는 서로 다른 액터의 요구를 모두 처리하고 있어 SRP를 위반합니다.

SRP 준수 및 퍼사드 패턴 적용 예시

각 액터의 책임을 별도 클래스로 분리하고, 퍼사드(Facade) 클래스를 통해 통합 인터페이스를 제공합니다.

// 데이터(공유 자원)
class EmployeeData {
  int hoursWorked;
  EmployeeData(this.hoursWorked);
}

// 회계팀: 급여 계산
class PayCalculator {
  final EmployeeData data;
  PayCalculator(this.data);

  double calculatePay() {
    return data.hoursWorked * 10000;
  }
}

// 인사팀: 근무 시간 보고
class HourReporter {
  final EmployeeData data;
  HourReporter(this.data);

  void reportHours() {
    print('Reported ${data.hoursWorked} hours');
  }
}

// 전산팀: 데이터 저장
class EmployeeSaver {
  final EmployeeData data;
  EmployeeSaver(this.data);

  void save() {
    print('Employee data saved');
  }
}

// 퍼사드 클래스
class EmployeeFacade {
  final PayCalculator _payCalculator;
  final HourReporter _hourReporter;
  final EmployeeSaver _employeeSaver;

  EmployeeFacade(EmployeeData data)
      : _payCalculator = PayCalculator(data),
        _hourReporter = HourReporter(data),
        _employeeSaver = EmployeeSaver(data);

  double calculatePay() => _payCalculator.calculatePay();
  void reportHours() => _hourReporter.reportHours();
  void save() => _employeeSaver.save();
}

// 사용 예시
void main() {
  final data = EmployeeData(40);
  final employee = EmployeeFacade(data); // 퍼사드 클래스 

  employee.calculatePay(); // 회계팀
  employee.reportHours();  // 인사팀
  employee.save();         // 전산팀
}

이렇게 하면 각 클래스는 하나의 액터만을 책임지고, 클라이언트는 EmployeeFacade만 사용하면 되므로 구조가 단순해집니다. 퍼사드는 내부의 복잡성을 숨기고, 필요한 인터페이스만 외부에 노출합니다.

정리

  • 여러 액터의 요구가 한 클래스에 섞이면 SRP 위반입니다.

  • 각 액터별 클래스로 분리 후, 퍼사드 패턴으로 통합 인터페이스를 제공합니다.

  • 퍼사드 패턴은 클라이언트가 복잡한 내부 구조를 몰라도 되게 해주며, SRP 준수에 도움을 줍니다

Last updated