SOLID원칙은 객체지향 언어를 배우기 전에 공부를 다 해봤을 것이다. 그 중에서 직접적으로 설계와 관련있는 SRP와 OCP에 대해 자세히 알아보자.
번역을 하면 단일 책임 원칙으로 하나의 클래스는 하나의 책임만을 가져야한다 라는 원칙이다. 이에 따라 클래스가 변경되는 이유는 하나뿐이어야 한다는 것도 포함한다.
클래스가 여러 책임들을 가진다면 어떤 일을 하고 책임들을 차등하게 해결해야하는지 어렵기 때문에 쉽게 알기 위해 하나로 나누는 것이다.
궁극적으로는 클래스를 이해하기 쉽게 만들어 코드의 가독성과 유지보수성을 높이고, 변경에 의한 영향을 최소화하여 변경을 쉽게 만드는 것이다.
# SRP를 위반한 코드
class ReportManager:
# 보고서 생성 로직
def generateReport(self):
print("Report generated")
# 이메일 발송 로직
def sendEmail(self):
print("Email sent")
ReportManager
가 두개의 책임을 가지고 있으므로 분리한다.
class ReportManager:
# 보고서 생성 로직
def generateReport(self):
print("Report generated")
class EmailManager
# 이메일 발송 로직
def sendEmail(self):
print("Email sent")
OCP는 개방/폐쇄 원칙으로 소프트웨어는 확장에는 열려있고, 수정에는 닫혀있어야한다는 원칙이다.
이는 기존 코드를 수정하지 않고 기능을 추가할 수 있어야한다는 점을 중요시한다.
class DiscountCalculator:
def calculate(self, amount, discount_type):
if discount_type == "seasonal":
return amount * 0.9
elif discount_type == "festival":
return amount * 0.8
else:
return amount
위처럼 되어있으면 discount_type이 추가될때마다 수정을 해야한다. 이를 바꿔서 수정을 하지 않고도 추가될 수 있게 바꾸자.
from abc import ABC, abstractmethod
class DiscountStrategy(ABC):
@abstractmethod
def apply_discount(self, amount):
pass
class SeasonalDiscount(DiscountStrategy):
def apply_discount(self, amount):
return amount * 0.9
class FestivalDiscount(DiscountStrategy):
def apply_discount(self, amount):
return amount * 0.8
class DiscountCalculator:
def __init__(self, strategy: DiscountStrategy):
self.strategy = strategy
def calculate(self, amount):
return self.strategy.apply_discount(amount)
# 사용 예시
calculator = DiscountCalculator(FestivalDiscount())
print(calculator.calculate(100)) # 80.0