[객체지향] 객체 지향 설계 5원칙 - SOLID

JHJeong·2024년 5월 21일
0

객체지향 원리

목록 보기
4/5
post-custom-banner
  • 로버트 C.마틴이 2000년대 초반 객체지향 프로그래밍 및 설계의 다섯가지 기본 원칙으로 제시한 것을 마이클 페더스가 두문자어로 소개한 것
  • 응집도는 높이고(High Cohesion), 결합도는 낮추는(Loose Coupling)는 고전 원칙의 객체 지향의 관점에서 재정립한 것
  • 결합도 : 모듈(클래스) 간의 상호 의존 정도로서, 결합도가 낮으면 모듈 간의 상호 의존성이 줄어들어 객체의 재사용이나 수정, 유지보수가 용이함
  • 응집도 : 하나의 모듈 내부에 존재하는 구성 요소들의 기능적 관련성으로, 응집도가 높은 모듈은 하나의 책임에 집중하고 독립성이 높아져 재사용이나 기능의 수정, 유지보수가 용이함

1. SRP(Single Responsibility Principle) : 단일 책임 원칙

"어떤 클래스를 변경해야하는 이유는 오직 하나뿐이어야 한다" - 로버트 C.마틴

  • 하나의 속성은 하나의 의미만 가지고 있어야 한다.
  • 단일 책임 원칙과 가장 관계가 깊은 것은 바로 모델링 과정을 담당하는 추상화임을 알 수 있음

아래와 같이 남자라고 하는 클래스와 남자 클래스에 의존하는 다양한 클래스가 있다고 하면, 해당 남자는 여러 역할과 책임이 있다.

이러한 경우 단일 책임원칙에 위배되기 때문에 역할(책임)을 분리한다면 아래와 같이 여러 클래스로 나눌 수 있다.

class 강아지 {
	final static Boolean 수컷 = true;
	final static Boolean 암컷 = true;
	Boolean 성별;

	void 소변보다() {
		if( this.성별 == 수컷 ) {
			// 한쪽 다리를 들고 소변을 본다.
		}
		else {
			// 뒷다리 두개를 굽혀 앉은 자세로 소변을 본다.
		}
	}
}

위의 예제 소스는 강아지가 수컷인지 암컷인지에 따라서 메서드 내부에서 분기 처리가 진행된다. 이는 단일 책임(행위) 원칙을 위배하고 있는 것이다. 메서드가 단일 책임 원칙을 지키지 않을 경우 나타나는 대표적인 예제가 바로 if 문이다. 이런 경우 단일 책임 원칙을 적용해 코드를 리팩토링하면 아래처럼 만들 수 있다.

abstract class 강아지 {
	abstract void 소변보다();
}

class 수컷강아지 extends 강아지 {
	void 소변보다() {
		// 한쪽 다리를 들고 소변을 본다.
	}
}

class 암컷강아지 extends 강아지 {
	void 소변보다() {
		// 뒷다리 두개를 굽혀 앉은 자세로 소변을 본다.
	}
}

2. OCP(Open Closed Principle) : 개방 폐쇄 원칙

"소프트웨어 엔티티(클래스, 모듈, 함수 등)는 확장에 대해서는 열려 있어야 하지만 변경에 대해서는 닫혀 있어야한다." - 로버트 C.마틴

위 문장을 조금 더 의역하면 "자신의 확장에는 열려 있고, 주변의 변화에 대해서는 닫혀 있어야한다."로 나타낼 수 있다.

  • 제일 좋은 예는 JDBC, JDBC를 사용하는 클라이언트는 데이터베이스가 오라클에서 MySQL로 바뀌더라도 Connection을 설정하는 부분 외에는 따로 수정할 필요가 없음. Connection 설정 부분을 별도의 설정 파일로 분리해두면 클라이언트 코드는 단 한줄도 변경할 필요가 없음
  • JDBC 뿐만 아니라 iBatis, MyBatis, 하이버네이트 등등 데이터베이스 프로그래밍을 지원하는 라이브러리와 프레임워크에서도 개방 폐쇄 원칙의 예를 볼 수 있다.

위 그림을 보면 오라클을 MySQL 이나 MS-SQL로 교체해도 JDBC 인터페이스라는 완충 장치로 인해서 자바 애플리케이션은 변화에 닫혀있다.
그래서 데이터베이스를 교체한다는 것은 데이터베이스가 자신의 확장에는 열려 있다는 것이다.

  • 개방 폐쇄 원칙을 따르지 않는다고 해서 객체 지향 프로그램을 구현하는게 불가능하진 않지만 무시하고 작성하면 객체지향 프로그래밍의 가장 큰 장점인 유연성, 재사용성, 유지보수성을 얻을 수 없음
  • 스프링 프레임워크도 개방 폐쇄 원칙을 교과서적으로 활용하고 있는 예.

3. LSP(Liskov Substitution Principle) : 리스코프 치환 원칙

