-
[디자인패턴] SOLID 원칙디자인패턴 2020. 12. 12. 20:33728x90
SOLID 원칙
로버트 마틴이 명명한 객체지향 프로그래밍 및 설계 기본 5대 원칙
1. SRP (Single Responsibility principle; 단일 책임 원칙)
1) 정의 : 한 클래스는 하나의 책임만 가져야 한다.
2) 설명
로버트 마틴은 'Responsibility(책임)'을 '변경하려는 이유'로 정의 → 한 클래스는 변경하려는 단 하나 이유만을 가져야 한다.
ex) 보고서를 편집하고 출력하는 모듈
이 모듈은 두 가지 이유로 변경될 수 있다. 첫 번째로 보고서의 내용 때문에 변경될 수 있다. 두 번째로 보고서의 형식 때문에 변경될 수 있다.
이 두가지 변경은 하나는 실질적이고 다른 하나는 꾸미기 위한 매우 다른 원인에 기인한다.
→ SRP에 의하면 이 문제의 두 측면이 실제로 분리된 두 책임 때문이며, 따라서 분리된 클래스로 나누어야 한다. 다른 시기에 다른 이유로 변경되어야 하는 두 가지를 묶는 것은 나쁜 설계일 수 있다.
3) 장점
- 책임 영역이 확실해지기 때문에 한 책임의 변경에서 다른 책임의 변경으로의 연쇄작용에서 자유로울 수 있다.
- 책임을 적절히 분배함으로써 코드의 가독성 향상, 유지보수 용이라는 이점이 있다.
2. OCP (Open/closed principle; 개방-폐쇄 원칙)
1) 정의 : 소프트웨어 개체(클래스, 모듈, 함수 등)는 확장에 대해 열려있어야 하고, 수정에 대해서는 닫혀 있어야 한다
2) 설명
변경을 위한 비용은 가능한 줄이고, 확장을 위한 비용은 가능한 극대화 해야 한다.
→ 요구사항의 변경 or 추가가 있더라도, 기존 구성요소는 수정이 일어나지 말아야 하며, 기존 구성요소를 쉽게 확장해서 재사용할 수 있어야 한다
OCP를 가능케 하는 중요 메커니즘은 추상화와 다형성이며, 객체지향의 장점을 극대화하는 아주 중요한 원리라 할 수 있다.
3) 적용방법
OCP 위반 OCP 적용 후 - 변경(확장)될 것과 변하지 않을 것을 엄격히 구분한다
- 이 두 모듈이 만나는 지점에 인터페이스를 정의한다
- 구현 클래스에 의존하기보다 정의한 인터페이스에 의존하도록 코드를 작성한다
4) 장점
- 객체지향 프로그래밍의 가장 큰 장점인 유연성, 재사용성, 유지보수성을 얻을 수 있다.
3. LSP (Liskov substitution principle; 리스코프 치환 원칙)
1) 정의 : 상위 타입의 객체를 하위 타입의 객체로 치환해도, 프로그램은 정상적으로 동작해야 한다
2) 설명
서브 타입은 언제나 기반 타입과 호환될 수 있어야 한다 → 서브 타입은 기반 타입이 약속한 규약 (public 인터페이스, 물론 메소드가 던지는 예외까지 포함)을 지켜야 한다
ex) LSP 위반 예제 - Rectangle(직사각형), Square(정사각형)
// 직사각형 class Rectangle { int width = -1; int height = -1; public getWidth() { return this.width; } public setWidth(int w) { this.width = w; } public getHeight() { return this.height; } public setHeight(int h) { this.height = h; } public getArea() { return this.width * this.height; } } // 직사각형을 상속하는 정사각형 class Square extends Rectangle { @Override public setWidth(int w) { this.width = w; this.height = w; } @Override public setHeight(int h) { this.width = h; this.height = h; } }
Rectangle(직사각형) 클래스가 있고, Rectangle을 상속하는 Square(정사각형) 클래스가 있다.
Rectangle rec = new Rectangle(); rec.width = 3; rec.height = 4; System.out.print(rec.area == 12); // true (Rectangle을 사용) Rectangle rec2 - new Square(); rec2.width = 3; rec2.height = 4; System.out.print(rec2.area == 12) // false (Square을 사용)
부모인 Rectangle 객체에서는 작동하는 행위가 Square 객체에 대해서 작동하지 않는다는 것은 LSP를 위반하는 것이다.
'Square(정사각형) is a Rectangle(직사각형)' 라고 생각해서 코드에 상속 관계를 반영할 수 있지만, SOLID 법칙의 기준으로 보면 둘은 코드에서 상속관계로 존재할 수 없다.
→ 정사각형-직사각형 관계보다 더 포괄적인 Shape(도형)을 상속하도록 리팩터링 하고, 하위 클래스는 상위 클래스에서 정의한 원칙에 벗어나지 않도록 해야 한다.
3) 장점
- LSP는 규약을 준수하는 상속 구조를 제공한다 → LSP는 상속 구조가 다형성을 위해 사용될 수 있도록 해주며 OCP의 기반이 된다.
4. ISP (Interface segregation principle; 인터페이스 분리 원칙)
1) 정의 : 특정 클라이언트를 위한 여러 개의 구체적인 인터페이스가, 하나의 범용 인터페이스보다 낫다
2) 설명
클라이언트가 자신이 이용하지 않는 메서드에 의존하지 않아야 한다는 원칙
→ 큰 덩어리의 인터페이스들을 구체적이고 작은 단위들로 분리시킴으로써 클라이언트들이 꼭 필요한 메서드들만 이용할 수 있게 한다
3) 적용 방법
ISP 위반 ISP 적용 후 4) 장점
- 시스템의 내부 의존성을 약화시켜 리팩토링, 수정, 재배포를 쉽게 할 수 있다
5. DIP (Dependency inversion principle; 의존관계 역전 원칙)
1) 정의 : 추상화에 의존해야지, 구체화에 의존하면 안 된다
2) 설명
- 하위 모듈의 변경이 상위 모듈의 변경을 요구하는 전통적인 의존 관계를 역전 → 상위 모듈이 하위 모듈의 구현으로부터 독립
- 상위 모듈은 하위 모듈에 의존해서는 안된다. 상위 모듈과 하위 모듈 모두 동일한 추상화에 의존해야 한다.
- Dependency Injection은 이 원칙을 따르는 방법 중 하나
잘 구조화된 객체지향 아키텍처들은 각 레이어마다 잘 정의되고 통제되는 인터페이스를 통한 긴밀한 서비스들의 집합을 제공하는 레이어들로 구성되어 있다.
상위 레벨의 레이어가 하위 레벨의 레이어를 바로 의존하게 하는 것이 아니라, 이 둘 사이에 존재하는 추상 레벨을 통해 의존해야 한다.
3) 장점
- 상위 레벨의 모듈은 하위 레벨의 모듈로의 의존성에서 벗어나 그 자체로 재사용되고 확장성도 보장받을 수 있다.
헐리우드 원칙
과거 헐리우드에서는 배우들이 좋은 영화의 배역을 구하기 위해 영화제작사에 자주 전화를 걸었다고 한다.
배우들의 잦은 전화 때문에 영화기획사 담당자들이 자신의 업무를 할 수 없을 정도로 전화에 시달리게 됐다.
고민 끝에 이들은 한 가지 좋은 묘안을 생각해 냈다. 배우들에게 자신이 어떤 역할을 잘하며 어떤 영화 배역을 맡고 싶다고 등록하도록 한다.
기획 중인 영화에서 어떤 배역이 나왔을 때 배우가 등록한 목록에서 적합한 배우를 찾은 다음 그 배우에게 전화하면 캐스팅이 시작된다- 과거에는 배역을 원하는 소스(배우)들에게 능동적으로 배역을 요청/확인하게 하였고, 배역을 제공하는 타겟(영화기획사)은 수동적으로 전화가 올 때 정보를 제공했다. 이 상황에서 당연히 배우들이 아쉬운 입장이므로 전화 빈도수가 높아지고 기획사는 괴로워진다.
- 반면 헐리우드 원칙을 도입했을 때 배우는 기획사에 자신의 정보를 등록하면 될 뿐이고 기획사는 필요한 배우에게 캐스팅을 요청하면 될 뿐이다.
참고
- server-engineer.tistory.com/225
- medium.com/humanscape-tech/solid-%EB%B2%95%EC%B9%99-%E4%B8%AD-lid-fb9b89e383ef
- www.nextree.co.kr/p6960/
- zdnet.co.kr/view/?no=00000039139151
- ko.wikipedia.org/wiki/SOLID_(%EA%B0%9D%EC%B2%B4_%EC%A7%80%ED%96%A5_%EC%84%A4%EA%B3%84)
디자인패턴 - Dependency Injection 게시글 보기
2020/12/05 - [디자인패턴] - DI (Dependency Injection) : 의존성 주입
728x90'디자인패턴' 카테고리의 다른 글
DI (Dependency Injection) : 의존성 주입 (2) 2020.12.05