객체 지향 설계 원칙이란?
- 수많은 사람들이 고민하고 시행착오를 겪으면서 만든 원칙입니다.
- 좀 더 유지보수하기 쉽고, 유연하고, 확장이 쉬운 소프트웨어를 만들 수 있습니다.
- 코드 베이스뿐만 아니라 아키텍쳐 설계에 이르기까지 다양하게 적용할 수 있습니다.
높은 응집력이란?
- 비슷한 일을 하는 기능 즉, 하나의 책임에 포함되는 기능들이 잘 뭉쳐있다면 높은 응집력을 가진다고 볼 수 있습니다.
- 하나의 기능을 변경하는데 여기저기 변경해야 될 곳이 많다면 응집력이 낮다고 볼 수 있습니다.
낮은 결합도란?
- 클래스 간에 의존성이 낮다면 낮은 결합도를 가진다고 볼 수 있습니다.
- 하나의 클래스를 수정하는데 의존하는 다른 클래스를 모두 수정해야 한다면 결합도가 높다고 할 수 있습니다.
SOLID 원칙
- SRP, OCP, LSP, ISP, DIP의 첫 글자를 딴것이 SOLID 입니다.
SRP(Single Responsibility Principle, 단일 책임의 원칙)
- 클래스가 제공하는 기능들은 하나의 책임을 수행하는데 집중해야 한다는 원칙입니다.
- SRP를 지키지 않는다면?
- 응집력이 낮아지고, 결합도는 높아집니다.
- 서로 다른 애플리케이션에 배포될 때 사용하지 않는 기능도 포함됩니다. 즉, 왕따가 발생합니다.
- 변수 레벨
- 하나의 속성이 여러 의미를 가지는 경우
- 메서드 레벨
- if 문이 많을 경우
- SRP를 잘 지킨다면?
- 응집력이 높아지고, 결합도는 낮아집니다.
- 코드 가독성도 좋아집니다.
- 테스트 범위도 작아집니다. 즉 유지보수도 편해집니다.
- AOP는 별도의 부가 기능을 핵심 로직에서 분리했기 때문에 SRP의 원칙을 지킨 방식이라고도 할 수 있습니다.
SRP를 지키는 역할 분리의 예) Kevin이라는 클래스가 있다면?
- 남편의 역할
- 자주 전화해주기
- 기념일 챙기기
- 아빠의 역할
- 놀아주기
- 씻겨주기
- 재워주기
- 먹여주기
- 책 읽어주기
- 아들의 역할
- 건강 체크하기
- 용돈 주기
- 안부 전화하기
- 자주 방문하기
- 사위의 역할
- 건강 체크하기
- 용돈 주기
- 안부 전화하기
- 자주 방문하기
- 친구의 역할
- 안부 전화하기
- 술 마시기
- 고민 들어주기
- 직원의 역할
- 출근하기
- 열심히 일하기
- 회의하기
- 퇴근하기
OCP(Open Close Principle, 개방폐쇄의 원칙)
- 확장에는 열려있고(Open), 변경에는 닫혀 있어야 한다(Close)는 원칙입니다.
- 변하는것과 변하지 않는것을 잘 구분하면 OCP를 지키기 용이합니다. 변하는것은 Open, 변하지 않는 것은 Close에 해당됩니다.
- 변하지 않는것은 변하는 것의 구현에 의존하지 않고, 인터페이스를 통해 느슨하게 의존하게 만듭니다.
- 디자인 패턴 중에서 전략패턴의 전략 인터페이스는 OCP의 Open에 해당되고 Context는 OCP의 Close에 해당됩니다.
- 예)
- 자동차라는 객체에서 변하지 않는 동작
- 움직이는 것
- 자동차 객체에서 변하는 동작
- 수동 모드, 오토메이션 모드, 크루즈컨트롤 모드
- 자동차라는 객체에서 변하지 않는 동작
LSP(The Liskov Substitution Principle, 리스코브 치환의 원칙)
- subclass의 객체는 superclass의 참조 변수에 대입해서 superclass의 역할을 수행하는데 문제가 없어야 한다는 원칙입니다.
- OCP 원칙의 기반이 된다고 생각됩니다.
ISP(Interface Segregation Principle, 인터페이스 분리의 원칙)
- 인터페이스의 단일 책임을 위한 원칙입니다.
- 즉, 일반적인 하나의 인터페이스를 조금 더 구체적인 인터페이스로 쪼개는것이 낫다는 것입니다.
- 예)
- 새의 행동(일반적인 하나의 인터페이스)
- 날수 있는 행동(구체적인 인터페이스)
- 울수 있는 행동(구체적인 인터페이스)
DIP(Dependency Inversion Principle, 의존성 역전의 원칙)
- 자주 변경되는 구체 클래스에 의존하지 않고, 추상화(일반화) 된 클래스에 의존하는 것을 의미합니다.
- 구체 클래스가 추상 클래스에 의존하므로 의존 관계가 역전된 형태입니다.
- 예)
- Spring framework의 IOC 컨테이너
- 직접 객체를 생성하는것이 아니라 프레임워크에서 객체를 제공해줍니다.
- 느슨한 연결 측면에서의 DIP
- 추상 클래스에서 구체 클래스의 hook 메서드를 호출하는 것
- hook 메서드 호출 시, 구체 클래스가 무엇인지 알 필요가 없습니다.
- 추상 클래스에서 구체 클래스의 hook 메서드를 호출하는 것
- 이벤트 드리븐 방식
- 이벤트 리스너를 등록하고 hook 메서드를 통해 해당 이벤트를 처리합니다.
- hook 메서드 호훌 시, 구체적인 이벤트 리스너가 무엇인지 알 필요가 없습니다.
- 이벤트 리스너를 등록하고 hook 메서드를 통해 해당 이벤트를 처리합니다.
- Spring framework의 IOC 컨테이너