본문 바로가기

공부기록/아키텍처

클린 아키텍처 7장~11장 SOLID

  1. SRP

하나의 모듈은 하나의, 오직 하나의 액터에 대해서만 책임져야 한다.

서로 다른 액터를 책임진다면 병합이 발생할 가능성은 확실히 더 높다.

해결책: 메서드를 각기 다른 클래스로 이동. 그러나 각기 다른 클래스로 관리하기가 어렵다면? 퍼사드로 관리하자

단일 책임 원칙은 메서드와 클래스 수준의 원칙이다. 상위의 두 수준에서도 다른 형태로 다시 등장. 컴포넌트 수준에서는 공통 폐쇄 원칙, 아키텍처 수준에서는 아키텍처 경계의 생성을 책임지는 변경의 축이 된다.

 

  • OCP

확장에는 열려있어야하고, 변경에는 닫혀 있어야함 → 다형성을 사용하여, 기능을 변경시, 다른 모듈로 갈아끼우라는 뜻.

아키텍처 컴포넌트 수준에서 OCP를 고려할 때, 훨씬 중요한 의미를 가진다.

처리 과정을 클래스 단위로 분할하고, 컴포넌트 단위로 구분해야 한다.

아키텍처를 떠받치는 원동력 중 하나. 시스템을 확장하기 쉬운 동시에 변경으로 인해 시스템이 너무 많은 영향을 받지 않도록 하는 데 있다.

 

  • LSP

 두 개의 타입이 있고, A타입을 B타입으로 치환해도 동일하게 동작하면, A타입은 B타입의 하위타입. 동일하게 동작한다는 것에는 단순히 클래스를 extends했다는 것을 넘어서서 '동일하게' 동작한다는 의미를 가진다. 예를 들어 Rectangle을 상속받은 Square는 LSP를 위반한다. Rectangle에서는 w,h을 조작할 수 있지만, Square에서는 하나를 조작하면 나머지도 같이 변경되기 때문에, 기존의 기능이 유지되지 않기 때문이다.

시간이 지나면서 상속뿐만 아니라, 인터페이스와 구현체에도 적용되는 광범위한 소프트웨어 설계 원칙이 되었다. 사용자가 기대하는 인터페이스의 역할이 보편적이라는 의미. 잘 정의된 인터페이스와 그 인터페이스의 구현체끼리의 상호 치환 가능성에 기대는 경우가 있기 때문.

 

  • ISP

실제로 사용할 부분만 Import 할 수 있게 하자. 왜냐하면 사용하지 않는 부분이 수정됐다고, 패치를 받거나 할 수 있기 때문에, 또는 그것으로 인해 다른 기능이 바뀔 수 있어서. 루비나 파이썬같은 언어는 런타임에 추론하여 import를 사용하지 않음. 재컴파일과 재배포가 필요없음. 동적 타입 언어가 유연하며 결합도가 낮은 이유. ISP는 언어와 연관된 문제라고 결론내릴 여지가 있음. 무언가에 의존하면 예상치 못한 문제에 빠질 수 있음.

  • DIP

추상에 의존하며, 구체에는 의존하지 않는 시스템. 구체 모듈을 참조해서는 안됨. 인터페이스의 변동성을 낮추기 위해 힘을 써야함. 일반적으로 추상 팩토리를 사용하여 추상 인터페이스를 참조하도록 강제한다. 구체함수를 오버라이드하지 마라.