07
4
2010

좋은 API를 만드는 법 – How to Design a Good API and Why it Matters

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′ 부터 시작합니다.

  • 가능한 많은 사람들에게 스펙을 알리세요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에 영향을 줘서는 안됩니다.

  • 구현 내용이 API에 드러나서는 안됩니다.

4. 모든 것의 접근성을 최소화 하세요.

  • 모든 클래스와 멤버들은 가능하면 private으로 두세요
  • 모듈의 사용, 이해, 테스트, 디버그가 독립적으로 될 수 있도록 하세요

5. 이름이 중요합니다. API는 작은 언어입니다.

  • 이름이 API자신을 설명할 수 있도록 해야합니다. 약자나 속어는 피하세요
  • 일관적인 이름을 사용하세요. API내에서도 일관적이어야 하며 플랫폼내에서도 일관적이어야 합니다.
  • 코드는 글을 읽는 것처럼 읽혀야 합니다.2

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 를 줄일 필요가 있습니다.3

2. API를 사용하다가 사용자가 크게 놀라서는 안됩니다.

3. 빨리 실패하고 빨리 에러를 보고할 수록 좋습니다.

  • 컴파일타임에 보고 하는 것이 제일 좋습니다.
  • 런타임에는 첫번째 잘못된 메소드가 호출 되었을 때 보고하는 것이 좋습니다.

4. 모든 데이터를 문자열 형태로 접근가능 하도록 하세요.

5. 리턴값은 예외처리를 하지 않도록 하세요.

예외 디자인

1. 예외적인 상태를 가리키기 위해 예외를 던지세요.

  • 프로그램 흐름 제어를 위해서 예외를 사용해서는 안됩니다.
  • 그리고 예외를 조용히 덮어서도 안됩니다.

2. Unchecked 예외를 즐겨 사용하세요.

  • Checked – 클라이언트가 복구를 위한 행위를 해야하는 예외
  • Unchecked – 프로그래밍 에러
  • checked 예외를 남발하면 boilerplate를 유발합니다.

3. 실패정보를 예외에 포함시키세요.

  • 진단과 복구를 할 수 있도록 해야합니다.
  • Checked 예외는 접근자를 제공하고,
  • Unchecked 예외는 메시지에 포함하세요.

결론

1. API디자인은 고귀하고 할만한 가치가 있는 작업입니다.

2. 지금까지 이야기 한 내용은 가능하면 지키도록 하세요

3. API디자인은 터프합니다.

  • 고립된 행위가 아닙니다.
  • 완벽은 이룰수 없습니다. 그러나 계속 추구해야하는 바입니다.
  1. bounce sth out sb – 알리다 []
  2. 시가 아니라 산문 []
  3. boilerplate code : copy & paste된 코드 조각 []