ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Liskov Substitution Principle
    python/SOLID 2023. 12. 6. 22:53

    정의

    Subclasses should NOT change the behavior of superclasses in unexpected ways.

     

    Selecting on types 유형

    위반 코드

    class Employee:
        def __init__(self, name):
            self.name = name
    
    
    class Manager(Employee):
        def __init__(self, name, department):
            super().__init__(name)
            self.department = department
    
    
    def print_employee(e):
        if type(e) is Employee:
            print(f"{e.name} is an employee")
        elif type(e) is Manager:
            print(f"{e.name} leads department {e.department}")

     

    • Manager 클래스의 인스턴스가 필요한 곳에, Employee 클래스(Manager 클래스의 superclass) 의 인스턴로 대체할 수 없다. (Manager type 인지 Employee type 인지 체크되어야 대체될 수 있다.)

    개선 코드

    https://wefree.tistory.com/328 참고

     

    Break the is-a relationship 유형

    위반 코드

    아래처럼 초기 Employee 코드에서

    class Employee:
        def __init__(self, name, salary):
            self.name = name
            self.salary = salary
    
        def print_year_salary(self):
            print(f"{self.name} year salary ${self.salary * 12}")

     

    salary 를 받지 않는 Intern 클래스를 Employee 클래스를 상속 받아 추가했다.

    class Intern(Employee):
        def __init__(self, name, salary):
            # Intern 은 salary 를 받지 않으므로 None 으로 세팅, 0 으로 세팅하는 것이 좋을거라 생각할 수 있지만?
            super().__init__(name, None)

     

    • salary 값을 None 으로 세팅했는데, 0 이 더 좋을거라 생각할 수도 있다. 0으로 세팅했을 경우, 만약 Employee 의 평균 salary 값을 구하는 함수를 추가할 때 0 으로 세팅한 값 때문에 문제가 될 수 있다. (None 과 0 은 다르다!)

    Intern 의 salary 값이 None 이기 때문에, superclass 의 print_year_salary() 가 잘 동작하기 위해서는 아래처럼 수정되어야 한다.

        def print_year_salary(self):
            if type(self) is not Intern:
                print(f"{self.name} year salary ${self.salary * 12}")

     

    즉, subclass Intern 때문에 superclass Employee 의 print_year_salary() 가 변경되어야 했다 !!!

    근본적으로 Intern 을 Employee 로 부터 상속받아 is-a 관계를 만든것이 잘못이다.

     

    Raise error in overridden method 유형

    위반 코드

    class Employee:
        def __init__(self, name):
            self.name = name
    
        def promote(self):
            print("Promote employee")
    
    
    class Intern(Employee):
        def promote(self):
            raise NotImplementedError("Interns cannot be promoted")
    
    
    def promote_employee(e):
        e.promote()
    • pormote() 함수의 경우 superclass 인 Employee 에서는 Exception 이 발생하지 않는데, subclass 인 Intern 의 경우 Exception 이 발생할 수 있다.
    • Employee 인스턴스를 받아 Exception  발생 없이 잘 처리되던 promote_employee() 함수였다. 그런데 Employee 인스턴스 대신에 subclass 인 Intern 인스턴스로 교체했더니 promete_employee() 호출 도중 Exception 이 발생해 프로그램이 깨져버렸다.

     

    Break constraints

    위반 코드

    아래처럼 초기 코드가 있는 상태에서

    class Employee:
        def __init__(self, employee_id, name):
            self.employee_id = employee_id
            self.name = name
    
        def is_employee_id_valid(self):
            return type(self.employee_id) is int and self.employee_id > 0
    
    
    class Intern(Employee):
        def __init__(self, employee_id, name):
            super().__init__(employee_id, name)

     

    Intern 클래스의 employee_id 는 I 로 시작하도록 변경해 달라고 요청이 왔다. 시간이 없어 꼼수로 아래처럼 수정했다.

    class Intern(Employee):
        def __init__(self, employee_id, name):
            super().__init__(f"I{employee_id}", name)

     

    그런데, 이렇게 구현할 경우 superclass 의 is_employee_id_valid() 의도에서 벗어나게된다. (superclass 를 수정해야 하나?)

     

    참고: https://www.udemy.com/course/solid-design-principles-with-python

    'python > SOLID' 카테고리의 다른 글

    Dependency Inversion Principle  (0) 2023.12.06
    Interface Segregation Principle  (0) 2023.12.06
    Open-closed Principle  (1) 2023.12.06
    Single Responsibility Principle  (0) 2023.12.05

    댓글

Designed by Tistory.