좋은 객체 지향 설계의 다섯가지 원칙 (SOLID)
1. SRP 단일 책임 원칙 (Single Responsibility Principle)
- 한 클래스는 하나의 책임만 맡아야 한다. (약간 모호)
- SRP 판단의 기준은 변경이다. 변경이 있을 때 수많은 코드를 뜯어 고쳐야 한다면 SRP를 따르지 않은 것이고, 수정이 적다면 상대적으로 잘 따랐다고 볼 수 있다.
2. OCP 개방-폐쇄 원칙 (Open/Closed Principle)
- 소프트웨어 요소는 확장에는 열려있으나 변경에는 닫혀있어야 함. (다형성 활용 예시)
- 역할과 구현의 분리와 일맥상통
코드 변경은 없이, 하지만 다형성을 활용하면 객체만 바꿔치기 하면서 확장이 매우 넓어짐
하지만, 이는 사실 불가능하다.
MemberRepository repos = new MemoryMemberRepository();
MemberRepository repos = new JdbcMemberRepository();
위의 Memory를 활용한 repository에서 아래에 Jdbc를 활용한 repository로 바꾸기 위해서 분명 client측의 코드 변경이 불가피하다.
하지만, Spring에서는 이를 가능케 한다. (별도의 설정자)
3. LSP 리스코프 치환 원칙 (Liskov Substitution Principle)
- 프로그램의 객체는 프로그램의 정확성을 깨트리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다.
- 컴파일의 성공과는 무관.
- 인터페이스의 규칙, 규약을 지키는 것이다.
4. ISP 인터페이스 분리 원칙 (Interface Segregation Principle)
- 특정 클라이언트를 위한 인터페이스를 세부적인 인터페이스로 나눔
- 예를들어 자동차 인터페이스를, 운전/정비 인터페이스로 나누고, 사용자 클라이언트를 운전자/정비사 클라이언트로 나누는 것이다.
- 인터페이스가 훨씬 더 명확해짐
5. DIP 의존관계 역전 원칙 (Dependency Inversion Principle)
- 클라이언트쪽 코드가 구현체를 사용하지 않고, 인터페이스를 사용하게 할 것 (역할에만 의존할것) 운전자는 자동차의 역할만 알면 될 뿐, 차 종에 대해 깊이 알 필요는 없다.
- MemberRepository repos = new MemoryMemberRepository();
MemberRepository repos = new JdbcMemberRepository();
따라서, 해당 코드는 DIP를 위반한 것.
- 구체화가 아닌 추상화에 의존할 것
2. 그래서?
다형성만으로 SOLID를 지키기에는 턱도 없다. THEN?
3. 스프링의 이유
스프링은 SOLID원칙을 지키기 위해
- DI (의존관계, 의존성 주입)
- DI 컨테이너
를 사용하여 다형성,OCP,DIP를 가능케 한다.
4. 어쨌거나
어쨌거나 가장 중요한 것은
역할과 구현은 무조건 분리할 것