> For the complete documentation index, see [llms.txt](https://taewoongs-organization.gitbook.io/jtwjs-dev-wiki/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://taewoongs-organization.gitbook.io/jtwjs-dev-wiki/dev_note/fp/undefined-7.md).

# 계층형 설계

{% hint style="info" %}
**"어떤 코드도 이상적인 모습에 도달할 수 없다."**

설계는 개발자들 간에 생각하는 부분이 서로 다르고, 상황에 따라 좋은 설계 기준이 달라지기도 한다.

설계에 대해 이야기할 때는 서로 같은 용어를 사용하고, 상황을 고려해서 평가해야 한다.
{% endhint %}

## 계층형 설계

> 소프트웨어를 계층으로 구분하여 설계하는 방식

* 각 계층의 함수는 바로 아래 계층의 함수를 이용해 정의한다.
* **즉, 계층형 설계에서 모든 계층은 바로 아래 계층에 의존해야 한다.**
* 계층형 설계는 코드를 추상화 계층으로 구성한다. 즉, 구체화 단계에 따라 계층이 나뉨
  * 흔히 소프트웨어 레이어드 아키텍처를 보면 도메인 계층과 외부 프로세스와 도메인을 연결시키는 애플리케이션 계층이 있다. 가장 하위에 있는 계층은 구체화 수준이 높고 상위로 갈수록 구체화 수준이 낮다.
* 각 계층을 볼 때 다른 계층의 구체적인 내용을 몰라도 된다.

{% hint style="info" %}
소프트웨어 설계란, 코드의 확장성, 유지보수성, 테스트 용이성 등을 높히기 위해 미적 감각을 사용하는 것
{% endhint %}

## 계층형 설계 패턴

### 직접 구현

> 직접 구현된 함수를 읽을 때 함수 시그니처가 나타내고 있는 문제를 함수 본문에서 **적절한 구체화 수준**으로 해결해야 한다.

{% hint style="info" %}
**함수 시그니처란?**

함수의 이름과 입력값, 반환값의 타입으로 함수를 고유하게 식별할 수 있는 정보를 말한다.
{% endhint %}

* 본문이 너무 구체적이라면 코드에서 나는 악취일 가능성이 높다. (명령형)
* 직접 만든 함수와 언어에서 제공하는 기능은 추상화 수준이 다르다.
* 추상화 수준이 서로 다르다면, 흐름이 불규칙적이고 명확하지 않아 가독성을 해친다.
* **함수가 모두 비슷한 계층에 있다면 직접 구현했다고 볼 수 있다.**
* 같은 계층에 있는 함수는 같은 목적을 다뤄야 한다.

{% hint style="info" %}
사용하는 곳에서 함수가 어떤 데이터 구조인지 알아야 한다면 낮은 수준의 계층이다.\
ex:) 가장 낮은 계층 - 자바스크립트에서 제공하는 메서드(반복문, 배열 인덱스 접근 등)
{% endhint %}

{% hint style="info" %}
**한 줄 짜리 코드가 좋은 코드인가?**

코드의 라인 수는 중요하지 않고, 코드가 적절한 구체화 수준과 일반화가 되었는지가 중요하다.

일반적으로 한줄 짜리 코드는 여러 구체화 수준이 섞일 일이 없기 때문에 좋은 코드이다.
{% endhint %}

#### 직접 구현 패턴

> **직접 구현 패턴은 함수를 명확하고 아름답게 구현해 계층을 구성할 수 있도록 알려준다.**

* 함수가 더 구체적인 내용을 다루지 않도록 일반적인 함수로 추출하는 작업은 직접 구현 패턴을적용한 방법 중 하나
* 문제 해결을 위한 함수를 구현할 때 어떤 구체화 수준을 따를지에 따라 어떤 계층에 속할지 정해진다.
* 함수의 이름은 의도를 나타내며, 본문은 중요한 세부 사항을 나타내어 함수가 어떤 계층에 속해야 하는지 알려준다.

### 추상화 벽

> 추상화 벽(abstraction barrier)은 세부 구현을 감춘 함수로 이루어진 계층
>
> "**어떤 것을 신경 쓰지 않아도 되지?**"라는 말을 거창하게 표현한 개념

* 중요한 세부 구현을 감추고 인터페이스를 제공하는 식으로 코드를 만들면 높은 차원으로 생각할 수 있다.
* 고수준의 추상화 단계만 생각하면 되기 때문에 두뇌 용량의 한계를 극복할 수 있다.
* 구현 세부사항을 전혀 몰라도 함수를 사용할 수 있다.
* 계층 구조에서 어떤 계층에 있는 함수들이 공통된 개념을 신경 쓰지 않아도 된다면 그 계층을 추상화 벽이라 할 수 있다.
* 추상화 벽으로 추상화 벽 아래에 있는 코드와 위에 있는 코드의 의존성을 없앨 수 있다.
* **신경 쓰지 않아도 되는 것을 다루는 것이 추상화 벽의 핵심!**

#### 추상화 벽을 사용하면 좋은 상황

1. **쉽게 구현을 바꾸기 위해** → 뭔가 바뀔것을 알고 있지만 아직 준비되지 않은 경우 (ex: api 더미 데이터)
2. **코드를 읽고 쓰기 쉽게 하기 위해** → 알아야할 필요가 없는 세부 구현사항을 숨겨서 단순화함으로써 뇌 과부화 방지
3. **주어진 문제에 집중하기 위해** → 복잡한 세부 구현사항을 감추고 필요한 주요 기능에만 집중할 수 있게 된다.

### 작은 인터페이스

> 작은 인터페이스 패턴은 **새로운 코드를 추가할 위치**에 관한 것

* 시스템이 커질수록 비즈니스 개념을 나타내는 중요한 인터페이스는 작고 강력한 동작으로 구성하는 것이 좋다.
* `추상화 벽`에  만든 함수는 **`인터페이스`**&#xB77C;고 볼 수 있다.
* 추상화 벽에 있는 인터페이스로 어떤 값의 집합에 접근하거나 값을 조작할 수 있다.
* 작은 인터페이스 패턴은 추상화 벽 뿐만 아니라 모든 계층에 적용할 수 있는 패턴
* **새로운 기능을 만들 때 하위 계층에 기능을 추가하거나 수정하는 것보다 상위 계층에 만드는 것이 작은 인터페이스 패턴이다.**

#### 추상화 벽을 작게 만들어야 하는 이유

* 추상화 벽에 코드가 많을 수록 기능이 수정됬을 때 변경해야 하는 코드가 많아진다.
* 하위 계층에서 불필요한 기능이 쓸데없이 커지는것을 방지할 수 있다.
* 추상화 벽에 있는 코드(인터페이스)는 보통 낮은 수준의 코드이기 때문에 더 이해하기 어렵고 많은 버그가 존재할 수 있다.

{% hint style="info" %}
계층이 가진 함수는 완전하고, 적고, 시간이 지나도 바뀌지 않아야 한다. \
이것이 작은 인터페이스가 전체 계층에 사용되는 이상적인 모습이다.
{% endhint %}

### 편리한 계층

> 코드와 그 코드가 속한 추상화 계층은 작업할 때 편리해야 한다.

* 단순한 이유(그냥 좋아서)로 계층을 추가하면 안된다.
* 소프트웨어를 개발할 때 더 빠르고 고품질로 제공하는 계층에 시간을 투자해야 한다.
