객체 지향 5원칙 SOLID

2023. 11. 7. 14:47java

1. 단일 책임 원칙(SRP)

하나의 모듈이 하나의 책임을 가진다. -> 오직 하나의 기능을 맡아야한다.

업무를 효율적으로 분리할 수 있다.

-> DB 패스워드 암호화 방식을 변경해야합니다.

-> DB Entity 를 정의해야합니다.

 

예시

게임을 만든다고 가정.(Map과 Unit 으로 구성)

이 때 Map class에 Unit을 분류하는 기능이 있다면? 단일 책임 원칙에 위배된다.

 

왜 문제인가?

새로운 Unit이 생겼을때 Unit class를 건드려야하는데 Unit이 아니라 Map을 건드려야한다.

 

 

2. 개방 폐쇄 원칙(OCP)

확장에 대해선 열여있고 수정에 대해선 닫혀있다.

1. 확장에 대해 열려있다. : 요구 사항에 대해 기능을 추가할 수 있다.

2. 수정에 대해 닫혀있다. : 수정하지 않은채로 기능을 추가해야한다.

 

예시

기존에 정의되어있던 Unit을 만드는 방식이 A에서 B로 변경되었다.

이때 Aunit class를 사용하고 있었다면? 개방 폐쇄 원칙에 위배된다.

 

왜 문제인가?

AUnit class를 Map에서 사용하고 있었는데 BUnit class 로 바뀌었으니 해당 선언부를 수정해야한다.

 

추상화, 다형성을 이용하여 이를 해결할 수 있다.

interface를 이용하는 코드를 사용한다. 즉 Unit interface를 생성하여 코드를 사용한다.

그러면 Map을 바꿀 필요없이 Map 객체를 만들 때 BUnit을 넣어 초기화 시켜주면 된다.

 

런타임 의존성? 컴파일 의존성?

컴파일 시점에선 Unit에 의존하고 있으나 런타임 시점에선 BUnit에 의존한다.

객체지향 프로그래밍에선 이 두 시점을 구분해야한다.

 

3. 인터페이스 분리 원칙(ISP)

클라이언트가 자신이 이용하지 않는 기능을 제공하는 인터페이스를 사용해선 안된다.

 

예시

게임에 새롭게 skill class 를 생성했다. 이때 기존 Unit interface에 create 함수만 정의되어있었는데 

skill 함수를 추가했다. 이때 인터페이스 분리 원칙을 위반한다.

 

왜 문제인가?

BUnit은 skill이 필요없고 create만 필요하다. Unit 으로 skill을 접근할 수 있게됬는데 BUnit에 없는 기능을 사용할 수 있게된 것이다.

 

UnitSkill이라는 새로운 인터페이스를 만들어 이를 해결할 수 있다.

만약 skill과 create 모두 필요한 class가 생긴다면, 이 두 인터페이스를 상속받으면 된다.

 

4. 리스코프 치환 원칙(LSP)

하위 타입은 상위 타입을 대체할 수 있어야한다.

클라이언트가 객체를 사용할때 상위 타입에서 하위 타입으로 변경해서 객체를 사용할 때 차이점을 인식하지 못해야한다.

 

예시

상위 : 직사각형

하위 : 정사각형 (정사각형을 상속 받음)

직사각형은 가로와 세로를 설정하는 함수가 있다. 이를 정사각형이 오버라이딩해서 가로를 입력하건 세로를 입력하건

가로와 세로 모두 같도록 설정하도록 기능을 변경했다고 가정하자.

이러면 리스코프 치환 원칙을 위반하게 된다.

 

 

왜 문제인가?

다형성으로 부모 클래스로 자식 클래스 타입의 인스턴스를 참조할 수 있는데 이때 하위 타입과 상위 타입이 호환이 안된다면

예기치 않은 오류가 발생할 수 있다.

클라이언트 입장에서 직사각형으로 정사각형 타입의 인스턴스를 참조했는데 정사각형의 가로 설정, 세로 설정함수를

이용했더니 가로 세로가 각각 설정되는게 아니라 계속 같도록 설정되는 예기치 않는 오류가 생길 수 있다.

 

오버라이딩을 좀 더 세심히 신경쓰고 접근 제어자를 이용하여 호환에 문제가 생길 부분을 제한한다.

 

5. 의존 역전 법칙(DIP)

저수준 모듈이 고수준 모듈에 의존해야한다.

저수준 모듈? 입력과 출력과 가까운 구현 모듈

고수준 모듈? 도메인과 관련된 추상화된 모듈

 

고수준 모듈이 우리가 위 예제에서 살펴본 Interface와 관련이 있다.

추상화에 의존하도록 변경하여 유연한 애플리케이션을 만들 수 있다.

여기서 의존성이 역전되는 시점은 컴파일 시점이다. 컴파일 시점에 인터페이스에 의존해야한다는 뜻이다.

 

'java' 카테고리의 다른 글

우테코 3주차 소감문  (0) 2023.11.08
디자인 패턴(생성 패턴)  (0) 2023.11.07
stream 문법  (0) 2023.11.05
함수형 프로그래밍 , 람다식  (0) 2023.11.05
자바 Arrays.asList  (0) 2023.11.05