# 디자인 패턴의 아름다움

* 코드가 진짜 문제가 되는 부분을 디자인 패턴이나 설계 원칙을 통해 개선해야 한다. 이전에 봤던 어떤 적용 시나리오와 유사하다고 해서 적합성을 판단하지 않고 마구 적용하면 안된다.<br>
* 디자인 패턴을 적용하는 목적은 단일 책임을 위해 큰 코드 조각을 작은 클래스로 분할하여 코드가 높은 응집도와 낮은 결합도를 갖게 하는 것이다. 코드가 복잡하지 않으면 복잡한 디자인 패턴을 도입할 필요가 없다.<br>
* 디자인 패턴을 적용하면 확장성은 향상되지만 가독성은 나빠질 수 있다. 또한 팀 전체가 복잡한 설계에 따른 작업을 항상 수행해야 한다. 잘못된 예측으로 인한 과도한 설계를 피하기 위해 지속적인 리팩터링을 해야 한다.<br>
* 객체 지향 설계 프로세스
  * 책임과 기능을 나누고, 어떤 클래스가 있는지 확인한다
  * 클래스를 정의하고, 클래스의 속성과 메서드를 정의한다
  * 클래스 간의 상호 작용을 정의한다
  * 클래스를 연결하고 실행 엔트리 포인트를 제공한다<br>
* 소프트웨어 개발은 지속적인 반복, 패치, 문제 발견, 문제 해결의 과정이며, 지속적인 리팩터링의 과정이다. 엄격하게 하나의 단계를 모두 마치고 다음 단계로 넘어가는 것은 불가능하다.<br>
* getter와 setter 메서드를 남용하면 캡슐화를 위반하는 것이다. getter도 레퍼런스를 반환하게 된다면 주의해야 한다.<br>
* 크고 포괄적인 전역 상수 혹은 메서드 클래스를 정의하는 것은 좋은 설계라 할 수 없다. 만들어야 한다면 기능에 따라 쪼개라.
  * 코드의 유지 보수성에 영향을 미친다. 개발 과정에서 해당 클래스가 점점 커질 수 있고, 노동 집약적 코드 확인도 늘어난다.
  * 코드의 컴파일 시간을 증가시킨다. 해당 클래스에 종속된 다른 클래스가 매번 다시 컴파일된다.
  * 코드의 재사용 가능성에도 영향을 미친다. 해당 프로젝트에서 개발한 클래스를 다른 프로젝트에서 재사용하려고 할 때, 그 클래스가 상수 클래스에 종속돼있으면 불필요하게 상수 클래스까지 가져와야 한다.<br>
* 추상 클래스를 사용하면 설계 의도를 쉽게 드러낼 수 있고, 구현하는 것을 깜빡하지 않을 수 있고, 부모 클래스의 메서드와의 오용 가능성도 사라진다.<br>
* is-a 관계를 나타내려 하고, 코드 재사용 문제를 해결하려면 추상 클래스를 사용한다
* has-a 관계를 나타내려 하고, 추상화 문제를 해결하려면 인터페이스를 사용한다.<br>
* 언어에서 인터페이스 제공 안 할수도 있는데, override 안 하면 exception 일어나도록 하고, 생성자를 protected 속성으로 설정하는 등 제약을 가하면 된다.<br>
* 인터페이스를 남용하면 사방에 펼쳐진 인터페이스가 개발에 불필요한 부담이 될 것이다.
* 불안정한 구현을 캡슐화하고 안정적인 인터페이스를 노출하겠다는 설계 사상의 원래 의도를 잘 파악하고 해당될 때만 적용하면 된다.
* 특정 기능에 대한 구현 방법이 하나이고, 이후에도 다른 구현 방법으로 대체할 일이 없다면 인터페이스를 정의할 필요 없다.
* 함수는 그 자체로 구현 세부 사항을 캡슐화한 추상화이다. 따라서 함수의 정의가 충분히 추상적이면 인터페이스 없어도 추상화 만족한다.<br>
* 상속을 잘못 사용하면 예외 사례에 의해 복잡성이 증가한다. 이때는 인터페이스를 정의하고 구현 클래스를 만든 다음 composition이나 delegation하면 된다.<br>
* 클래스와 인터페이스의 수는 코드의 복잡성과 유지 관리 비용을 증가시킨다.
* 클래스 간의 상속 구조가 안정적이어서 쉽게 변경되지 않고 상속 단계가 2단계 이하로 비교적 얕아 복잡하지 않다면 과감하게 상속을 사용할 수 있다.
* 반대로 시스템이 불안정하고 상속 계층이 깊고 상속 관계가 복잡하면 상속 대신 합성을 사용해라.<br>
* 동일한 클래스라 할지라도 다른 비즈니스 시나리오나 요구사항에 따라 클래스의 책임이 단일한지 아닌지를 판단하는 것이 다를 수 있다.
* 단일 책임 여부를 결정하기 위해 사용되는 결정 원칙
  * 클래스에 코드, 함수, 속성이 너무 많아 코드의 가독성과 유지 보수성에 영향을 미치고 있다면 클래스 분할 고려
  * 클래스가 다른 클래스에 과하게 의존하고 있다면 클래스 분할 고려
  * 클래스에 private 메서드가 너무 많을 때 클래스 분리하고 puiblic 메서드 설정하여 코드 재사용성 향상시켜야 한다
  * 클래스 이름을 비즈니스적으로 정확히 정의하기 어렵거나 Manager, Context처럼 일반적인 단어가 아니면 클래스의 이름을 정의하기 어려울 경우, 클래스 책임 정의가 충분히 명확하지 않음을 의미할 수 있다.
  * 클래스의 많은 메서드가 여러 속성 중 일부에서만 작동하는 경우 분할 고려


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://lazyartisan.gitbook.io/note/main-page/books/undefined-5.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
