해당 사진은 객체 지향적으로 대강 잘만 프로그래밍 하면 되는 줄 알았던 안일한 과거의 저의 모습입니다.
좋은 객체 지향 프로그래밍. 말만 들어도 머리가 어지러운데 원칙까지 있다니...
벌써 눈을 질끈 감게 되는 저를 위해 좋은 객체 지향 설계의 5가지 원칙을 정리하는 글을 쓰겠습니다.
좋은 객체 지향 설계의 5가지 원칙
말 그대로 좋은 객체 지향 설계를 위한 로드맵 같은 원칙입니다.
이것만 지켜도 좋은 객체 지향 설계임을 증명할 수 있는 것입니다.
하지만 호락호락 하지 않습니다. 원칙은 5가지가 있고 하나하나가 복잡시럽습니다.
1. SRP (single responsibility principle) - 단일 책임 원칙
▶ "한 클래스는 하나의 책임만 가져야 한다."
하나의 책임이라는 것은 모호합니다. 클 수도 있고 작을 수도 있는데다가 문맥과 상황에 따라 달라집니다.
초장부터 이게 무슨 말인가 싶지만 중요한 기준은 변경입니다.
쉽게 설명 해 변경이 있을 때 파급 효과가 적으면 단일 책임원칙을 잘 따른 것이라 할 수 있습니다.
객체의 생성과 사용 분리라는 유식한 말로도 풀어 설명할 수 있는데요.
한 클래스에 이것 저것 기능을 넣지 말라는 말입니다.
한 클래스가 여러 기능을 구현하다 보면 그 안에서 결합력이 강해져 하나만 변경하기 어려워지기 때문입니다.
2. OCP (Open/closed principle) - 개방/폐쇄 원칙 (*중요)
▶ "소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다."
그야말로 열림 교회 닫힘과도 같은 말입니다.
쉽게 말 하면 기능을 확장하기 위해 프로그래밍을 할 때 기존 코드가 변경되지 않게 하라는 말입니다.
다형성을 활용 해 보면 더욱 쉽게 접근할 수 있습니다.
인터페이스를 구현한 새로운 클래스를 하나 만들어서 새로운 기능을 구현하는 것이 대표적 예시입니다.
구체 클래스의 로직을 변경할 때 클라이언트 클래스의 로직이 변경되면 이 원칙을 위반한 것입니다.
열심히 설명했지만 결론적으로 다형성만으로는 이 원칙을 충족시킬 수 없습니다.
때문에 이를 충족하기 위해서 스프링 컨테이너의 도움을 받아야 합니다.
3. LSP (Liskov substitution principle) - 리스코프 치환 원칙
▶ "프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다."
간단히 말 하자면 다형성에서 하위 클래스는 인터페이스 규약을 다 지켜야 한다는 뜻입니다.
이 말은 단순히 컴파일 성공을 넘어서는 뜻인데요.
예를 들어 자동차 인터페이스와 그의 구현체가 있다고 가정 해 봅시다.
자동차 인터페이스의 액셀 기능은 앞으로 가는 것이라는 규약이 있습니다.
하지만 구현체에서 액셀을 실행하면 뒤로 가도록 구현하여도 컴파일 시에는 전혀 문제가 없습니다.
하지만 LSP 리스코프 치환 원칙을 위배한 꼴이 되어 좋은 객체 지향 설계는 실패한 것입니다.
4. ISP (Interface segregation principle) - 인터페이스 분리 원칙
▶ "특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다."
간단히 예를 들어보겠습니다.
자동차 인터페이스를 운전 인터페이스, 정비 인터페이스로 분리합니다.
이렇게 되면 사용자 클라이언트를 운전자 클라이언트, 정비사 클라이언트로 분리할 수 있게 됩니다.
사용자를 분리하면 정비 인터페이스 자체가 변해도 운전자 클라이언트에 영향을 주지 않게 되죠.
인터페이스가 명확해지고 대체 가능성이 높아지는 겁니다.
운전자 클라이언트를 위한 운전 인터페이스, 정비사 클라이언트를 위한 정비 인터페이스,
특정 클라이언트를 위한 인터페이스 여러 개와 같은 말입니다.
범용적으로 쓰이는 인터페이스보다는 위와 같이 특정 클라이언트를 위한 인터페이스 여러 개를 만들 것을
권장하는 원칙입니다.
5. DIP (Dependency inversion principle) - 의존관계 역전 원칙 (*중요)
▶ "프로그래머는 추상화에 의존해야지, 구체화에 의존하면 안된다."
쉽게 이야기해서 구현 클래스에 의존하지 말고, 인터페이스에 의존하라는 뜻입니다.
객체 지향에서부터 이야기한 역할에 의존하게 해야 한다는 것과 같습니다.
객체 세상도 클라이언트가 인터페이스에 의존해야 유연하게 구현체를 변경할 수 있습니다.
반대로 구현체에 의존하게 되면 변경이 아주 어려워지는데요.
예를 들면 자동차 인터페이스와 테슬라라는 구현체가 있을 때 운전자가 자동차 역할을 잘 아는 것이 아니라
테슬라라는 구현만 알게 되면 후에 구현체를 변경해야 할 때 복잡해집니다.
어제 작성한 객체 지향 글에 이어 좋은 객체 지향 설계의 원칙에 대해 알아봤습니다.
누구나 좋은 프로그래밍을 하고 싶어하지만 정말로 좋은 프로그래밍을 하는 것은 꽤 어려운 일 같습니다.
오히려 이렇게 원칙으로 정해놓으니 더 수월하게 느껴질 수도 있지 않을까 하는 생각이 드네요.
참고로 좋은 객체 지향 설계의 원칙은 각 항복의 영문 앞글자들을 하나씩 합쳐서 SOLID라고 부릅니다.
다들 좋프 (좋은 프로그래밍이라는 뜻) 하세요 ~!
어제 작성한 따끈따끈한 객체 지향 설명 글 보러가기 !
스프링이 뭐지? (스프링 탄생 배경과 객체 지향, 다형성) (tistory.com)
스프링이 뭐지? (스프링 탄생 배경과 객체 지향, 다형성)
무언가를 배울 때 그 무언가가 왜 만들어졌는지, 즉 탄생 배경을 알면 배우기가 더 수월하다는 말을 들었습니다. 고로 스프링의 첫 단추를 꿰는 저 자신을 위해 탄생 배경에 대해 간략하게 설명
kes0917.tistory.com
해당 글은 김영한님의 스프링 핵심 강의를 기반으로 작성 되었습니다.
'Spring' 카테고리의 다른 글
[스프링] 자바 기반 AppConfig를 스프링으로 바꿔보자 (0) | 2023.03.15 |
---|---|
[스프링] DI, IoC, 컨테이너가 뭐지? (DI, IoC, 컨테이너의 간단 정리) (0) | 2023.03.15 |
[스프링] AppConfig을 리팩터링 해 보자 (0) | 2023.03.15 |
[스프링] AppConfig가 뭐지? (0) | 2023.03.14 |
[스프링] 스프링이 뭐지? (스프링 탄생 배경과 객체 지향, 다형성) (0) | 2023.03.08 |
댓글