'객체 지향 프로그래밍' 두 번째 게시글은 객체 지향 프로그래밍의 5가지 핵심 원칙인 SOLID에 대해 여러가지 참고 자료를 통해 공부한 내용을 정리해보려고 한다.
객체 지향 프로그래밍의 5가지 설계 원칙, SOLID
1. 단일 책임의 원칙(SRP, Single Responsibility Priciple)
<클래스는 단 하나의 책임을 가져야 하며, 클래스를 변경하는 이유는 단 하나의 이유여야 한다.>
- 중요한 기준은 변경
- 변경이 있을 때 파급효과가 적으면, 단일 책임의 원칙을 잘 따른 것
클래스를 변경하는 이유가 한가지라는 것은 해당 클래스(모듈)가 여러 대상 또는 액터들에 대해 책임을 가져서는 안되고, 오직 하나의 액터에 대해서만 책임을 져야 한다는 뜻!
여러 액터에 대해 책임을 가지고 있다면 여러 액터들로부터 변경에 대한 요구가 올 수 있으므로, 해당 클래스(모듈)을 수정해야 하는 이유 역시 여러개가 될 수 있다. 반면 어떤 클래스가 단 하나의 책임 만을 가지고 있다면, 특정 액터로부터 변경을 특정할 수 있으므로 해당 클래스를 변경해야 하는 이유와 시점이 명확해짐!
2. 개방 폐쇄 원칙(OCP, Open-Closed Principle)
<확장에는 열려있고, 변경에는 닫혀 있어야 한다.>
- 확장에 대해 열려 있다 - 요구사항이 변경될 때 새로운 동작을 추가하여 애플리케이션의 기능을 확장할 수 있다.
- 수정에 대해 닫혀 있다 - 기존의 코드를 수정하지 않고 애플리케이션의 동작을 추가하거나 변경할 수 있다.
- 인터페이스를 구현한 새로운 클래스를 만들어서 새로운 기능을 구현 -> 기존 코드를 변경하지 않으면서 확장하는 방법
- 만약 구현 객체를 변경하기 위해 클라이언트 코드를 변경한다면 그것은 OCP원칙을 잘 지키지 못한것 -> 객체를 생성하고, 연관관계를 맺어주는 별도의 조립, 설정자가 필요함
개방 폐쇄 원칙을 지키기 위해서는 추상화에 의존해야 한다.
추상화란 핵심적인 부분만 남기고, 불필요한 부분은 제거하여 보다 간단하게 만드는 것이고, 추상화를 통해 변하지 않는 부분만 남김으로써 기능을 구체화하고 확장할 수 있다. 변하지 않는 부분은 고정하고 변하는 부분을 생략하여 추상화함으로써 변경이 필요한 경우에 생략된 부분을 수정하여 개방-폐쇄 원칙을 지킬 수 있다.
추상화를 통해 변하는 것들은 숨기고 변하지 않는 것들에 의존하게 하면 우리는 기존의 코드 및 클래스들을 수정하지 않은 채로 애플리케이션을 확장할 수 있다. 이것이 곧 개방 폐쇄의 원칙이 의미하는 바.
3. 리스코프 치환 원칙(LSP, Liskov Substitution Principle)
<상위 타입의 객체를 하위 타입의 객체로 치환해도 상위 타입을 사용하는 프로그램은 정상적으로 작동해야 한다.>
- 프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀수 있어야함
즉, 하위 타입은 상위 타입을 대체할 수 있어야 한다. 해당 객체를 사용하는 클라이언트는 상위 타입이 하위 타입으로 변경되어도, 차이점을 인식하지 못한 채 상위 타입의 퍼블릭 인터페이스를 통해 서브 클래스를 사용할 수 있어야 한다.
리스코프 치환 원칙은 자식 클래스가 부모 클래스를 대체하기 위해 부모 클래스에 대한 클라이언트의 가정을 준수해야 한다는 것을 강조한다.
4. 인터페이스 분리 원칙(ISP, Interface Segregation Principle)
<인터페이스는 그 인터페이스를 사용하는 클라이언트를 기준으로 분리해야 한다.>
- 특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.
- 자동차 인터페이스 -> 운전 인터페이스, 정비 인터페이스로 분리
- 사용자 클라이언트 -> 운전자 클라이언트, 정비사 클라이언트로 분리
- 위처럼 분리하면 정비 인터페이스가 변해도 운전자 클라이언트에 영향을 주지 않는다. -> 인터페이스가 명확해지고, 대체 가능성이 높아진다.
객체가 충분히 높은 응집도의 작은 단위로 설계되었더라도, 목적과 관심이 다른 클라이언트가 있다면 인터페이스를 통해 적절하게 분리해줄 필요가 있는데, 이를 인터페이스 분리 원칙이라고 한다.
즉, 클라이언트의 목적과 용도에 적합한 인터페이스 만을 제공하는 것이다.
인터페이스 분리 원칙을 준수함으로써 모든 클라이언트가 자신의 관심에 맞는 퍼블릭 인터페이스만을 접근하여 불필요한 간섭을 최소화 할 수 있으며, 기존 클라이언트에 영향을 주지 않은 채로 유연하게 객체의 기능을 확장하거나 수정할 수 있다.
5. 의존 역전 원칙(DIP, Dependency Inversion Principle)
<고수준 모듈은 저수주 모듈의 구현에 의존해서는 안된다.>
- 프로그래머는 "추상화에 의존해야지, 구체화에 의존하면 안된다."
- 구현 클래스에 의존하지 말고, 인터페이스에 의존하라는 뜻
- 구현 객체에 의존하지 말고 역할(Role)이 설명되어 있는 인터페이스에 의존하자!
고수준 모듈은 저수준 모듈의 구현에 의존해서는 안되며, 항상 저수준 모듈이 고수준 모듈에 의존해야 한다는 것.
객체 지향 프로그래밍에서는 객체들 사이에 메시지를 주고 받기 위해 의존성이 생기는데, 의존성 역전의 원칙은 올바른 의존 관계를 위한 원칙에 해당된다. 여기서 저수준 모듈과 고수준 모듈은 다음을 의미한다.
- 고수준 모듈 : 입력과 출력으로부터 먼(비즈니스와 관련된) 추상화된 모듈
- 저수준 모듈 : 입력과 출력으로부터 가까운(HTTP, 데이터베이스, 캐시 등과 관련된) 구현 모듈
의존 역전 원칙이란 결국 비즈니스와 관련된 부분이 세부사항에는 의존하지 않는 설계 원칙을 의미한다.
의존 역전 원칙은 개방 폐쇄 원칙과 밀접한 관련이 있으며, 의존 역전 원칙이 위배되면 개방 폐쇄 원칙 역시 위배될 가능성이 높다.
결론적으로 5가지의 객체 지향 설계 원칙인 'SOLID 원칙' 이 이야기 하는 것의 핵심은 추상화와 다형성이다.
구체 클래스에 의존하지 않고 추상 클래스(또는 인터페이스)에 의존함으로써 유연하고 확장가능한 애플리케이션을 만들 수 있다.
참고 : https://mangkyu.tistory.com/194, https://github.com/WooVictory/Ready-For-Tech-Interview/blob/master/Java/%5BJava%5D%20%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%20%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%20%EA%B0%9C%EB%85%90.md, 김영한의 스프링 핵심원리 - 기본편
'CS' 카테고리의 다른 글
Object Oriented Programming(객체 지향 프로그래밍) - 1 (0) | 2023.07.19 |
---|