해당 글은 Robert C.Martin 클린 아키텍처 라는 책을 읽고 학습한 내용을 정리 및 회고하는 글 입니다. 자세한 사항은 YES 24 클린 아키텍처 - 소프트웨어 구조와 설계의 원칙 에서 확인해주세요.
클린 아키텍처 - 소프트웨어 구조와 설계의 원칙 (Robert C. Martin)
- 위키북스
- 지은이: Robert C.Martin (Uncle Bob)
- 옮긴이: 송준이
이번 장에서 이야기하고자 하는 것
LSP
- 다음과 같은 치환 원칙이 적용된다면 LSP 를 만족한다
- A 를 구현하는(상속하는) 서브 타입 B와 C 가 있다면 B 타입에 모두 C 타입으로 변경하더라도 행위가 변하지 않는다.
- LSP 는 아키텍처 수준까지 확장할 수 있고 반드시 확장해야 한다.
- 치환 가능성을 위배한다면 상당량의 추가 구현사항이 등장하기 때문이다.
ISP
- 변경에 유리하게 대처하기 위해서는 정말로 알아야 할 정보만 알아야 한다
- 필요 이상으로 많은 것을 포함하는 모듈에 의존하는 것은 해로운 일이다.
- 무언가에 의존한다는 것은 예상치도 못한 일을 불러일으킬 수 있다.
- 그러므로 의존을 최소화해야 한다는 교훈을 ISP 에서 느낄 수 있따.
DIP
- 유연성이 극대화된 시스템
- 소스 코드 의존성이 추상에 의존하며 구체에는 의존하지 않는 시스템
- It depends on abstraction, not a concretion
- 소스 코드 의존성이 추상에 의존하며 구체에는 의존하지 않는 시스템
- 현실적으로 DIP 는 규칙이 되기 힘듦
String.class
와 같은 구체 클래스에 대한 의존성은 벗어날 수 없고 벗어나서는 안되기 때문에
- Abstraction 은 Concretion 보다 변경 가능성이 더 낮기 때문이다.
- DIP 를 위한 몇가지 실천법이 존재한다.
- 변동성이 큰 Concrete Class 를 참조하지 말아라
- 변동성이 큰 Concrete Class 로부터 파생하지 말아라
- Concrete Class 를 Override 하지 말아라
- 구체적이며 변동성이 크다면 절대로 그 이름을 언급하지 말아라
나의 해석과 회고
이번에는 내 생각에 대한 회고가 아니라 각각의 원칙에 대해서 한번 정리해보려 한다.
LSP
interface Car {}
class Bmw implements Car {}
class Audi implements Car {}
class Main {
public static void main(String[] args) {
Car car = new Bmw();
Car car2 = new Audi();
car = new Audi();
car2 = new Bmw();
}
}
과 같이 되었을 때 car
과 car2
의 행위에 대한 결과가 동일하다면 이는 LSP 가 만족하는 것이다.
ISP
interface Rule {}
interface UserRule extends Rule {}
interface AdminRule extends Rule {}
class UserRuleSet implements UserRule {}
class AdminRuleSet implements AdminRule {}
과 같이 되었을 때, UserRuleSet
이나 AdminRuleSet
은 Rule 에 직접적으로 의존하지 않기 때문에, 정말 필요한 정보만 사용하기 때문에 ISP 가 만족된다고 할 수 있다.
하지만 여기서 주의해야 할 점이 Rule 을 무조건 나눈다고 해서 ISP 를 만족하는 것은 아니다.
Rule
이라는 인터페이스가 필요 이상으로 많은 정보를 가졌고, 그들을 적절히 UserRule 과 AdminRule 이 소유하고 분리할 때만 적용되는 말이다
DIP
public class Main {
public static void main(String[] args) {
List<String> strings = new ArrayList<>();
ArrayList<String> strings2 = new ArrayList<>();
}
}
위의 코드에서 string2
는 표면적으로는 DIP 를 위배한다.
ArrayList 는 Concrete 이며 직접적으로 Concrete 를 의존하기 때문이다.
하지만 DIP 를 잘 이해했다면 위의 코드는 모두 문제가 없다.
그럼 다음은 어떨까?
public class Main {
public static void main(String[] args) {
Car car1 = new Bmw<>();
Audi car2 = new Audi<>();
}
}
위의 코드는 DIP 를 위배할 것 같은데 과연 정말 위배할까?
답은 상황에 따라 다르다는 것이다.
만약 위배하게 된다면 Audi 를 레퍼런스 타입으로 하는 car2
가 DIP 를 위배한다고 할 수 있다.
하지만 만약 그럴 일이 매우 드물겠지만 Audi 라는 Concrete Class 가 절~~대 바뀔 여지가 없다면 DIP 를 위배하지 않는다고 한다.
이렇듯 상황에 따라서, 비즈니스에 따라서 달라질 수 있는 것이 바로 DIP 이며 이러한 이유로 인해서 규칙이 될 수 없다고 이야기한다.
'더 좋은 개발자 되기 > 개발자 책읽기' 카테고리의 다른 글
[개발자 책읽기] - 상자 밖에 있는 사람, 아빈저 연구소 (1) | 2023.06.17 |
---|---|
[개발자 책읽기] 클린 아키텍처-소프트웨어 구조와 설계의 원칙 (7장 8장 - SRP 와 OCP) (0) | 2022.04.22 |
[개발자 책읽기] 클린 아키텍처-소프트웨어 구조와 설계의 원칙 (5장 6장 - 객체 지향, 함수형 프로그래밍) (0) | 2022.04.22 |
[개발자 책읽기] 클린 아키텍처-소프트웨어 구조와 설계의 원칙 (2장 두가지 가치에 대한 이야기) (0) | 2022.04.11 |
[개발자 책읽기] 클린 아키텍처-소프트웨어 구조와 설계의 원칙 (1장 설계와 아키텍처란?) (0) | 2022.04.10 |
댓글