> 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/system-design/clean-code.md).

# Clean Code

### 좋은 코드

* 유지보수성

### 나쁜 코드

* **반복적으로 나타나는 중복된 코드**가 악취나는 코드

### 중복 코드

* 여러 코드에 퍼져있는 반복되는 코드를 별도 모듈로 분리하여 유지보수성을 높이는게 중요&#x20;
* 함수로 분리하고 명확한 네이밍을 지어 로직을 이해하기 쉽게 만듦

### 매직 상수

* 매직 상수란 특정 값을 하드코딩한 것을 의미
* 나중가면 이게 무슨 뜻인지 알수가 없게됨
* 개선 방법
  * 숫자에 의미를 담기
  * 흩뿌려진 상수 모으기

### 이름 짓기

> 코드를 읽었을 때 그 이름대로 예측 및 유추하게 된다.\
> 예측한대로 동작하게 만드는게 좋은 이름 짓기 방법이다.

* 구체적인 이름 짓기
* 관례를 따르기, 각 언어 생테계에 따라 관례가 존재한다.
* 정보를 담기
  * 네이밍과 동작이 동일해야 한다.
* 읽는 사람 입장에서 최대한 뇌빼고 이해할수 있도록 짓는게 중요
* 컨텍스트 내에서 물흐르듯이 이해할 수 있도록 간단 명료하게 작명해야 한다.

### 오류 관련

* null 관련한 문제
* 자바의 null 문제를 언어 차원에서 방지한 것이 코틀린 언어

### 흐름 제어

* `if`문 `switch`문
* **중첩을 최소화하기**&#x20;
* 중첩이 많다는것은 많은 악취를 포함한다.
  * 너무 많은 일을 함
  * 너무 많은 조건을 갖고 있음
  * 너무 많은 상태를 알고 있음
  * 즉, 복잡하다. -> 유지보수하기 어렵다.

### 사용하지 않는 코드

* 사용되지 않는 코드는 읽는사람으로써 혼란을 야기시킴
* 사용되지 않는 코드는 남겨두지 않고 과감하게 제거하는게 필요

## 함수

* 재사용 가능한 코드 조각
* 특정 작업을 수행하는 명령어의 조합
* 입력을 받아 특정 명령을 수행하거나, 결과를 반환
* 모듈화, 재사용성, 구조화, 관리

### 함수 관련 클린코드

#### 작게 만들기

* 작아야 읽기 쉽고 수정하기 쉽다. 즉, 유지보수하기 쉬운 코드가 된다.
* 15 line 이하가 작다고 표현됨

{% hint style="info" %}
함수를 작게 만드는 방법

* 메서드 추출
* 메서드를 메서드 객체로 대체
  * 복잡한 메서드를 단순화하고 가독성을 높이기 위해 사용됨
    {% endhint %}

#### 복잡도를 낮추기

* 함수 안의 분기 개수를 작게 유지
* `if`, `switch`, `삼항연산`, `try & catch`, `for`, `&&, ||`
* 분기점이 많을수록 복잡도가 증가한다.

#### 파라미터 개수를 제한하기

* 4개 이하
* 4개를 초과하면 파라미터 객체를 고려

#### 각 함수는 하나의 일만 잘하기 (단일 책임)

* 하나의 함수 안에서 여러가지 일을 하지 말자.
* 복잡하고, 테스트가 어렵게됨

### Class

#### 단일 책임 원칙 (SRP)

* 각 클래스는 하나의 책임만 갖음
* 2개 이상의 역할을 수행하면 복잡성이 높아짐
* 더 작고, 더 응집된 클래스를 만들려고 노력

#### 의미 있는 클래스 이름 짓기

* 클래스 이름만 보고 어떤 클래스인지 알 수 있어야 함
* 명확하고 설명적인 이름
* 클래스의 목적과 책임이 들어나야 함

#### 캡슐화

* 접근 제어자 `public`, `private`, `protected`를 사용하여 클래스 멤버의 가시성을 관리

#### 생성자

* 생성자에 복잡한 논리나 작업을 피한다.
  * 복잡한 로직은 별도 메서드로 추출
* 생성자는 로직을 넣지 않는 것이 중요

#### 의존성 주입

* 클래스는 다른 클래스를 사용하여 의존성이 생기게 됨
* 의존성을 낮추는것이 복잡성을 줄인다.
* 외부에서 주입해주는 방식으로 사용해야 목 데이터로 갈아끼워 테스트하기도 쉽고 교체 방식으로 클래스의 별도 수정없이 행동을 바꿀수 있게 된다.

#### 인터페이스 활용

* 유연성이 높아지고, 다형성을 사용하기 쉬워짐

```java
interface Logger {
  void log(String message);
}

class FileLogger implements Logger {
  @Override
  public void log(String message) {
    //
  }
}
```

#### 상속을 과용하지 않고, 효과적으로 사용

* 상속 대신 조합(Composition)을 권장
* 상속을 사용하면 부모 클래스에 모두 접근 가능하기 때문에 캡슐화가 깨진다.
* 상속은 간단한 곳에서만 사용하도록!

#### '신'을 만들지 않기

* 클래스 하나에 모두 작성하지 않고 책임에 맞게 별도 클래스로 분리하는것이 중요
* 클래스와 관련된 모든 로직을 다 때려박은 클래스를 "God Class" 라 부른다.

#### 관레를 따르기

* 일관된 코딩 스타일로 작성

#### 하드코딩 피하기

* 상수나 매직 넘버를 코드에 직접 하드코딩하는 것을 피한다.
* 명명된 상수나 열거형을 사용

#### 클래스 크기를 작게 유지하기&#x20;

* 클래스와 관련 없는 것들을 별도 클래스로 분리
* 작고 응집도 높은 클래스 만들기

### 모듈

* 응집된 코드와 관련 리소스 집합

#### 단일 책임 원칙

* 하나의 책임을 갖도록 유지
* 둘 이상의 일을 수행하면 복잡도 증가

#### 모듈의 독립성

* 하나의 모듈이 다른 모듈의 내부 세부 사항에 의존하지 않도록 한다.
* 강결합으로 변경이 어려움

#### 모듈의 크기

* 작게 유지
* 응집되게 관리

#### 모듈간의 의존성

* 인터페이스와 추상화 활용
* 특정 구현부는 인터페이스 안에 숨김

#### 모듈 버전 관리

* 모듈을 외부에 배포하거나, 공유하는 경우 버전 관리 필요
* 모듈에 의존하는 프로젝트와 호환성 유지

#### 모듈의 일관성

* 각 모듈은 일관성을 유지
* 동작 방식도 유사하도록 설계 및 구현

#### 관심사를 모듈로 분리

* 각각의 관심사가 다르다면 별도 모듈로 분리
