티스토리 뷰
목차
SOLID라고 하는 5가지 객체지향 설계원칙이 있다. OOP의 개념이 이해가 되고 습득이 되어 해당 개념 또한 습득하여 내 것으로 만들어보고자 한다.
1. 단일 책임 원칙 - SRP (Single Responsibility Principle)
- 클래스는 단 한개의 책임을 가져야 함
- '책임' -> 기능정도로 보면 됨
- 하나의 클래스는 하나의 기능을 담당하여 하나의 책임을 수행할 수 있도록 함
- 만일 하나의 클래스에 기능이 여러개라면 기능 변경이 일어났을때 수정해야할 코드가 많아짐
- SRP 원칙을 따름으로써 한 책임의 변경으로부터 다른 책임의 변경으로의 연쇄작용을 극복할 수 있게됨
- 단일 책임 원칙의 목적은 프로그램의 유지보수성을 높이기 위한 설계 기법
- 모듈이 변경되는 이유가 한가지 여야 함
- SOLID 원칙의 기초가 됨
- SRP원칙 적용시 주의할 점
- 클래스명은 책임의 소재를 알 수 있도록 작명 -> 하나의 개념을 나타나게 구성
- 책임을 분리할때 결합도, 응집도 판단
2. 개방 폐쇄 원칙 - OCP (Open Closed Principle)
- 확장에 열려있어야 하며, 수정에는 닫혀있어야 한다.
- 클래스 확장을 통해 손쉽게 구현하면서 확장에 따른 클래스 수정은 최소화 하는 프로그램 설계 기법
- 확장에 열려있다
- 새로운 변경 사항이 있을 때 유연하게 코드를 추가함으로써 큰 힘을 들이지 않고 애플리케이션의 기능을 확장
- 모듈의 확장성 보장
- 변경에 닫혀있다
- 새로운 변경 사항이 발생했을 때 객체를 직접적으로 수정하는 것을 제한
- 새로운 변경사항이 발생했을 때 객체를 직접적으로 수정해야 한다면 새로운 변경사항에 대해 유연하게 대응할 수 없는 애플리케이션이라고 말함
- 확장에 열려있다
- 추상화 사용을 통한 관계 구축 권장을 의미
- 다형성과 확장을 가능케 하는 객체지향의 장점을 극대화하는 설계 원칙
- OCP 원칙을 따르는 자바의 데이터베이스 인터페이스 JDBC
- 데이터베이스 교체를 하고 싶을 때 하드코딩할 필요 없이 connection 객체 부분만 변경
- OCP 원칙 적용시 주의할 점
- 확장에는 열려있고 변경에는 닫히게 하기 위해서는 추상화를 잘 설계할 필요성이 있는데, 추상화를 정의할 때 여러 경우의 수에 대한 고려와 예측이 필요
- 추상 메서드 설계에서 적당한 추상화 레벨을 선택함으로써, 어떠한 행위에 대한 본질적인 정의를 서브 클래스에 전파함으로써 관계 성립
- OCP는 DIP의 설계 기반이 되기도 함
3. 리스코프 치환 원칙 - LSP (Liskov Substitution Principle)
- 서브 타입은 언제나 부모 타입으로 교체할 수 있어야 한다는 원칙
- 다형성 원리를 이용하기 위한 원칙 개념
- 다형성의 특징을 이용하기 위해 상위 클래스 타입으로 객체를 선언하여 하위 클래스의 인스턴스를 받으면 업캐스팅된 상태에서 부모의 메서드를 사용해도 동작이 의도대로 흘러가야 한다는 것을 의미
- 부모 메서드의 오버라이딩을 조심스럽게 따져가며 해야함 -> 부모 클래스와 동일한 수준의 선행 조건을 기대하고 사용하는 프로그램 코드에서 예상치 못한 문제를 일으킬 수 있음
- ex 자바에서 대표적으로 Collection 인터페이스를 lsp의 예 LinkedList -> HashSet으로 변경하여도 add() 메서드를 실행하는데 있어 원래 의도대로 작동
- 리스코프 치환 원칙은 협업하는 개발자 사이의 신뢰를 위한 원칙이기도 함
- LSP 원칙 적용시 주의할 점
- 다형성의 특징을 이용하기 위해 상위 클래스 타입으로 객체를 선언하여 하위 클래스의 인스턴스를 받으면 업캐스팅된 상태에서 부모의 메서드를 사용해도 동작이 의도대로만 흘러가도록 구성하면 되는 것
- LSP 원칙의 핵심은 상속
- 객체 지향 프로그래밍에서 상속은 기반 클래스와 서브 클래스 사이에 IS-A 관계가 있을 경우로만 제한
- extends 대신 인터페이스로 implements하여 인터페이스 타입으로 사용하기를 권장, 상위 클래스의 기능을 이용하거나 재사용을 하고 싶다면 상속 보단 합성으로 구성하기를 권장
4. 인터페이스 분리 원칙 - ISP (Interface Segregation Principle)
- 인터페이스를 각각 사용에 맞게 잘 분리해야한다는 설계 원칙
- SRP 원칙이 클래스의 단일 책임을 강조한다면, ISP는 인터페이스의 단일 책임을 강조하는 것으로 보면 됨
- SRP의 원칙의 목표는 클래스 분리를 통하여 이루어진다면, ISP 원칙은 인터페이스 분리를 통해 설계하는 원칙
- ISP 원칙은 인터페이스를 사용하는 클라이언트 기준으로 분리함으로써, 클라이언트의 목적과 용도에 적합한 인터페이스 만을 제공하는 것이 목표, 범용적인 인터페이스 보다는 클라리언트가 실제로 사용하는 인터페이스를 만들어야 함. 만약, 인터페이스의 추상 메서드들을 범용적으로 이것저것 구현한다면 그 인터페이스를 상속 받은 클래스는 자신이 사용하지 않은 인터페이스마저 억지로 구현 해야 하는 상황이 올 수도 있음
- 인터페이스는 제약 없이 자유롭게 다중 상속이 가능하기 때문에 분리할 수 있으면 분리하여 각 클래스 용도에 맞게 implements하라는 설계 원칙이라고 이해
- ISP 원칙 적용시 주의할 점
- 인터페이스에 기능에 대한 책임에 맞게 추상 메소드를 구성하면 됨
- 책임을 준수하더라도 실무에서는 ISP가 만족되지 않을 수 있는 케이스가 존재
- 한번 인터페이스를 분리하여 구성해놓고 나중에 무언가 수정사항이 생겨서 또 인터페이스들을 분리하는 행위를 가하면 안됨
- 본래 인터페이스는 한번 구성하였으면 왠만해선 변하면 안되는 정책 같은 개념
5. 의존 역전 원칙 - DIP (Dependency Inversion Principle)
- DIP 원칙은 어떤 class를 참조해서 사용해야하는 상황이 생긴다면, 그 클래스를 직접 참조하는 것이 아니라 그 대상의 상위 요소로 참조하라는 원칙
- 구현 클래스의 의존하지말고, 인터페이스에 의존
- 의존 관계를 맺을 때 변화하기 쉬운 것 또는 자주 변화하는 것보다는, 변화하기 어려운 것 거의 변화가 없는 것에 의존
- 객체들이 서로 정보를 주고 받을 때는 의존 관계가 형성되는데, 이 때 객체들은 나름대로의 원칙을 갖고 정보를 주고 받아야 하는 약속이 있는데 여기서 나름대로의 원칙이란 추상성이 낮은 클래스보다 추상성이 높은 클래스와 통신 한다는 것을 의미
- 자신보다 변하기 쉬운 것에 의존하던 것을 추상화된 인터페이스나 상위 클래스를 두어 변하기 쉬운 것의 변화에 영향받지 않게 하는 것
- 상위 클래스일수록, 인터페이스일수록, 추상 클래스일수록 변하지 않을 가능성이 높기에 하위 클래스나 구체 클래스가 아닌 상위 클래스, 인터페이스, 추상 클래스를 통해 의존
'IT > SOLID' 카테고리의 다른 글
| DIP - 의존성 역전 원칙 (Dependency Inversion Principle) (0) | 2025.04.29 |
|---|---|
| ISP - 인터페이스 분리 원칙(Interface Segregation Principle) (0) | 2025.04.28 |
| LSP - 리스코프 치환 원칙 (Liskov Substitution Principle) : "부모를 대체해도 문제가 없어야 한다" (0) | 2025.04.25 |
| OCP - 개방/폐쇄 원칙 (Open/Closed Principle) (0) | 2025.04.24 |
| SRP - 단일 책임 원칙 (Single Responsibility Principle) (0) | 2025.04.21 |