일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 도커
- Be
- Runtime Area
- pair programming
- 클린코드
- Java 22
- 트랜잭션 격리 수준
- ATDD
- GC
- testdrivendevelopment
- G1GC
- 부모객체
- M:N
- docker
- 미니미프로젝트
- Self Descript Message
- Solid
- hateoas
- 마이크로서비스디자인패턴
- 완벽이해
- Spring/JAVA 서적
- Execution Engine
- java
- 자식객체
- ComponentScan
- KPT
- RESAPI
- DB
- TDD
- 스프링으로하는마이크로서비스구축
- Today
- Total
Programming Summary
JAVA) SOLID 원칙이란? 본문
SOLID 원칙이란?
SOLID 원칙은 로버트 마틴이 2000년대 초반에 명명한 객체 지향 프로그래밍의 다섯가지 기본 원칙을 마이클 페더스가 두문자어 기억술로 소개한 것이다.
S(SRP : 단일 책임의 원칙)
클래스는 하나의 책임을 가져야한다. 이는 조금 추상적인 말이다. 이를 조금 더 구체적으로 말해보자면, 클래스가 변경되어야 하는 이유는 하나여야 한다는 것이다. 이는 해당 모듈이 여러 대상 또는 액터들에 대해 책임을 가져서는 안되고, 오직 하나의 액터
에 대해서만 책임을 져야 한다는 것이다. 일 어떤 모듈이 여러 액터에 대해 책임을 가지고 있다면 여러 액터들로부터 변경에 대한 요구가 올 수 있으므로 해당 모듈을 수정해야 하는 이유 역시 여러 개가 될 수 있다.
여기서 모듈
이라 함은 클래스
혹은 클래스의 모음
으로 해석할 수 있다. 지만 SRP를 위반하는지 판단하는 것은 상당히 어려운데, 동일한 대상이라 할지라도 유스케이스
나 요구 사항의 단계
에 따라 책임이 단일한지 여부가 달라질 수 있기 때문이다. 러므로 유스케이스
를 변경하거나 요구 사항이 달라질 경우 기존에 충족했던 단일 책임이 충족되지 못할 수 있다.
다음 코드는 우리 미니미 프로젝트 시작 프로그램의 일부이다.
public class BbaShaApplication {
private static View view = MAIN_VIEW.getView();
private static final Dispatcher dispatcher = Dispatcher.of();
public static void run() {
try{
startMain();
} catch(BbaShaException e) {
writelnAndFlush(e.getMessage());
}
}
public static void startMain() throws BbaShaException {
while(true) {
view.print();
String request = view.input();
if(request.equals("0")) return;
view = dispatcher.dispatch(view, request);
}
}
}
위의 BbaShaApplication
은 다음과 같은 다양한 액터로부터의 변경이 발생할 수 있다.
- 애플리케이션 운영자 ㅇㅇㅇ 책임 : 프로그램 실행 방식을 바꿔야 한다.
제품 관리 팀 ㅇㅇㅇ 팀장 : 사용성 개선을 위해 새로운 사용자 입력 형식 도입해야 한다.(마우스 클릭)
등등...
이러한 문제를 해결하기 위해 애플리케이션을 실행하는 부분과 메인 루프 및 사용자 입력을 처리하는 부분을 나눌 수 있다.
public class MainController {
private View view;
private final Dispatcher dispatcher;
public MainController(View initialView, Dispatcher dispatcher) {
this.view = initialView;
this.dispatcher = dispatcher;
}
public void startMain() throws BbaShaException {
while (true) {
view.print();
String request = view.input();
if (request.equals("0")) return;
view = dispatcher.dispatch(view, request);
}
}
}
public class MainController {
private View view;
private final Dispatcher dispatcher;
public MainController(View initialView, Dispatcher dispatcher) {
this.view = initialView;
this.dispatcher = dispatcher;
}
public void startMain() throws BbaShaException {
while (true) {
view.print();
String request = view.input();
if (request.equals("0")) return;
view = dispatcher.dispatch(view, request);
}
}
}
- 이를 통해 변경이 필요할 때 수정해야 할 대상을 명확히 함으로써 유지 보수성을 증가시킬 수 있다.
O(OCP : 개방-폐쇠의 원칙)
확장에는 열려있고 변경에는 닫혀있어야 한다는 원칙이다. 이는 인터페이스를 통해 주로 구현된다. 이를 조금 더 구체적으로 살펴보자.
- 확장에 대해 열려 있다: 요구사항이 변경될 때 새로운 동작을 추가하여 애플리케이션의 기능을 확장할 수 있다.
- 수정에 대해 닫혀 있다: 기존의 코드를 수정하지 않고 애플리케이션의 동작을 추가하거나 변경할 수 있다.
이를 우리 팀원은 다음과 같이 표현했다.
코드는 귀찮음이 많다. 그러므로 많은 일을 하고 싶지만 내가 바뀌기는 싫다.
개발자 역시 귀찮음이 많기 때문에 수정을 최소화 하되 기존의 기능을 통해 새로운 기능을 사용할 수 있도록 코드를 짜면 된다고 생각했다.
L(LSP : 리스코프 치환 원칙)
- 부모 클래스를 자식 클래스로 바꾸어 사용할 수 있어야 한다는 의미이다. 이것도 OCP에 이어 추상적인 것에 의존하라는 의미이다. 이를 조금 더 자세히 말하자면 해당 객체를 사용하는 클라이언트는 상위 타입이 하위 타입으로 변경되어도, 차이점을 인식하지 못한 채 상위 타입의 퍼블릭 인터페이스를 통해 서브 클래스를 사용할 수 있어야 한다는 것이다.
- 대표적으로 ArrayList를 들 수 있다. ArrayList를 선언할 때 부모인 List를 사용하는 게 더 좋다. 우리가 주로 사용하는 메서드들은 ArrayList만의 특성이 아니라 List 인터페이스에 정의된 메서드를 사용한다. 즉, 어떤 방식으로 구현된 List인지보다 List라는 것을 사용한다는 것이다.
I(ISP : 인터페이스 분리 원칙)
- 객체가 충분히 높은 응집도의 작은 단위로 설계되었더라도, 목적과 관심이 각기 다른 클라이언트에 있다면 인터페이스를 통해 적절히 분리해줄 필요가 있다. 이를 인터페이스 분리 원칙이라 부른다. 조금 더 쉽게 말하자면, 인터페이스를 만들 때 너무 광범위하게, 제너럴하게 만들지 말고, 조금씩 만들어 사용하도록 하라는 의미이다. 이를 준수함으로써 모든 클라이언트가 자신의 관심에 맞는 퍼블릭 인터페이스만을 접근하여 불필요한 간섭을 최소화할 수 있으며, 기존 클라이언트에 영향을 주지 않은 채로 유연하게 객체의 기능을 확정하거나 수정할 수 있다.
D(DIP : 의존관계 역전 원칙)
- 상위 모듈이 하위 모듈에 의존하지 않도록 구현하는 원칙이다.
- 고수준, 상위 모듈 : 입력과 출력으로부터 먼(비즈니스와 관련된) 추상화된 모듈
- 저수준, 하위 모듈 : 입력과 출력으로부터 가까운(HTTP, 데이터베이스, 캐시과 관련된) 구현 모듈
- 결국 의존관계 역전 원칙이란 비즈니스와 관련된 부분이 세부사항에는 의존하지 않도록 설계하는 것이다. 의존 역전 원칙은 개방 폐쇠 원칙과 밀접한 관련이 있으며 이를 위배하면 개방 폐쇄 원칙 역시 위배될 가능성이 높다.
참고
'프로 디지털 아카데미 4기' 카테고리의 다른 글
Spring) 어디서 DTO를 Entity로 변환해야 하는가? (0) | 2024.07.22 |
---|---|
Server) Web Server와 WAS는 무슨 차이일까? (0) | 2024.07.16 |
미니미 프로젝트) KPT 회고 (0) | 2024.07.15 |
방법론) TDD를 할까? 말까? (0) | 2024.07.12 |
Java) 나는 왜 자바를 좋아하는가? (0) | 2024.07.12 |