소프트웨어에 대한 모든 것

[디자인패턴][SOLID] 개방/폐쇄 원칙 본문

시스템 설계 및 디자인/객체지향 SOLID

[디자인패턴][SOLID] 개방/폐쇄 원칙

앤테바 2022. 3. 23. 17:39
반응형

개방/폐쇄 원칙 (Open-closed principle)

  • 클래스는 확장에는 열려있고 수정(변경)에는 닫혀 있어야 한다.
  • 기존 코드를 변경하지 않으면서, 기능을 수정하거나 추가할 수 있도록 설계되어야 한다는 원칙

개방/폐쇄 원칙은 기존의 시스템의 존재하는 코드의 수정없이 새로운 features(or use cases)를 쉽게 추가할 수 있습니다.

 

예제를 통해서 살펴 보겠습니다.

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __repr__(self):
        return f'name={self.name}, age={self.age}'


class PersonStorage:
    def save_to_database(self, person):
        print(f'Save the {person} to database')

    def save_to_json(self, person):
        print(f'Save the {person} to a JSON file')


person = Person('James', 28)
storage = PersonStorage()
storage.save_to_database(person)

위의 디자인에서 PersonStorage 클래스는 두 메소드를 지원합니다.

  1. save_to_database() 함수는 person을 database에 저장합니다.
  2. save_to_json() 함수는 person을 json 형태 파일로 저장합니다.

여기에서 xml 파일 형태로 저장하는 요구사항이 발생한다면? PersonStorage 클래스를 수정해야 한다. 즉, PersonStorage는 확장에 열려 있지 않고 수정에 열려있는 OCP를 위반하는 경우이다. 

 

OCP 원칙에 맞춰서 클래스를 재 디자인 한다면 아래와 같다.

PersonStorage를 abstract class로 정의하고 save() 함수를 추상 함수로 정의한다.

from abc import ABC, abstractmethod


class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __repr__(self):
        return f'name={self.name}, age={self.age}'


class PersonStorage(ABC):
    @abstractmethod
    def save(self, person):
        pass


class PersonDB(PersonStorage):
    def save(self, person):
        print(f'Save the {person} to database')


class PersonJSON(PersonStorage):
    def save(self, person):
        print(f'Save the {person} to a JSON file')



person = Person('James', 28)
storage = PersonDB()
storage.save(person)

 

OCP 원칙에 위배되지 않게 코드를 수정 하였습니다. 

새로운 디자인에서 xml 파일 형식 저장 요구사항을 구현한다면 PersonStorage를 상속받은 PersonXML 클래스를 추가하면, 확장에는 열려 있고 수정에는 닫혀 있는 OCP 원칙을 충실히 지킨 디자인을 한 것입니다.

 

from abc import ABC, abstractmethod


class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __repr__(self):
        return f'name={self.name}, age={self.age}'


class PersonStorage(ABC):
    @abstractmethod
    def save(self, person):
        pass


class PersonDB(PersonStorage):
    def save(self, person):
        print(f'Save the {person} to database')


class PersonJSON(PersonStorage):
    def save(self, person):
        print(f'Save the {person} to a JSON file')


class PersonXML(PersonStorage):
    def save(self, person):
        print(f'Save the {person} to a XML file')


person = Person('James', 28)
storage = PersonXML()
storage.save(person)

 

참고 자료:

Python Open–closed principle

반응형
Comments