"서브 타입은 언제나 자신의 기반 타입(base type)으로 교체할 수 있어야 한다." - 로버트 C.마틴

  • 객체 상속의 조건은 다음과 같다
  • 하위 클래스 is a kind of 상위 클래스 : 하위 분류는 상위 분류의 한 종류이다.
  • 구현 클래스 is able to 인터페이스 : 구현 분류는 인터페이스할 수 있어야 한다.

위 문장대로 구현된 프로그램이라면 이미 리스코프 치환 원칙을 지키고 있는 것.
하지만 위 문장대로 구현되지 않는 코드가 있을 수 있는데, 바로 상속이 조직도나 계층도 형태로 구축된 경우이다.

위의 예는 계층도/조직도인 경우인데 딸이 아버지, 할아버지 역할을 하는 것이 논리에 맞지 않음을 알 수 있다.
리스코프 치환 원칙을 완벽하게 지원하는 경우는 아래와 같은 동물 분류도와 같은 경우이다.

4. ISP(Interface Segregation Principle) : 인터페이스 분리 원칙

"클라이언트는 자신이 사용하지 않는 메서드에 의존 관계를 맺으면 안된다." - 로버트 C.마틴

단일 책임원칙의 예를 다시 보면 남자가 단일 책임 원칙으로 여러 클래스로 분리됨을 보였는데, 이 방법 말고 다른 방법인 ISP, 인터페이스 분할 원칙도 존재한다.

이런 식으로 어머니와 있을 때는 아들 인터페이스로 제한하고, 직장상사와 있을 때는 사원 인터페이스로 제한하는 것이 바로 인터페이스 분할 원칙의 핵심이다.

  • 단일 책임 원칙(SRP)와 인터페이스 분할 원칙(ISP)는 같은 문제에 대한 두 가지 다른 해결책이라고 볼 수 있음
  • 인터페이스 최소주의 원칙 : 인터페이스를 통해 메서드를 외부에 제공할 때 최소한의 메서드만 제공하라는 것.( 아들 인터페이스에 출근하기() 함수는 공개할 필요가 없다는 것.)

5. DIP(Dependency Inversion Principle) : 의존 역전 원칙

"고차원 모듈은 저차원 모듈에 의존하면 안 된다. 이 두 모듈 모두 다른 추상화된 것에 의존해야 한다."
"추상화된 것은 구체적인 것에 의존하면 안된다. 구체적인 것이 추상화된 것에 의존해야한다."
"자주 변경되는 구체(Concrete) 클래스에 의존하지 마라" - 로버트 C.마틴

자동차와 스노우타이어 사이에는 위와 같은 의존 관계가 있다. 자동차가 스노우타이어에 의존한다.

그런데 계절이 바뀌면 일반타이어로 교체해야하는데, 이런 경우, 자동차 자신보다 더 자주 변하는 스노우타이어에 의존하고 있기 때문에 아래와 같이 추상화된 타이어 인터페이스에만 의존하게 함으로써 자동차는 영향을 받지 않는 형태로 구성해야 한다.

위 처럼 의존 방향이 역전 된 것을 의존 역전 원칙이라고 한다.
자신보다 변하기 쉬운 것에 의존하던 것을 추상화된 인터페이스나 상위 클래스를 두어 변하기 쉬운 것의 변화에 영향받지 않게 하는 것이 의존 역전 원칙이다.

6.정리

  • SOLID 는 객체 지향을 올바르게 프로그램에 녹여내기 위한 원칙
  • SoC(Separation Of Concerns) : 관심사의 분리 : 관심이 같은 것 끼리는 하나의 객체 안으로 또는 친한 객체로 모으고, 관심이 다른 것은 가능한 한 따로 떨어져 서로 영향을 주지 않도록 분리하라는 것
    -> 하나의 속성, 하나의 메서드, 하나의 클래스, 하나의 모듈, 또는 하나의 패키지에는 하나의 관심사만 들어 있어야한다는 것이 SoC 임
  • 이 SoC를 적용하면 자연스럽게 단일 책임 원칙(SRP), 인터페이스 분리 원칙(ISP), 개방 폐쇄 원칙(OCP)에 도달하게 됨

SRP(단일 책임 원칙) : 어떤 클래스를 변경해야 하는 이유는 오직 하나뿐이어야 한다.
OCP(개방 폐쇄 원칙) : 자산의 확장에는 열려 있고, 주변의 변화에 대해서는 닫혀 있어야한다.
LSP(리스코프 치환 원칙) : 서브 타입은 언제나 자신의 기반 타입으로 교체할 수 있어야한다.
ISP(인터페이스 분리 원칙) : 클라이언트는 자신이 사용하지 않는 메서드에 의존 관계를 맺으면 안된다.
DIP(의존 역전 원칙) : 자신보다 변하기 쉬운 것에 의존하지 마라.

profile
이것저것하고 싶은 개발자
post-custom-banner

0개의 댓글