<aside>
📚 • 2장에서 객체지향에 대한 기본적인 내용을 살펴보았다면 3장은 SOLID 같은 고전적인 설계 원칙 몇 가지를 소개한다.
• 설계 원칙을 이해하는 것도 중요하지만 실제 프로젝트에서 사용하는 방법을 정확하게 알고 있어야 한다.
• CH3 에서는 각 설계 원칙의 정의와 의도, 사용하는 방법을 알아보자.
</aside>
<aside>
💡 • 설계 원칙을 배울 때, 정의를 이해하는 것보다 훨씬 중요한 것은 왜 그 원칙이 생겨날 수 밖에 없었는지를 생각하여 목적을 파악하는 것이다.
• 그래야만 설계 원칙을 적절하고 유연하게 적용할 수 있게 된다.
</aside>
3.1 단일 책임 원칙
단일 책임 원칙의 정의 및 해석
- 클래스와 모듈은 하나의 책임 또는 기능만을 가지고 있어야 한다는 설계 원칙
- 거대하고 포괄적인 클래스를 설계하는 대신 작은 단위와 단일 기능을 가진 클래스를 설계해야 한다.
- 클래스에 비즈니스와 관련 없는 기능이 두 개 이상 포함되어 있으면 책임이 단일하지 않으므로 여러개의 작은 클래스로 분할되어야 한다.
클래스에 단일 책임이 있는지 판단하는 방법
- 클래스에 단일 책임이 있는지를 평가할 수 있는 표준은 존재하지 않는다.
- 처음에는 단일 책임을 가지더라도 클래스에 기능이 추가되고 코드가 복잡해지면서 클래스의 책임이 거대해질 수 있다.
- 이 경우 거대해진 클래스를 여러개의 세분화된 클래스로 다시 나눌 필요가 있다.
- 단일 책임 여부를 결정하기 위해 사용되는 몇가지 결정 원칙
- 클래스에 코드, 함수, 속성이 너무 많아 코드의 가독성과 유지 보수에 영향을 미치는 경우 클래스 분할을 고려해야 한다.
- 클래스가 과하게 다른 클래스에 의존한다면 높은 응집도와 낮은 결합도의 코드 설계 사상에 부합하지 않으므로 클래스 분할을 고려해야 한다.
- private 메서드가 너무 많은 경우 새로운 클래스로 분리하고 public 메서드로 설정하여 코드의 재사용성을 향상시키는 것이 좋다.
- 클래스의 이름을 정확하게 지정하기 어렵다면 클래스의 책임 정의가 충분히 명확하지 않은 것이다.
- 클래스의 메서드들이 여러 속성 중 일부에서만 작동하는 경우 이러한 속성과 해당 메서드를 분할하는 것을 고려하자.
- 무조건 클래스를 작게 나누는 것도 좋지 않다.
- 코드의 응집력은 유지해야 한다.
- 모든 설계 원칙의 목표는 코드의 가독성 / 확장성 / 재사용성 / 유지 보수성을 향상시키는 것이다.
3.2 개방 폐쇄 원칙
확장할 때는 개방, 수정할 때는 폐쇄
- 새 기능을 추가할 때 기존 모듈, 클래스, 함수를 수정하기 보다는 새로운 모듈, 클래스, 함수 등을 추가하는 방식으로 코드를 확장해야 한다는 원칙
- 개방 폐쇄 원칙은 가장 이해하기 어렵고, 마스터하기 어려우면서도 가장 유용한 원칙이다.
- 코드를 변경할 때 그 결과를 확장으로 보아야 하는지 수정으로 보아야 하는지 명확하게 구분하기 어렵기 때문
- 기존 모듈 / 클래스 / 함수를 수정하면 발생하는 문제
- 기존에 이를 사용하고 있던 모든 부분(비즈니스 로직, 테스트 코드 등)이 수정의 영향을 받을 수 있다.
코드를 수정하는 것은 개방 폐쇄 원칙을 위반하는 것일까?
- 코드의 수정이 기존에 작성되었던 코드와 단위 테스트를 깨뜨리지 않는 한 이는 개방 폐쇄 원칙을 위반하지 않는다고 봐도 무방하다.
- 새로운 기능을 추가할 때 모듈 / 클래스 / 메서드의 코드를 전혀 수정하지 않는 것은 불가능하다.
- 수정을 아예 안하고자 하는게 아니라, 수정을 가능한 한 상위 수준의 코드에서 진행하고, 코드의 핵심 부분이나 복잡한 부분, 공통 / 기반 코드가 개방 폐쇄 원칙을 충족하는 방향으로 노력해야 한다.
확장할때는 개방, 수정할 때는 폐쇄를 달성하는 방법
- 처음에 코드 작성시 현재 코드에 앞으로 요구사항이 추가될 가능성이 있는지 판단하는데 더 많은 시간을 할애하라.
- 코드 구조를 미리 확장 가능하도록 구성해두면 추후 새로운 요구사항을 추가할 때 코드의 수정을 최소화할 수 있다.