Skip to content

Commit

Permalink
docs : 최준 이펙티브 자바 item 51 정리본 추가 (#108)
Browse files Browse the repository at this point in the history
  • Loading branch information
CJ-1998 authored Jul 28, 2024
1 parent 142ad0f commit 7ab3bf2
Show file tree
Hide file tree
Showing 2 changed files with 284 additions and 0 deletions.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
# 5️⃣1️⃣ Item 51 : 메서드 시그니처를 신중히 설계하라

<br>

## 📌 목차
1. API 설계 요령
2. 1.메서드 이름을 신중히 짓자.
3. 2.편의 메서드를 너무 많이 만들지 말자.
4. 3.매개변수 목록은 짧게 유지하자.
5. 매개변수 목록 줄이는 기술
6. 4.매개변수 타입으로는 클래스보다는 인터페이스가 더 낫다.
7. 5.boolean보다는 원소 2개짜리 열거 타입이 낫다.
8. 결론

<br>

## 🏗 API 설계 요령

`API 설계 요령`들을 보자.

이 요령들을 잘 활용하면 아래와 같은 `장점`들을 얻을 수 있다.

- `배우기 쉬운` API 만들 수 있다.
- `쓰기 쉬운` API 만들 수 있다.
- `오류 가능성이 적은` API 만들 수 있다.

<br>

## 1️⃣ 1. 메서드 이름을 신중히 짓자.

첫번째 API 설계 요령은 `‘메서드 이름을 신중히 짓자’`이다.

<br>

메서드 이름을 지을 때에는 아래를 참고해서 해야 한다.

1. 항상 `표준 명명 규칙`을 따라야 한다.
2. `이해할 수 있는` 메서드 이름을 지어야 한다.
3. 같은 패키지에 속한 다른 이름들과 `일관되게` 지어야 한다.
4. `개발자 커뮤니티`에서 널리 받아들여지는 이름 사용해야 한다.
5. `긴 메서드 이름`은 피해야 한다.
6. 애매하면 `자바 라이브러리의 API 가이드` 참조해 지어야 한다.

<br>

## 2️⃣ 2. 편의 메서드를 너무 많이 만들지 말자.

두번째 API 설계 요령은 `‘편의 메서드를 너무 많이 만들지 말자’`이다.

<br>

편의 메서드는 `자주 사용되는 기능 or 반복되는 코드 블록 모듈화 해 재사용 가능하게 만든 메서드`다.

편의 메서드는 다음과 같은 `장점`이 있다.

1. 코드의 `재사용성`을 높인다.
2. 코드의 `가독성을 향상`시킨다.
3. `버그 발생 확률을 줄이는 데` 도움이 된다.

<br>

하지만 `메서드가 너무 많은` 클래스, 인터페이스는 다음과 같은 문제점이 있다.

1. `익히기` 어렵다.
2. `사용하기` 어렵다.
3. `문서화하기` 어렵다.
4. `테스트하기` 어렵다.
5. `유지보수하기` 어렵다.
6. 구현하는 사람, 사용하는 사람 `모두 어렵게 한다`.

<br>

따라서 클래스나 인터페이스는 자신의 `각 기능을 완벽히 수행`하는 메서드로 제공해야 한다.

아주 `자주 쓰이는 메서드의 경우`에만 별도의 약칭 메서드로 두자.

<br>

## 3️⃣ 3. 매개변수 목록은 짧게 유지하자.

세번쨰 API 설계 요령은 `‘매개변수 목록은 짧게 유지하자’`이다.

<br>

매개변수는 `4개 이하가 좋다`고 한다.

5개부터는 매개변수를 `전부 기억하기 쉽지 않다`.

<br>

매개변수가 많은 메서드가 많으면 아래와 같은 `문제`가 생긴다.

1. `API 문서를 가지고 보면서` 개발해야 한다.
2. `IDE를 사용하면 수고를 덜 수 있지만` 여전히 쉽지 않다.

<br>

`같은 타입의 매개변수 여러 개` 연달아 나오는 경우 더 문제가 많아진다.

1. 사용자가 매개변수 `순서를 기억하기 어렵다`.
2. 실수로 순서 바꿔 입력해도 그대로 컴파일되고 `실행되어 의도와 다르게 동작`한다.

<br>

### 🔨 매개변수 목록 줄이는 기술

긴 매개변수 목록을 짧게 줄여주는 기술 `3가지`를 보자.

<br>

**첫번째 기술**

첫번째 기술은 `여러 메서드로 쪼개는 것`이다.

하나의 매개변수 목록을 여러 메서드로 나누는 것이다.

이렇게 하면 메서드가 너무 많아질 것 같다.

<br>

그러나 이렇게 메서드를 나누면 `직교성이 높아진다`.

직교성이 높아진다 = `공통점 없는 기능들이 잘 분리`되어 오히려 메서드 수를 줄여주는 효과가 있다.

API는 기본 기능만 잘 갖춰 놓으면 아무리 `복잡한 기능도 조합`할 수 있다.

그래서 공통점 없이 기능들을 잘 분리해 놓으면 `자연스럽게 중복이 줄고 결합성이 낮아진다`.

이렇게 하면 코드를 수정하거나 테스트하기 쉬워진다.

그래서 직교성이 높은 설계는 가볍고 구현하기 쉽고 유연하고 강력하다고 한다.

<br>

**두번째 기술**

두번째 기술은 `매개변수 여러 개를 묶어주는 도우미 클래스`를 만드는 것이다.

이런 도우미 클래스는 일반적으로 `정적 멤버 클래스`로 둔다.

`매개변수 몇 개를 독립된 하나의 개념`으로 볼 수 있을 때 추천하는 기법이다.

<br>

아래와 같은 순서로 진행하는 것이다.

1. 매개변수를 묶는 도우미 클래스를 만든다.
2. 메서드의 매개변수를 이 하나의 도우미 클래스로 주고 받는다.
3. API, 클래스 내부 구현이 깔끔해진다.

<br>

```java
public class CardGame{
public void game(int rank, String suit){
~~
}
}

->

public class CardGame{
public static class CardType{
private int rank;
private String suit;
...
}

public void game(CardGame cardGame){
~~
}
}
```

<br>

**세번째 기술**

세번째 기술은 객체 생성에 사용한 `빌더 패턴을 메서드 호출에 응용`하는 것이다.

앞의 두 기술을 혼합한 것이다.

이 기술은 매개변수가 많은데 `그중 일부는 생략해도 괜찮을 때` 도움이 된다.

<br>

이것은 다음과 같은 순서를 따라 진행하면 된다.

1. 모든 매개변수를 하나로 `추상화한 객체를 정의`한다.
2. 이 객체에 각 매개변수 하나 or 연관된 몇 개에 관한 `setter 메서드를 정의`한다.
3. 클라이언트는 객체의 setter 메서드로 필요한 `매개변수를 설정`한다.
4. execute 메서드를 호출해 설정한 `매개변수들의 유효성을 검사`한다.
5. `객체를 메서드로` 넘긴다.

<br>

따라서 매개변수 목록 줄이는 기술을 정리하면 아래와 같다.

1. 여러 메서드로 쪼개자.
2. 매개변수 여러 개를 묶어주는 도우미 클래스를 만들자.
3. 객체 생성에 사용한 빌더 패턴을 메서드 호출에 응용하자.

<br>

## 4️⃣ 4. 매개변수 타입으로는 클래스보다는 인터페이스가 더 낫다.

네번째 API 설계 요령은 `‘매개변수 타입으로는 클래스보다는 인터페이스가 더 낫다’` 이다.

<br>

매개변수 타입을 인터페이스로 하는 이유는 아래와 같다.

1. `어떤 인터페이스의 구현체도` 파라미터로 건넬 수 있다.
2. `아직 존재하지 않는 구현체도` 파라미터로 건넬 수 있다.

<br>

인터페이스 대신 클래스를 사용하면 아래와 같은 `단점`이 있다.

1. 클라이언트에게 `특정 구현체만 사용하도록 제한`하게 된다.
2. 입력 데이터가 다른 형태로 존재하면 특정 구현체 객체로 옮겨 담느라 `비싼 복사 비용 생긴다`.

<br>

## 5️⃣ 5. boolean보다는 원소 2개짜리 열거 타입이 낫다.

다섯번째 API 설계 요령은 `‘boolean보다는 원소 2개짜리 열거 타입이 낫다’` 이다.

<br>

열거 타입을 사용하면 `장점`은 아래와 같다.

1. 코드를 `읽고 쓰기가 더 쉬워진다`.
2. 하는 일을 훨씬 `명확히 알려준다`.
3. 나중에 `선택지를 추가하기도 쉽다`.
4. 새로운 타입을 지원해야 한다면 다른 정적 메서드 추가할 필요 없이 `열거 타입에 추가`하면 된다.
5. 의존성을 개별 `열거 타입 상수의 메서드 안으로 리팩터링해 넣을 수도 있다`.

<br>

예시로 Thermometer라는 온도계 클래스를 보자.

온도계 클래스의 정적 팩터리 메서드가 있는데 `섭씨 온도와 화씨 온도를 구분하기 위해 매개변수로 true, false`를 넘기는 것이다.

```java
Thermometer.newInstance(true); -> 섭씨
Thermometer.newInstance(false); -> 화씨
```

<br>

이렇게 사용하는 것보다는 열거 타입을 만들어 사용하는 것이 좋다는 것이다.

이렇게 하면 `코드를 읽고 쓰고 더 쉬워지고 하는 일이 더 명확히 보인다`.

```java
public enum TemperatureScale{ FAHRENHEIT, CELSIUS }

Thermometer.newInstance(TemperatureSclae.CELSIUS); -> 섭씨
Thermometer.newInstance(TemperatureSclae.FAHRENHEIT); -> 화씨
```

<br>

나중에 켈빈 온도를 지원해야 한다면 Thermometer 클래스에 정적 메서드 추가할 필요 없이 `열거 타입에 추가하면 된다`.

`선택지를 추가하는데 더 쉬워진 것이다`.

```java
Thermometer.newKelvinInstance(); (X)
public enum TemperatureScale{ FAHRENHEIT, CELSIUS, KELVIN } (O)
```

<br>

## ‼ 결론

API 설계 요령 `5가지`를 정리하면 아래와 같다.

1. 메서드 이름을 신중히 짓자.
2. 편의 메서드를 너무 많이 만들지 말자.
3. 매개변수 목록은 짧게 유지하자.
4. 매개변수 타입으로는 클래스보다는 인터페이스가 더 낫다.
5. boolean보다는 원소 2개짜리 열거 타입이 낫다.

0 comments on commit 7ab3bf2

Please sign in to comment.