Development/Python
Python 프로그래밍 SOLID 원칙
위풍당당 가리비
2024. 5. 7. 22:09
반응형
SOLID 원칙
- S : Single reponsibility. 하나의 컴포넌트는 하나의 책임만 져야한다.
- O : Open/Close. 확장에는 개방되고, 수정에는 폐쇄되도록 디자인 해야한다.
- L : Liskov substitution. 리스코프 치환 원칙. 클라이언트는 코드 변경없이 하위타입을 사용할 수 있어야한다.
- I :
- D :
Open/Close principle
- 확장에는 개방적! 수정에는 폐쇄적!
- 새롭게 처리해야할 것이 들어오면 새로운 것을 처리하는 코드만 추가해야지 기존꺼는 바뀌면 안된다. 바뀐다면 기존코드가 수정에 닫혀있지 않다라는 것을 의미한다.
어떤 로직을 처리하다 보면 if elif elif를 줄줄이 써야하는 경우가 생긴다. 예를 들어서 config파일을 받아서 해당 config에 맞는 모델을 만든다던지, 데이터셋을 만든다던지 하는 등의 경우가 있다.
이런 경우에는 새로운 데이터셋, 모델이 추가될 때마다 만드는 함수도 같이 수정을 해야한다. 그러면 이 만드는 함수는 수정에 닫혀있지 않다고 말할 수 있다.
새로운 요소가 추가되더라도 만드는 함수가 제대로 동작하기 위해서는 추상화된 모델, 데이터셋을 만들고, 추상화된 클래스를 상속받아서 __subclasses__()라는 함수를 사용해서 만드려고 하는 클래스를 찾으면 된다.
코드를 깔끔하게 만들 수 있는 아주 좋은 꿀팁.
내일 회사가서 바로 데이터셋, 모델 만들 때 써먹어야겠다.
여기에서 얻은 지식을 일반화해보면 "비즈니스 로직은 구체 클래스와 직접적으로 상호작용하지 않고 추상 클래스와 상호작용해야한다!"
- 비즈니스 로직 = 여러개의 데이터셋, 모델을 만드는 함수.
- 추상 클래스 = 데이터셋의 기본이 되는 클래스, 모든 데이터셋은 해당 클래스를 상속받아서 만들어져야한다.
- 구체 클래스 = 각 데이터셋을 담당하는 클래스, 추상 클래스를 상속받아서 만들어야한다.
Liskov Substitution Principle. LSP
- 클라이언트 (내가 제공하는 클래스를 사용하는 사람)는 부모 클래스와 자식 클래스를 사용할 때 큰 주의 없이 사용할 수 있어야한다는 원칙.
- 조금 더 풀어서 설명하면 부모와 자식이 같은 인터페이스를 가지고 있어 코드에서 부모 클래스 객체를 자식 클래스 객체로 바꾸기만 해도 똑같이 동작해야한다는 의미.
- 즉, 인터페이스를 잘 짜야한다. 좋은 클래스는 명확하고 간단한 인터페이스를 가진다.
- LSP 문제는 Mypy나 pylint 같은 도구로 쉽게 검출이 가능하다.
- 예시 1)
- 부모 클래스 : def get_output(input: list) -> bool
- 자식 클래스 : def get_output(input: dict) -> bool
- 이런 경우에는 같은 메소드가 다른 인자를 입력으로 받기 때문에 LSP를 위배한다.
- 그렇지만 항상 이 LSP 문제를 만족할 수는 없다. 예시로 nn.Module을 상속받아서 모델을 만드는데 forward()에 들어가는 인풋은 모델마다 다 다를 수 있다.
반응형