API 핵심 설계 요령들을 몇가지 알아보도록 하자.
표준 명명 규칙(아이템 68)을 따라야 한다.
먼저 이해할 수 있고 같은 패키지에 속한 다른 이름들과 일관되게 지어야 하며, 그 다음으로 개발자 커뮤니티에서 널리 받아들여지는 이름을 사용하자. 참고로 너무 긴 이름은 피하는 것이 좋다.
메서드가 너무 많은 클래스와 인터페이스는 익히고, 사용하고, 문서화하고, 테스트하고, 유지보수하기가 어렵다. 따라서 클래스나 인터페이스는 자신의 각 기능을 완벽히 수행하는 메서드로만 제공하고, 확신히 서지 않는다면 만들지 말자.
4개 이하가 적정이며, 그 이상은 매개변수들을 기억하기가 쉽지 않아진다. 특히나 같은 타입의 매개변수 여러 개가 연달아 나오는 경우는 특히나 안좋다.
📌 긴 매개변수 목록을 짧게 줄여주는 기술
1.여러 메서드로 분리
여러 메서드로 쪼갠 후, 쪼개진 메서드 각각은 원래 매개변수 목록의 부분집합을 받으면 된다. 메서드가 많아질 수 있지만, 직교성을 높여 메서드 수를 줄여주는 효과도 있기 때문에 괜찮다.
🔖 직교성을 높여 메서드 수를 줄여주는 효과?
직교성이란 "공통점이 없는 기능들이 잘 분리되어 있다" 정도로 해석 할 수 있다. 즉 기능을 원자적으로 쪼개다 보면, 기본 기능만 가지고도 여러 복잡하 기능들을 조합해낼 수 있기 때문에 불필요한 메서드를 만들지 않아도 된다.
java.util.List
인터페이스를 예시로 들어보자.
지정된 범위의 부분리스트에서 주어진 원소의 인덱스를 찾아야 한다고 가정하면, 총 매개변수 3개가 필요할 것이다.(부분리스트 시작/끝/찾을 원소)
하지만 List는 대신 부분리스트를 반환하는 subList()
메서드와 주어진 원소의 인덱스를 알려주는 indexOf()
메서드를 별개로 제공하고 있어서, 메서드를 여러개로 쪼갠 것을 알 수 있다.
2.여러개를 묶어주는 도우미 클래스 생성
일반적으로 도우미 클래스는 정적 멤버 클래스(아이템 24)로 둔다. 특히 잇따른 매개변수 몇 개를 독립된 하나의 개념으로 볼 수 있을때 추천하는 방법이다.
예를 들어, 카드게임을 클래스로 만들때 카드의 숫자와 무늬를 뜻하는 두 개개변수를 도우미 클래스로 만들어 하나의 매개변수로 주고받을 수 있다.
3.객체 생성에 사용한 빌더 패턴을 메서드 호출에 응용
앞서 두 방식을 혼합한 것으로, 이 기법은 매개변수가 많으며 그 중 일부는 생략해도 괜찮을 때 사용하면 좋다.
먼저 모든 매개변수를 하나로 추상화한 객체를 정의하고, 클라이언트에서 이 객체의 세터 메서드를 호출해 필요한 값을 설정하게 한다. 다음 execute 메서드를 호출해 앞서 설정한 매개변수들의 유효성을 검사하고, 설정이 완료된 객체를 넘겨 원하는 계산을 수행하면 된다.
매개변수로 적합한 인터페이스가 있다면, 구현한 클래스가 아닌 인터페이스를 직접 사용하는 것이 좋다. 클래스를 사용하면 클라이언트에게 특정 구현체만 사용하도록 제한하는 것이 되기 때문이다.
예를 들어 인자로 Map을 넘긴다면, HashMap뿐만 아니라 TreeMap, ConcurrentHashMap, TreeMap의 부분맵 등 어떤 Map 구현체도 인수로 건넬 수 있다.
메서드 이름상 boolean을 받아야 의미가 더 명확할 때를 제외하고, 열거 타입을 사용하면 코드를 읽고 쓰기가 더 쉬워지며 나중에 선택지를 추가할 때도 좋다.
예를 들어 화씨온도와 섭씨온도를 원소로 정의한 열거 타입을 보자.
public enum TemperatureSacle { FAHRENHEIT, CELSIUS }
Thermometer.newInstance(true)
보다는 Thermometer.newInstance(TemperatureScale.CELSIUS)
가 하는 일을 명확히 알려주며, 이후에 종류가 늘어나면 정적 메서드를 추가할 필요 없이 열거 타입에만 추가해주면 된다.