티스토리 뷰

API 설계 요령들을 알아보자.

메서드 이름을 신중히 짓자.

  • 항상 표준 명명 규칙 (Item68)을 따르자.
  • 이해할 수 있고, 같은 패키지에 속한 다른 이름들과 일관되게 짓는게 우선 목표다.
  • 개발자 커뮤니티에서 널리 받아들여지는 이름을 사용하자.
  • 긴 이름은 피하자.
  • 자바 라이브러리의 API 가이드를 참조하자.

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

  • 모든 메서드는 각각 자신의 소임을 다해야 한다.
  • 메서드가 너무 많은 클래스는 익히고, 사용하고, 문서화하고, 테스트하고, 유지보수하기 어렵다.
  • 아주 자주 쓰일 경우에만 별도의 약칭 메서드를 두자.
  • 확신이 서지 않으면 만들지 말자.

매개변수 목록은 짧게 유지하자.

  • 4개 이하로 만들자.
  • 같은 타입 매개변수 여러 개가 연달아 나오는 경우는 특히 해롭다.

매개변수 목록을 짧게 줄여주는 기술

  • 여러 메서드로 쪼개기
    • 잘못하면 메서드가 너무 많아질 수 있지만, 직교성 (orthogonality)을 높여 오히려 메서드 수를 줄여주는 효과가 있다. ex) java.util.List
  • 매개변수 여러 개를 묶어주는 도우미 클래스 만들기
    • 일반적으로 이런 도우미 클래스는 정적 멤버 클래스로 둔다.
    • 특히, 매개변수 몇 개를 독립된 하나의 개념으로 볼 수 있을때 추천하는 기법이다.
  • 객체 생성에 사용한 빌더 패턴을 메서드 호출에 응용하기
    • 매개변수가 많을 때, 특히 그중 일부는 생략해도 괜찮을때 도움이 된다.
// BAD. 매개변수 4개이상, sex를 boolean으로 사용
void method1(String firstName, String lastName, boolean sex, int age) { }

enum Sex {
    Woman,
    Man
}

@Builder
static private class Person {
  String firstName;
  String lastName;
  Sex sex;
  int age;
}

// GOOD. 도우미 클래스 사용, boolean 대신 Enum 사용, 매개변수 1개로 줄임 
void method2(Person person) {}

// GOOD. 빌더패턴 사용 
public static void main(String[] args) {
  Item51 item51 = new Item51();
  item51.method2(
    Person.builder()
    .age(20)
    .firstName("subin")
    .lastName("king")
    .sex(Sex.Man)
    .build()
  );
}
  • 직교: 서로 직각을 이루며 교차한다는 뜻. 수학의 관점에서는 직교하는 요소들은 서로 독립적이다.

이 개념을 SW 설계 영역으로 가져오면 "직교성이 높다" 라고 하면 "공통점이 없는 기능들이 잘 분리되어 있다" 혹은 "기능을 원자적으로 쪼개 제공한다" 정도로 해석할 수 있다.

매개변수의 타입으로는 클래스보다는 인터페이스가 더 낫다. (Item64)

매개변수로 적합한 인터페이스가 있다면 그 인터페이스를 직접 사용하자.

// BAD
void method3(HashMap<String, Integer> hashMap) {}

// GOOD
void method4(Map<String, Integer> map) {}

클래스가 아니라 인터페이스를 받으면 나중에 HashMap 이 아니라 TreeMap, ConcurrentHashMap 등 어떤 Map 구현체로도 인수를 건넬 수 있다.

심지어 아직 존재하지 않는 Map도 가능하다.

클래스를 사용하면 클라이언트에게 특정 구현체만 사용하도록 제한하는 꼴이며, 혹시라도 입력 데이터가 다른 형태로 존재한다면 명시한 특정 구현체의 객체로 옮겨 담느라 비싼 복사 비용을 치러야 한다.

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

  • 메서드 이름상 boolean 을 받아야 의미가 명확할 때는 예외다.
  • 열거 타입 사용하면 코드 읽고 쓰기가 더 쉽고 추가하기도 쉽다.
enum TemperatureScale {
  FAHRENHEIT,
  CELSIUS
}

FAHRENHEIT: true, CELSIUS: false 로 지정하는것 보다 enum이 훨씬 명확하다.

또한 나중에 다른 온도 단위를 추가한다면 리팩터링하기 편하다.