객체지향 설계 SOLID 5원칙 중에서 마지막 원칙에 해당하는 DI (Dependency Inversion Principle)에 대해서 알아보자.
객체지향적 설계에는 의존관계가 생기기 마련이다. 각 클래스는 단일 책임 원칙에 따라 하나의 책임만 져야 하고, 각 클래스가 결합돼 프로그램이 구동된다는 것을 보면, 어떤 클래스가 다른 클래스에 의존하는 것은 당연하다.
class Dog:
def speak(self):
print("Bark")
class Cat:
def speak(self):
print("Meow")
class Zoo:
def __init__(self):
self.cat = Cat()
self.dog = Dog()
def speak_all(self):
self.cat.speak()
self.dog.speak()
위와 같은 Dog, Cat 클래스가 있고, Zoo는 Cat과 Dog를 가지고 있다. High level 클래스인 Zoo가 Low level 클래스인 Cat, Dog를 가지며 의존성을 띤다. 이 때, 다른 동물을 추가하고 싶다면 어느 부분을 수정해야 할까?
Zoo 클래스의 init과 speak_all 부분을 모두 수정해야 한다! 클래스를 추가해서 의존성 하나를 덧붙일 뿐인데 추가하는 클래스가 아닌 의존하는 클래스(Zoo)의 구조가 바뀐다.
이 때의 dependency를 그림으로 나타내면 다음과 같다.
다른 동물들이 Zoo에 추가될 때마다 Zoo에서 뻗어나가는 화살표가 많아질 것이고, 이는 곧 Zoo에서 수정해야 할 코드들이 늘어남을 의미한다.
이것을 피하기 위해서 나온 개념이 dependency inversion인데, 가운데 abstract한 클래스를 두고 low level class들이 이를 상속받게 한다. 마찬가지로 Zoo도 abstract class를 의존하게 하는 것이다. 아래 코드를 보자.
class Animal:
def speak(self):
pass #abstract
class Dog(Animal):
def speak(self):
print("Bark")
class Cat(Animal):
def speak(self):
print("Meow")
class Zoo():
def __init__(self):
self.animals = []
def add_animal(animal: Animal):
self.animals.append(animal)
def speak_all(self):
for animal in self.animals:
animal.speak()
코드로 보니 훨씬 이해가 쉽다. 이제 Sheep이라는 코드를 작성해 Zoo에 넣고 싶다면? 아래와 같이 하면 된다.
class Sheep(Animal):
def speak(self):
print("Baaa")
zoo = Zoo()
sheep = Sheep()
zoo.add_animal(sheep)
Zoo에 대한 코드 수정이 한 개도 없다. High level class인 Zoo에서 Low level class인 동물들에 대한 "직접적인 의존"을 하지 않기 때문이다. abstract class로 Animal을 만들고, 그곳에 의존토록 한 뒤, 동물들은 Animal을 상속해 구현한다.
다른 동물을 넣어도 마찬가지다. 아직 "의존관계 역전" 이라는 게 와닿지 않는다면, 아래 그림을 보자.
Zoo는 Animal 클래스에 의존하고 (Dependency를 가지고), Dog, Cat, Sheep들도 Animal 클래스에 의존한다. 화살표의 방향이 한 곳만을 향하고 있고, 특히나 Dog, Cat, Sheep과 같은 Low level class들의 경우 의존관계가 뒤집힌 것을 확인할 수 있다. 아무리 많은 동물들이 생긴다고 하더라도, Zoo에서 새롭게 뻗어나가는 화살표가 없다.
low level class의 구현을 계속해서 해나가더라도 high level class는 독립적이며, 추가적인 수정이 필요하지 않다. 이것이 제일 중요한 것 같다 !
(너무 어렵다)
Reference:
https://www.youtube.com/watch?v=DYmtue0k1cc.
https://en.wikipedia.org/wiki/Dependency_inversion_principle
'study > others' 카테고리의 다른 글
[Tex | MathJax] Tex 문법을 Tistory에서 호환성 있게 사용하기 (모바일, PC) (0) | 2022.09.02 |
---|---|
[파이썬 | Python] Mutable object, Immutable object (0) | 2022.01.23 |
[깃 | Git] Udacity Git Commit Message Style Guide - 깃 커밋 메시지 일관성있게 쓰기 (스타일 가이드) (0) | 2022.01.14 |
42서울 (42SEOUL) 온라인테스트 후기 (0) | 2021.10.28 |