기본적인 개념
좋은 설계를 위한 객채 지향 원칙 묶음이다. 그저 원칙이기 때문에 OOP(객체 지향 프로그래밍)을 지원하는 모든 언어에 원칙을 적용 가능하다.
각 원칙은 따로 적용해야 하는 순서는 없고, 서로 다른 문제를 해결하기 위해 만든 원칙이기 때문에 문제가 없다면 원칙을 억지로 적용할 이유도 없다.
좋은 설계란?
- 코드를 확장하고, 유지보수 관리하기 쉬운 구조
- 복잡성을 제거해 가독성이 좋고, 리팩토링이 쉬운 구조
- 그럼으로, 새로운 요구사항이나 변경사항이 있을 때 영향을 받는 범위가 적고, 개발 생산성이 높은 구조
(좋은 설계란 이야기할 거리가 많은 주제입니다. 위 내용을 좋은 설계에 대한 개인적인 의견으로 받아들여 주시면 감사하겠습니다.)
SRP (Single Responsibility Principle) - 단일 책임 원칙
객체(클래스)는 단 하나의 책임(기능)만 가져야 한다는 원칙
만일 하나의 객체가 여러 기능을 담당하는 경우, 그중 하나의 기능을 수정할 때 다른 기능들도 연쇄적으로 수정해야하는 경우가 발생할 수 있다. 또는 하나의 기능에서 에러가 발생하면, 같은 객체에 묶인 기능들도 같이 못 쓰게 되버리는 경우도 발생할 수 있다.
이런 경우들을 미리 방지해서 프로그램의 유지보수성을 높이는 것이 목적인 원칙이다.
이때 책임의 범위는 개발자마다, 개발하는 프로그램마다 기준이 달라질 수 있다. 따라서 100% 정답이라 할 만한 기준은 없다.
OCP (Open Closed Principle) - 개방 폐쇄 원칙
확장에는 열러있고, 수정에는 닫혀있어야 한다는 원칙
해석하자면, 기능 추가 요청이 오면 클래스를 확장을 통해 손쉽게 구현하면서, 확장에 따른 클래스 수정은 최소화 하도록 프로그램을 작성해야 하는 설계 기법을 말한다고 보면 된다. 즉, 기존의 코드를 변경하지 않으면서 기능을 유연하게 추가할 수 있도록 설계해야 한다는 원칙이다.
다형성과 확장을 극대화하는게 목적인 원칙이다.
LSP (Liskov Substitution Principle) - 리스코프 치환 원칙
서브 타입은 언제나 기반(부모) 타입으로 교체할 수 있어야 한다는 원칙이다.
다형성의 특징을 이용하기 위한 원칙으로, 상위 클래스 타입으로 객체를 선언하여 하위 클래스의 인스턴스를 받으면, 업캐스팅된 상태에서 부모의 메서드를 사용해도 동작이 의도대로 흘러가야 하는 것을 의미하는 것이다.
따라서 이 원칙을 지키기 위해서는, 부모메서드의 오버라이딩을 할 때 정신줄 잡고 해야 한다. 만약 부모 메서드의 선행조건을 반영하지 못하면, 같은 선행 조건을 기대하고 사용되는 코드에서 문제가 발생할 수 있기 때문이다.
대표예시 : Collection 인터페이스
LinkedList도 add()나 HashSet도 add()나 둘 다 같은 의미와 기능을 수행한다.
public void myData() {
// Collection 인터페이스 타입으로 변수 선언
Collection data = new LinkedList();
data = new HashSet(); // 중간에 전혀 다른 자료형 클래스를 할당해도 호환됨
modify(data); // 메소드 실행
}
public void modify(Collection data){
list.add(1); // 인터페이스 구현 구조가 잘 잡혀있기 때문에 add 메소드 동작이 각기 자료형에 맞게 보장됨
// ...
}
ISP (Interface Segregation Principle) - 인터페이스 분리 원칙
인터페이스를 각각 사용에 맞게 끔 잘게 분리해야한다는 설계 원칙이다.
어차피 인터페이스는 몇 개든 자유롭게 다중 상속이 가능하니까, 분리할 수 있으면 분리하고, 사용할 때는 용도에 맞게 가져다가 쓰라는 원칙이다. 괜히 하나에 몰빵해서 구분하기도, 찾기도 어렵게 하지 말고
주의할 점은 인터페이스를 분리해서 구성했다면, 나중에 수정, 변경사항이 생겼을 때, 또 변경하면 안된다는 것이다. (한번 인터페이스를 구성했으면 왠만해선 변하면 안된다.)
SRP와 비슷해 보이는데, 다른 점은 SRP 원칙이 클래스의 단일 책임을 강조한다면, ISP는 인터페이스의 단일 책임을 강조하는 것으로 보면 된다.
DIP (Dependency Inversion Principle) - 의존 역전 원칙
DIP 원칙은 어떤 Class를 참조해서 사용해야하는 상황이 생긴다면, 그 Class를 직접 참조하는 것이 아니라 그 대상의 상위 요소(추상 클래스 or 인터페이스)로 참조하라는 원칙이다.
쉽게 이야기해서 구현 클래스에 의존하지 말고, 인터페이스에 의존하라는 뜻으로, 이렇게 함으로써 각 클래스간의 결합도를 낮추는 것이 목적이다.
출처 & 참고문헌
'CS' 카테고리의 다른 글
실수계산 오차와 부동소수점 ( feat. IEEE 754 표준 ) 1부 (1) | 2024.11.25 |
---|---|
C언어의 컴파일 과정 (1) | 2023.12.22 |
소켓이란? (0) | 2023.12.19 |
자바 인코딩의 원리 (2) | 2023.11.08 |
API (Application Programming Interface ) 개념 설명 (0) | 2023.06.21 |