객체 지향 프로그래밍에서 정말 중요하게 여겨지는 5가지 원칙이 있다.
프로그래머들의 필독서로 유명한 클린코드의 저자 로버트 마틴이 객체 지향에서 중요한 5가지 개념을 정리한 것인데
SOLID원칙 이라고도 많이 알려져있다.
이번에는 이 객체 지향의 5가지 원칙 SOLID에 대해 얘기하고자 한다.
SOLID
SRP: 단일 책임 원칙 (single responsibility principle)
OCP: 개방-폐쇄 원칙 (open/closed principle)
LSP: 리스코프 치환 원칙 (Liskov substitution principle)
ISP: 인터페이스 분리 원칙 (Interface segregation principle)
DIP: 의존관계 역전 원칙 (Dependency inversion principle)
1. SRP - 단일 책인 원칙 (single responsibility principle)
한 클래스는 하나의 책임만 가져야 한다는 뜻이다.
하나의 책임이라는 것은 문맥과 상황에 따라 달라지므로 모호할 수 있지만, 중요한 기준은 변경에 있다.
변경이 있을 때 파급 효과가 크면 단일 책임 원칙을 잘 못 지킨 것이고, 작으면 단일 책임 원칙을 잘 지켰다고 할 수 있다.
예를 들어 보고서를 편집하고 출력하는 모듈을 생각해 보자.
이 모듈은 두 가지 이유로 변경될 수 있는데, 하나는 보고서의 내용 때문일 수 있고, 다른 하나는 보고서의 형식 때문일 수 있다.
이 두가지 변경은 하나는 보고서의 내용(텍스트) 측면, 다른 하나는 보고서의 디자인 측면이라는 서로 매우 다른 원인에서 비롯된다.
따라서 단일 책임 원칙관점에서 보고서를 편집하고 출력하는 모듈은 잘못된 설계이고,
해당 모듈은 두 가지 책임이 서로 분리된 모듈로 나뉘어야 한다.
2. OCP - 개방-폐쇄 원칙 (open/closed principle)
SOLID 5가지 원칙 중 DIP와 더불어 가장 중요하게 여겨지는 원칙이다.
개방-폐쇄 원칙이란 소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어햐 한다는 원칙이다.
중요한 개념인 만큼 그림을 참고하여 설명하려 한다.
운전자는 자동차면허만 있다면 자동차 종류에 상관없이 운전을 할 수 있다.
이를 프로그래밍 관점에서 보자면 인터페이스는 자동차, 구현체는 전기자동차, 경유자동차, 수소자동차라고 할 수 있다.
이때 운전자가 휘발유자동차를 운전해야하는 상황이 생긴다면 단순히 휘발유자동차 구현체만 추가해 주면 되고
자동차 인터페이스를 가르키는 운전자가 해야할 일은 없다.
하지만 만약 운전자가 자동차 인터페이스가 아니라 전기자동차나 수소자동차등 특정 구현체를 가르킨다면
다르게 말해 자동차의 종류에 따라 운전법이 다르고 운전면허가 따로 있다면,
운전자는 운전해야 하는 자동차의 종류가 달라질때마다 새로운 운전면허를 따야되는 불쌍한 일이 벌어지게 된다.
따라서 자동차의 종류는 필요에 따라 추가할 수 있지만, 운전자는 운전만 할줄 알면 어떤 종류에 차를 운전하든 변경할 필요가 없는것
즉, '확장에는 열려 있으나 변경에는 닫혀 있는것' 이것이 개방-폐쇄 원칙이다.
3. LSP - 리스코프 치환 원칙 (Liskov substitution principle)
프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다는 원칙이다.
다형성에서 하위 클래스는 인터페이스 규약을 다 지켜야 한다는 뜻으로 다형성을 지원하기 위한 원칙이다.
사용자가 인터페이스를 믿고 사용하려면 인터페이스를 구현한 구현체는 이 원칙을 지켜야 한다.
이것은 단순히 컴파일에 성공하는 것을 넘어서는 이야기다.
예를 들어 자동차 인터페이스에서 밣으면 앞으로 가는것을 의도하고 추상메서드로 엑셀을 만들었다고 하자.
만약 자동차 종류중 하나가 엑셀메서드에서 자동차가 멈추는 기능을 구현한다면 확장은 정상적으로 될것이다.
하지만 운전자가 멋모르고 이 자동차를 운전하면 대형사고로 이어질 수 있다.
따라서 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야한다.
4. ISP - 인터페이스 분리 원칙 (Interface segregation principle)
특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다는 원칙이다.
예를들면 자동차 인터페이스는 운전 인터페이스와 정비 인터페이스로 분리할 수 있고,
사용자는 운전자와 정비사로 분리할 수 있다.
이렇게 분리하면 정비 인터페이스 자체가 변해도 운전자 클라이언트에는 영향을 주지 않게 된다.
즉, 인터페이스가 명확해지고, 대체 가능성이 높아지게 된다.
5. DIP - 의존관계 역전 원칙 (Dependency inversion principle)
앞서 말했듯이 이 원칙은 OCP와 더불어서 객체 지향 5원칙 중 가장중요한 원칙이다.
DIP란 프로그래머는 "추상화에 의존해야지, 구체화에 의존하면 안된다." 라는 원칙이다.
쉽게 이야기해서 구현 클래스에 의존하지 말고, 인터페이스에 의존하라는 뜻이다.
위에 있는 그림을 예를 들자면, 운전자는 자동차를 운전할 수 있다면 전기자동차, 수소자동차, 경유 자동차 모두 운전할 수 있게 설계해야한다.
만약 운전자가 전기자동차'만', 수소자동차'만' 운전할 수 있게 설계한다면 프로그램은 확장하기 어렵고 변경 또한 어렵게 된다.
참고: 인프런 - '스프링 핵심 원리 - 기본편'