2007년 구글 TechTalk에서 죠슈아 블로쉬가 발표한 키노트의 프레젠테이션을 간략히 요약해봤습니다.
좋은 API의 특징
- 배우기 쉽습니다 Easy to learn
- 문서가 없이도 사용하기 쉽습니다 Easy to use, even without documentation
- 잘못 사용하기 어렵습니다 Hard to misuse
- 읽기 쉽고 관리하기 쉽습니다 Easy to read and maintain code that uses it
- 요구사항을 충분히 만족합니다 Sufficiently powerful to satisfy requirements
- 확장하기 쉽습니다 Easy to extend
- 사용자에게 정말 필요합니다 Appropriate to audience
API디자인의 프로세스
1. 요구사항을 수집합니다.
2. ‘스펙-0.1′ 부터 시작합니다.
- 가능한 많은 사람들에게 스펙을 알리세요
- 스펙을 짧게 유지하면 수정하기가 쉬워집니다.
- 자신감이 생긴면 살을 붙이세요.
3. API를 빨리 그리고 자주 쓰세요
- API를 구현하기 전에 먼저 작성합니다. 폐기해야 하는 코드를 작성하는 것을 막아줍니다.
- 세밀하게 다듬기 전에 먼저 작성합니다. 폐기해야 하는 스펙을 작성하는 것을 막아줍니다.
- 지속적으로 작성해서 살을 붙입니다.
4. SPI(Service Provider Interface)를 작성하는 것도 매우 중요합니다.
- 릴리즈전에 최소 3개의 플러그인을 작성해두세요.
- Tracz는 이것을 3의 법칙이라고 부릅니다.
5. 현실적인 것들을 고려하세요.
- API디자인은 많은 제약사항이 존재합니다. 당신의 API는 모든 사람을 만족시킬수 없습니다. 그러니 불만족스러운 점에서 모든 사람이 같도록 하세요.
- 사용상의 실수를 예상하세요.
- 당신의 API가 발전해 나갈 것을 예상하세요.
일반론
1. 하나의 API는 꼭 하나의 일을 해야하고 그것을 잘 해낼 수 있어야 합니다.
- API가 하는 일은 설명하기 쉬워야 합니다.
- API 이름짓기가 어렵다면 안좋은 신호입니다.
2. API는 가능한한 작아야 하지만, 필요이상으로 작아서는 안됩니다.
- API는 요구사항을 만족해야 합니다.
- 의심이 생긴다면 내버려두는 것이 좋습니다. 당신은 언제든 추가할 수 있지만 절대 추가된 API를 제거할 수 없습니다.
- 개념적인(철학적인) 비중이 API의 양보다 더 중요합니다.
3. 구현이 API에 영향을 줘서는 안됩니다.
4. 모든 것의 접근성을 최소화 하세요.
- 모든 클래스와 멤버들은 가능하면 private으로 두세요
- 모듈의 사용, 이해, 테스트, 디버그가 독립적으로 될 수 있도록 하세요
5. 이름이 중요합니다. API는 작은 언어입니다.
- 이름이 API자신을 설명할 수 있도록 해야합니다. 약자나 속어는 피하세요
- 일관적인 이름을 사용하세요. API내에서도 일관적이어야 하며 플랫폼내에서도 일관적이어야 합니다.
- 코드는 글을 읽는 것처럼 읽혀야 합니다.
6. 문서화도 중요합니다.
- 모든 클래스, 인터페이스, 메소드, 생성자, 파라미터 예외를 문서화하세요.
7. API디자인 결정에서 퍼포먼스 문제를 생각해야 합니다.
- 잘못된 결정은 퍼포먼스의 제약을 부릅니다.
- 퍼포먼스를 높이기 위해 API를 포장하면 안됩니다. 기저 퍼포먼스 이슈는 고쳐지겠지만 두고두고 고민거리가 됩니다.
8. API디자인 결정은 퍼포먼스에 실제적이고 영구적인 영향을 끼칩니다.
- 자바에서 Component.getSize() 는 Dimension을 리턴합니다.
- Dimension은 mutable 타입입니다.
- 따라서 getSize()가 호출 될 때 마다 Dimension객체가 하나씩 생성됩니다.
- 1.2버전에서 대안이 추가되었지만 기존코드는 여전히 저렇게 작동합니다.
9. API는 플랫폼에 녹아들어야 합니다.
- 작명관례를 지키기, 쓸모 없게된 파라미터나 리턴타입을 피하기, core API와 언어에서 사용하는 패턴을 흉내내기
- API구현을 도와주는 특징들을 사용하세요. Generics, varargs, enums, default arguments
- API 함정을 이끄는 요소들을 피하세요. Finalizers, public static final arrays
클래스 디자인
1. Mutability를 최소화 하세요.
- 클래스는 특별한 이유가 없다면 immutable해야 합니다. simple, thread-safe, reusable 한 장점이 있습니다.
- 만약 mutable 하려면 상태공간이 충분히 작고 잘 정의되어 있어야 합니다.
- 좋은예. TimerTask. 나쁜예. Date, Calendar.
2.서브클래스는 is-a일때만 사용하세요.
- is-a가 아니라면 포함((composition))을 이용하세요.
- 쉬운 구현을 위해 public 클래스는 다른 public 클래스의 서브클래스가 되지 않는 것이 좋습니다.
- 좋은예. Set extends Collection. 나쁜예. Stack extends Vector
3. 상속을 전제로 디자인과 문서화를 해야합니다. 그렇지 않다면 상속을 금지하세요.
- 상속은 캡슐화를 침해합니다.
- 좋은예. AbstractSet, AbstractMap 나쁜예. J2SE라이브러리의 많은 concrete 클래스들
메소드 디자인
1. 모듈이 할 수 있는 일을 클라이언트가 하도록 하지 마세요.
- boilerplate code 를 줄일 필요가 있습니다.
2. API를 사용하다가 사용자가 크게 놀라서는 안됩니다.
3. 빨리 실패하고 빨리 에러를 보고할 수록 좋습니다.
- 컴파일타임에 보고 하는 것이 제일 좋습니다.
- 런타임에는 첫번째 잘못된 메소드가 호출 되었을 때 보고하는 것이 좋습니다.
4. 모든 데이터를 문자열 형태로 접근가능 하도록 하세요.
5. 리턴값은 예외처리를 하지 않도록 하세요.
예외 디자인
1. 예외적인 상태를 가리키기 위해 예외를 던지세요.
- 프로그램 흐름 제어를 위해서 예외를 사용해서는 안됩니다.
- 그리고 예외를 조용히 덮어서도 안됩니다.
2. Unchecked 예외를 즐겨 사용하세요.
- Checked – 클라이언트가 복구를 위한 행위를 해야하는 예외
- Unchecked – 프로그래밍 에러
- checked 예외를 남발하면 boilerplate를 유발합니다.
3. 실패정보를 예외에 포함시키세요.
- 진단과 복구를 할 수 있도록 해야합니다.
- Checked 예외는 접근자를 제공하고,
- Unchecked 예외는 메시지에 포함하세요.
결론
1. API디자인은 고귀하고 할만한 가치가 있는 작업입니다.
2. 지금까지 이야기 한 내용은 가능하면 지키도록 하세요
3. API디자인은 터프합니다.
- 고립된 행위가 아닙니다.
- 완벽은 이룰수 없습니다. 그러나 계속 추구해야하는 바입니다.