결합도와 응집도
결합도(Coupling)
결합도는 클래스 간의 의존성이 낮을수록 결합도가 낮다고 볼 수 있다.
하나의 클래스를 수정하는데 의존하는 다른 클래스를 모두 수정해야 한다면 결합도가 높은 것이다.
따라서 개발함에 있어 낮은 결합도로 개발하는 것이 주된 목표이다.
응집도(Cohesion)
응집도는 비슷한 일을 하는 기능(모듈 내부의 구성 요소)들이 기능적 관련성으로 잘 뭉쳐져 있다면 높은 응집도를 가진다고 볼 수 있다.
하나의 기능을 변경할 때, 다른 곳에서도 변경해야 할 곳이 많다면 응집력이 낮은 것이다.
따라서 개발함에 있어 높은 응집도로 개발하는 것이 주된 목표이다.
즉, 좋은 소프트웨어 설계를 위해서는 결합도는 낮추고, 응집도는 높여야 한다.
객체지향 설계 원칙(SOLID)
SOLID는 컴퓨터 프로그래밍에서 로버트 마틴이 2000년대 초반에 명명한 객체 지향 프로그래밍 및 설계의 5가지 기본 원칙을 마이클 페더스가 소개한 것이다.
SOLID 원칙은 등장부터 현재까지 수많은 사람들이 고민하고 시행착오를 겪으면서 가공된 것으로 좀 더 유지보수하기 쉽고, 유연하고, 확장이 쉬운 개발을 할 수 있도록 한다.
코드 베이스뿐만 아니라 아키텍처 설계에 이르기까지 다양하게 적용할 수 있다.
SOLID 원칙
SRP(Single Responsiblity Principle, 단일 책임 원칙)
OCP(Open Close Principle, 개방 폐쇄 원칙)
LSP(Liskov Substitution Principle, 리스코프 치환 원칙)
ISP(Interface Segregation Principle, 인터페이스 분리 원칙)
DIP(Dependency Inversion Principle, 의존관계 역전 원칙)
SRP(Single Responsiblity Principle, 단일 책임 원칙)
하나의 클래스는 하나의 책임만을 가져야 한다는 원칙이다.
여기서 말하는 책임은 요구 사항 변경으로 해석하면 쉽게 이해할 수 있다.
어떤 기능에 대한 요구 사항이 변경되었을 때, 변경에 대한 영향을 받는 기능들만 모아둔 클래스라면, 동일한 책임을 지닌 기능이 모인 집합으로써 SRP 원칙이 적용된 설계로 해석할 수 있다.
SRP를 지키지 않는 경우
- 응집도는 낮아지고, 결합도는 높아진다.
- 서로 다른 애플리케이션에 배포될 때 사용하지 않는 기능도 포함될 수 있다.
- 변수 레벨 : 하나의 속성이 여러 의미를 가지는 경우
- 메서드 레벨 : if문이 많은 경우
SRP를 잘 지키는 경우
- 응집도는 높아지고, 결합도는 낮아진다.
- 코드의 가독성이 좋아진다.
- 테스트 범위가 작아져 유지보수가 용이해진다.
AOP는 별도의 부가 기능을 핵심 로직에서 분리했기 때문에 SRP 원칙을 잘 지킨 방식으로 볼 수 있다.
OCP(Open Close Principle, 개방 폐쇄 원칙)
소프트웨어의 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다는 원칙이다.
변하는 것과 변하지 않는 것을 잘 구분하면 OCP를 잘 지킬 수 있게 된다.
변하지 않는 것은 변하는 것의 구현에 의존하지 않고, 인터페이스를 통해 느슨한 결합(Loose Coupling)이 되도록 해야 한다.
디자인 패턴 중 전략 패턴(Strategy Pattern)의 전략 인터페이스는 OCP의 Open에 해당하고, Context는 OCP의 Close에 해당한다.
확장에 열려 있다.
모듈의 동작을 확장할 수 있다는 것을 의미한다. 애플리케이션의 요구 사항이 변경될 때, 새로운 동작을 추가해야 한다면, 해당 모듈을 확장할 수 있다.
변경에 닫혀 있다.
모듈의
애플리케이션의 요구 사항이 변경될 때, 코드의 수정 없이 기능을 확장하거나 변경할 수 있다.
LSP(Liskov Substitution Principle, 리스코프 치환 원칙)
객체는 프로그램의 정확성을 깨트리지 않으면서, 하위 타입의 인스턴스로 바꿀 수 있어야 한다는 원칙이다.
하위 클래스는 인터페이스 규약을 지키면서 작성되어야 하며, LSP는 OCP 원칙의 기반이 되는 원칙으로 볼 수 있다.
ISP(Interface Segregation Principle, 인터페이스 분리 원칙)
인터페이스의 단일 책임을 위한 원칙으로, 특정 클라이언트를 위한 여러 개의 인터페이스로 분리하는 것이 하나의 범용 인터페이스보다 더 좋다는 것을 의미한다.
ISP 원칙은 큰 덩어리의 인터페이스들을 구체적이고 작은 단위들로 분리시킴으로써 클라이언트들이 꼭 필요한 메서드들만 이용할 수 있게 한다.
이러한 작은 단위의 인터페이스들을 역할 인터페이스라고도 한다.
ISP 원칙을 통해 시스템 내부 의존성을 느슨하게 할 수 있으며, 리팩토링, 수정, 유지보수를 쉽게 할 수 있다.
예를 들면,
- 사람의 행동(하나의 범용 인터페이스)을 쪼개어
- 말하는 행동(역할 인터페이스)
- 밥을 먹는 행동(역할 인터페이스)
- 잠을 자는 행동(역할 인터페이스)
등으로 분리하는 것을 말한다.
DIP(Dependency Inversion Principle, 의존관계 역전 원칙)
개발자는 추상화에 의존해야 하며, 구체화에 의존하면 안된다는 원칙이다.
의존성 주입(DI)을 통해 DIP 원칙을 따를 수 있다.
즉, 자주 변경되는 클래스에 의존하는 것이 아닌, 추상화된 인터페이스에 의존해야 한다는 것이다.
예를 들면, 영화를 제작한다고 가정하면
배역(인터페이스)에 의존해야 하지 배우(구현체)에 의존하면 안된다는 것이다.
즉, 영화를 제작할 때 특정 배우를 염두하고 영화를 제작하는 것이 아닌 배역에 집중해서 기획하여
배역에 알맞은 배우(기능)를 캐스팅해야 한다.
다르게 말하면, 해당 배역은 어떤 배우든 조건에 맞으면 연기할 수 있다.
하지만, 배우에 의존하게 된다면, 해당 배우가 스케줄이 맞지 않으면 다른 배우로 대체하기가 힘들어진다.
'언어(Language) > Java' 카테고리의 다른 글
[Java] 스택 트레이스(Stack Trace) 제대로 알고 읽기 (2) | 2022.11.13 |
---|---|
[Java] 자바 문자열 시작 문자, 끝 문자 판단 - startsWith(), endsWith() (0) | 2022.10.27 |
[Java] 자바 스택(Stack) 클래스 메서드 정리 및 활용 (0) | 2022.10.10 |
[Java] 자바 정규 표현식(Regex) 개념 정리 및 활용 (1) | 2022.10.01 |
[Java] 자바 가상 머신(JVM: Java Virtual Machine)이란? (0) | 2022.09.30 |