@literal
, @code
@implSpec
, @index
@index
📌 문서화 주석을 제대로 작성하지 않으면?
- 문서화 주석이 없다면 Javadoc도 그저 공개 API 요소들의 선언만 나열해주는 것이 전부임!
- 문서가 잘 갖춰지지 않은 API는 쓰기 헷갈려서 오류의 원인이 되기 쉬움
해당 메서드와 클라이언트 사이의 규약을 명료하게 기술하기
상속용으로 설계된 클래스의 메서드가 아니라면, 무엇을 하는지를 기술하기 - how (x), what (o)
메서드의 계약(contract)를 완벽히 기술하려면,
@param
태그@return
태그@throws
태그 (검사 예외, 비검사 예외 모두)📌 참고!
만약 여러분이 따르는 코딩 표준에서 허락한다면 @return 태그의 설명이 메서드 설명과 같을 때에는 @return 태그 생략 가능
전제조건(precondition)
@throws
태그 : 비검사 예외를 선언하여 암시적으로 기술함. 비검사예외 하나가 전제조건 하나와 연결됨!@param
태그 : 그 조건에 영향받는 매개변수에 기술함사후조건(postcondition)
부작용
/**
* 이 리스트에서 지정한 위치의 원소를 반환한다.
*
* <p>이 메서드는 상수 시간에 수행됨올 보장하지 <i>않는다</i>. 구현에 따라
* 원소의 위치에 비례해 시간이 걸릴 수도 있다.
*
* @param index 반환할 원소의 인덱스; 0 이상이고 리스트 크기보다 작아야 한다.
* @return 이 리스트에서 지정한 위치의 원소
* @throws IndexOutOfBoundsException index가 범위를 벗어나면,
* 즉, ({@code index < 0 || index >= this.size()}》이면 발생한다.
*/
E get(int index);
(영어 버전)
/**
* Returns the element at the specified position in this list.
*
* <p>This method is <i>not</i> guaranteed to run in constant
* time. In some implementations it may run in time proportional
* to the element position.
*
* @param index index of element to return; must be
* non-negative and less than the size of this list
* @return the element at the specified position in this list
* @throws IndexOutOfBoundsException if the index is out of range
* ({@code index < 0 || index >= this.size()})
*/
E get(int index);
💬 Javadoc 유틸리티는 문서화 주석을 HTML로 변환함
- 문서화 주석에 HTML 태그를 사용 -
<p>
,<i>
- HTML 표(table)까지 집어넣는 프로그래머도 있음
@param
@return
@throws
{@code} 태그
📌 여러 줄로 코드 예시를 넣으려면?
{@code}
태그를 다시<pre>
태그로
감싸면 됨 (<pre>
{@code ... 코드 ... }
</pre>
형태)- 단,
@
기호에는 무조건 탈출문자를 붙여야 하니 문서화 주석 안의 코드에서 애너테이션을 사용한다면 주의!
this
/**
* 이 컬렉션이 비었다면 true를 반환한다.
*
* @implSpec
* 이 구현은 {@code this.sizeO = 0}의 결과를 반환한다.
*
* @return o| 컬렉션이 비었다면 true, 그렇지 않으면 false
*/
public boolean isEmpty() { ... }
(원어 버전)
/**
* Returns true if this collection is empty.
*
* @implSpec
* This implementation returns {@code this.size() = 0}.
*
* @return true if this collection is empty
*/
public boolean isEmpty() { ... }
@impleSpec
💬 impleSpec이 독특한 케이스!
일반적인 문서화 주석은 해당 메서드와 클라이언트 사이의 계약을 설명함
💬
@impleSpec
활용 방법
자바 11까지도 자바독 명령줄에서 -tag "implSpec:a:Implementation Requirements:" 스위치를 켜주지 않으면@implSpec
태그를 무시해버린다. 다음 버전에
서는 기본값으로 적용되길 기대해본다.
특별한 처리가 필요함!
{@literal}
{@code}
태그와 비슷하지만, 코드 폰트로 렌더링하지는 않음* {@literal |r| < 1}이면 기하 수열이 수렴한다.
{@literal}
로 감싸도 결과는 같지만, 그러면 코드에서의 가독성이 떨어짐💡 원칙
- 문서화 주석은 코드에서건 변환된 API 문서에서건 읽기 쉬워야 한다!
- 단, 양쪽을 만족하지 못하겠다면 API문서에서의 가독성을 우선시!
/**
* 이 리스트에서 지정한 위치의 원소를 반환한다.
*
* <p>이 메서드는 상수 시간에 수행됨올 보장하지 <i>않는다</i>. 구현에 따라
* 원소의 위치에 비례해 시간이 걸릴 수도 있다.
*
* @param index 반환할 원소의 인덱스; 0 이상이고 리스트 크기보다 작아야 한다.
* @return 이 리스트에서 지정한 위치의 원소
* @throws IndexOutOfBoundsException index가 범위를 벗어나면,
* 즉, ({@code index < 0 || index >= this.size()}》이면 발생한다.
*/
E get(int index);
해당 요소의 요약 설명
마침표(.
) 주의하기!
첫 번째 마침표가 나오는 부분까지만 요약 설명이 됨
* 머스터드 대령이나 Mrs. 피콕 같은 용의자.
📌 요약 설명이 끝나는 판단 기준
- {<마침표><공백><다음 문장 시작>} 패턴의<마침표>
<다음 문장 시작>
은 ‘소문자가 아닌’문자- 예시에서는 “Mrs.” 다음에 공백이 나오고 다음 단어인 ‘피’가 소문자가 아니므로 요약 설명이 끝났다고 판단한 것!
가장 좋은 해결책은 의도치 않은 마침표를 포함한 텍스트를 {@literal}
로 감싸주는 것
/**
* 머스타드 대령이나 {@literal Mrs. 피콕} 같은 용의자.
*/
💡 Tip
- 자바 10부터는
{@summary}
라는 요약 설명 전용 태그가 추가되어, 다음처럼 한결 깔끔하게 처리할 수 있다./** * {@summary 머스타드 대령이나 Mrs. 피콕 같은 용의자.} */ public enum Suspect { ... }
주석 작성 규약에 따르면, 요약 설명은 완전한 문장이 되는 경우가 드뭄(즉, 주어가 없을 때가 많음)
ArrayList(int initialcapacity)
: Constructs an empty list with the specified initial capacity.Collection.size()
: Returns the number of elements in this collection.Instant
: 타임라인상의 특정 순간(지점)Math.PI
: 원주율(pi)에 가장 가까운 double 값* 이 메서드는 {@index IEEE 754} 표준을 준수한다.
제네릭 타입이나 제네릭 메서드를 문서화할 때는 모든 타입 매개변수에 주석을 달아야 한다.
/**
* 키와 값을 매핑하는 객체. 맵은 키를 중복해서 가질 수 없다.
* 즉,키 하나가 가리킬 수 있는 값은 최대 1개다.
*
* (나머지 설명은 생략》
*
* @param <K> 이 맵이 관리하는 키의 타입
* Qparam <V> 매핑된 값의 타입
*/
public interface Map<K, V> { ... }
열거 타입을 문서화할 때는 상수들에도 주석을 달아야 한다. 열거 타입 자체와 그 열거 타입의 public 메서드도 물론이다. 설명이 짧다면 주석 전체를 한 문장으로 써도 된다.
/**
* 심포니 오케스트라의 악기 세션.
*/
public enum Orchestrasection {
/** 폴루트,클라리넷, 오보 같은 목관악기. */
WOODWIND,
/** 프렌치 호른,트럼펫 같은 금관악기. */
BRASS,
/** 탐파니, 심벌즈 같은 타악기. */
PERCUSSION,
/** 바이울린,젤로 같은 현악기. */
STRING;
}
애너테이션 타입을 문서화할 때는 멤버들에도 모두 주석을 달아야 한다. 애너테이션 타입 자체도 물론이다.
/**
* 이 애너테이션이 달린 메서드는 명시한 예외를 던져야만 성공하는
* 테스트 메서드임을 나타낸다.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ExceptionTest {
/**
* 이 애너테이션을 단 테스트 메서드가 성공하려면 던져야 하는 예외.
* (이 클래스의 하위 타입 예외는 모두 허용된다.》
*/
Class<? extends Throwable> valueO;
}
API 문서화에서 자주 누락되는 설명이 두 가지 있으니,바로 스레드 안전성과 직렬화 가능성이다.
클래스 혹은 정적 메서드가 스레드 안전하든 그렇지 않든, 스레드 안전 수준을 반드시 API 설명에 포함해야 한다.
직렬화할 수 있는 클래스라면 직렬화 형태도 API 설명에 기술해야 한다.
자바독은 메서드 주석을 ‘상속’시킬 수 있다.
{@inheritDoc}
태그를 사용해 상위 타입의 문서화 주석 일부를 상속할 수 있다. 클래스는 자신이 구현한 인터페이스의 문서화 주석을 (복사해 붙여넣지 않고) 재사용할 수 있다는 뜻이다. 이 기능을 활용하면 거의 똑같은 문서화 주석 여러 개를 유지보수하는 부담을 줄일 수 있지만,사용하기 까다롭고 제약도 조금 있다.비록 공개된 모든 API 요소에 문서화 주석을 달았더라도,여러 클래스가 상호작용하는 복잡한 API라면 문서화 주석 외에도 전체 아키텍처를 설명하는 별도의 설명이 필요할 때가 왕왕 있다.
문서화 주석은 여러분 API를 문서화하는 가장 훌륭하고 효과적인 방법이다.
공개 API라면 빠짐없이 설명을 달아야 한다.
표준 규약을 일관되게 지키자.
잘 쓰인 문서인지를 확인하는 유일한 방법은 자바독 유틸리티가 생성한 웹페이지를 읽어보는 길뿐이다.
다른 사람이 사용할 API라면 반드시 모든 API 요소를 검토하라.