Javadocãæ¸ããªã
ååã¯Javadocを書く - しげるメモã¨ããã¿ã¤ãã«ã§è©±ãé²ãã¾ããããä»åã¯éã«Javadocãæ¸ãããã©ã¯ãã£ã¹ã«ã¤ãã¦ã¡ã¢ãã¦ãã
ç§ã¯å¥ã«Javadocãæ¸ãã®ã好ããªããã§ã¯ãªããåç´ã«æ¸ããã»ããããã©ããããªãã¨æãã®ã§ãããã¦ã¾ãããã ãJavadocãæ¸ãã®ãããªãããã©ãããã¨ã¯èªåèªèº«ã§æãã¦ããã®ã§ããã®ããã©ããããã§ããã ãæ¸ããéãç¾å¨ã模索ä¸ã§ãã
ããæ¹ã¨ãã¦ã¯åç´ã§ã次ã®ãã¡ã©ã¡ããã§ãã
ããªãã®é¨åãEffective Java (Java Series)ã«ç´¹ä»ããã¦ãããã©ã¯ãã£ã¹ã¨ãã¶ãã¾ãããããã§ã¯ããã¾ã§"ããã©ããããªãJavadoc"ã¨ããè¦ç¹ã§ããã¾ãã
Javadocãããããæ¸ããªã
If an API is to be usable, it must be documented.
ã¦ã¼ã¶ãå©ç¨å¯è½ãªãã¹ã¦ã®APIã«Javadocãæ¸ãã
ä¸ã®ã«ã¼ã«ã¨åå± ãããã«ã¯ããããªæãã§ããã¾ãã
- ã¤ã³ã¿ã¼ãã§ã¼ã¹ã«Javadocãæ¸ãã¦ãå®è£ ã«ã¯æ¸ããªã
- APIãå ¬éããªã
- APIãå®è£ ããªã
ã¤ã³ã¿ã¼ãã§ã¼ã¹ã«Javadocãæ¸ãã¦ãå®è£ ã«ã¯æ¸ããªã
ç§ã¯ã¤ã³ã¿ã¼ãã§ã¼ã¹ã¡ã½ããã ãã«Javadocãæ¸ãã¦ããã®å®è£ ã«ã¯åºæ¬çã«Javadocãæ¸ãã¦ãã¾ãããjavadocãã¼ã«ã¯ã¡ã½ããã«ããã¥ã¡ã³ãã¼ã·ã§ã³ã³ã¡ã³ãããªãã¨ããªã¼ãã¼ã©ã¤ãå ã®ã¡ã½ãããã¤ã³ã¿ã¼ãã§ã¼ã¹ã¡ã½ããããåæã«å¼ã£å¼µã£ã¦ãã¦ããã¾ãã
ãã®ããæ¹ã¯ãJavadocãæ¸ãããã©ããããæ¸ããã ããããªãã¦å¯ä½ç¨(?)ã§ãããã¨ãããã¾ãã
- ã¤ã³ã¿ã¼ãã§ã¼ã¹ã¨ããã¥ã¡ã³ãã ãå¥ã«æ¸ãã
- ã¡ã½ããã®ã·ã°ããã£è¨è¨ã«æ³¨åã§ãã
- å®è£ ãåé¢ã§ãã
- åä½ãã¹ããåé¢ã§ãã
- ã¤ã³ã¿ã¼ãã§ã¼ã¹ã®Javadocã§æ±ºãããã¨ã ããå®è£
ããã¯ã©ã¹ãä½ãã
- æ©ã段éã§Mockã使ã£ã¦ãã¹ãã§ãã
- ããã¨ãªã£ããå®è£ ãåãæ¿ããã®ã楽
- java.lang.reflect.Proxy ã¯ã¤ã³ã¿ã¼ãã§ã¼ã¹ãã使ããªã
Effective Java ã®"Item 52: Refer to objects by their interfaces"ã§ãããããã¨ã¤ã³ã¿ã¼ãã§ã¼ã¹ã使ãå©ç¹ãæ¸ãã¦ããã¾ãã
APIãå ¬éããªã
ãã¦ã¼ã¶ãå©ç¨å¯è½ãªãã¹ã¦ã®APIã«Javadocãæ¸ããã®ãªãã°ãå ¬éããªããã°ã¦ã¼ã¶ã¯å©ç¨ã§ããªãã®ã§Javadocãæ¸ããªãã¦ããããªãã¾ãã
ãããããJavadocãæ¸ãã®ãããã©ãããAPIã¯ã
- ä½ãããã®ãæ確ã§ãªã (= whatãä¸æç)
- å©ç¨è ãæ³å®ã§ãã¦ãªã (= whyãä¸æç)
- å©ç¨è ã¨ã®å¥ç´ãå¤ããã (â è¨è¨ãä¸åå?)
ã®ãã¡ã©ããã ã¨æã£ã¦ããã®ã§ãå ¬éãã¦ã使ãããªãä¸ã«ä¿å®ãããªãããªããªãå ´åãããã¾ãã
ãã®å¯ä½ç¨(?)ã¯ãEffective Java ã®"Item 13: Minimize the accessibility of classes and members"ãåæã«æºããããã¨ã§ãããã
APIãå®è£ ããªã
ã便å©ããã ããä½ã£ã¦ããããã¨æããªãããJavadocãæ¸ãã®ãé¢åãªãã°ããAPIãå ¬éããªããã¨åãçç±ã§ãããªãããã
æ¬å½ã«å¿
è¦ã«ãªã£ãã¨ãã«ã¯ãä½ããããä½ã«ä½¿ããã©ãããæ¡ä»¶ã§ä½¿ãããããã¯èªåçã«è¦æ±ã¨ãã¦ä¸ãã£ã¦ããã¯ããªã®ã§ããã®ã¨ãã¾ã§å®è£
ããªãã¨ããæãã§ããã¹ãããã®ãé¢åã§ããã
Javadocã«æ¸ããã¨ãæ¸ãã
å ¬éAPIãåå¨ããªãããã°ã©ã ã¨ããã®ã¯ã»ã¨ãã©ãªãã¨æãã¾ãã®ã§ãã©ããã§çµå±Javadocãæ¸ããã¨ã«ãªãã¨æãã¾ãã
ç§ãJavadocã«æ¸ãã¹ãã ã¨æãé ç®ã¯ãååã®ãã§ãã¯ãªã¹ããéç®ããã¨ãã®è¾ºã§ãã
- ãã®ã¡ã½ãããä½ãããã
- ãã®ã¡ã½ããã¯å©ç¨è ã«ä½ãä¸ããã (ä½ãè¿ãããä½ãå¤ããã)
- ãã®ã¡ã½ããã使ãã«ã¯ãªã«ãããã°ããã®ã (äºåæ¡ä»¶)
- ãã®ã¡ã½ããã¯ã©ããªå½±é¿ãåã¼ãã®ã (äºå¾æ¡ä»¶ãå¯ä½ç¨)
- ãã®ã¡ã½ããã®å¦çã失æããã¨ãä½ãèµ·ããã (ç°å¸¸ç³»)
ããããã§ããéãåæ¸ãããã¨ã§Javadocã®è¨è¿°éãæ¸ããã¦ããã¾ãããæ¸ããªãããªããªãã¨ãããã¨ã¯åºæ¬çã«å¤ããã¾ããããããªãã°éã«Javadocã«æ¸ããã¨ãå°ãªããããªè¨è¨ã«æã£ã¦ãããã¨ã§ãJavadocèªä½ã®ããã©ããããæ¸ããã¾ãã
Javadocã«å¿ è¦ãªæ å ±ãæ¸ãã¦ãã£ã¦ãããã«çãã¾ã¨ã¾ã£ã¦ããã¨ãããã¨ã¯ã¡ã½ããã®è¨è¨èªä½ãç°¡æ½ã§ããã¨ãããã¨ã«ãªããå®è£ ããã¹ãã(ã¤ãã§ã«)æ¸ãããããã¾ããã
ããããããã©ããããªãããã«ããæ¹æ³ã¯å¤å²ã«æ¸¡ããããããåè«ã«ãªã£ã¦ãã¾ããã¡ã
ä½è¨ãªãã¨ãæ¸ããªã
å½ç¶ãªãããä½è¨ãªãã¨ãæ¸ããªããã°Javadocã¯çããªãã¾ãã
public interface Hoge { /** * ãã®ãªãã¸ã§ã¯ãã«æ ¼ç´ãããã»ãã»ããè¿ãã¾ãã * è¿ãããã»ãã»ãã¯{@link java.lang.reflect.Proxy}ã使ç¨ãã * ããã¯ã·ãªãã¸ã§ã¯ãã§ãã * ãã®ã¡ã½ããã¯Google Collections Libraryã使ç¨ã㦠* ã»ãã»ããæ¤ç´¢ãã¦ãããããJava Collection Frameworkãããé«éã§ãã * @return ãã®ãªãã¸ã§ã¯ãã«æ ¼ç´ãããã»ãã»ã */ HogeHoge getHogeHoge();
â¦æ£æçã«æ¸ãã¦ãããããããããã¼ã¨æã£ã¦ãã¹ã«ã¼ãã¦ãã ããããã ããã®ããã«æ¸ãã¨ãJavadocãé·ããªãã以ä¸ã®å¼å®³ãããã¾ãã
Javadocã«æ¸ãã¦ãããã¨ã¯ãå®è£ ãã§ã¯ãªããä»æ§ãã«ãªã£ã¦ãã¾ãã®ã§ãä½è¨ãªãã¨ãæ¸ãã¨å®è£ ã®å¹ ãéããã¦ãã¥ã¼ãã³ã°ãã§ããªããªã£ãããä¿å®ã®éã«ã¢ã¯ãããã£ãã¯ãªå®è£ ãå¼·è¦ãããããã¾ãã
è¦ã¯ãå©ç¨è
ããã®ã¡ã½ããã使ãããã«å¿
è¦ãªãã¨ã ãããã¹ã¦Javadocã«æ¸ãã¦ããã°ããããã©ã³ã¹æè¦ãéè¦ãã¨ã
IDEã«ããã°ã£ã¦ããã
Javadocã®éãæ¸ãããªãã¦ããJavadocãæ¸ãéã¯IDEã使ã£ã¦å¤å°åæ¸ã§ãã¾ãã
Eclipseã使ãã¨ãåºæ¬çã«@param, @return, @throw (ãã§ãã¯ä¾å¤ã®ã¿)ã¯èªåã§çæãã¦ããã¾ãããèªåè£å®ã§@linkãç°¡åã«æ¸ãããããã³ãã¬ã¼ããç»é²ããããã§ãã¾ããç§ãUMLã®ã¯ã©ã¹å³ãæããããªãã¨æãã®ã¯ãEclipseã使ãã¨Javadocã®è£å®ç³»ã便å©ããã¦ããå¼ãè¿ããªãããã§ãã
ã¡ãªã¿ã«ã使ã£ã¦ãããã³ãã¬ã¼ãã®ä¸é¨ã
- @return_or_null
- ãåå¨ããªãå ´åã¯{@code null}
- @nullpointer
- @throws NullPointerException å¼æ°${cursor}ã{@code null}ã®å ´å
- @illegalargument
- @throws IllegalArgumentException å¼æ°ã${cursor}å ´å
Javadocç³»ã®ãã³ãã¬ã¼ãã¯"@"ããå§ããã¨ãæ¥æ¬èªã§ããããèªåçã«åèªåºåãã¨ãªã£ã¦ã¤ã©ã¤ã©ãã¾ããã
ç¶æ¿ãããªã
Effective Javaã«ã¯ "Item 17: Design and document for inheritance or else hrohibit it" ã¨ããé ç®ãããããããç¶æ¿ã¯åä»ãªåé¡ã§ããããã« "... document for inheritance ..." ã¨ããã®ã§ãéã«ç¶æ¿ãç¦æ¢ããã°ãããããããªããã¥ã¡ã³ãã¯è¦ãã¾ããã
ç¶æ¿ãç¦æ¢ãã*1ã«ã¯ãä¸ã®3ãã¿ã¼ã³ãæå¹ã ã¨æãã¾ãã
- ã¯ã©ã¹ãfinalã§å®£è¨ãã
- ãã©ã¤ãã¼ãã³ã³ã¹ãã©ã¯ã¿ã®ã¿ãæä¾ãã
- éç¨final
æå¾ã®ã¯ç§ã®é èªã§ãã¯ã©ã¹ãã¤ã³ã¿ã¼ãã§ã¼ã¹ã®Javadocã«æ¬¡ã®éæ³ã®ä¸è¨ãæ¸ãã ãã§ãã
ã¢ããªã±ã¼ã·ã§ã³ã§ã¯ããã®ã¯ã©ã¹ããµãã¯ã©ã¹åããªãã§ãã ããã
ã¡ãªã¿ã«ããã¯ãããå¢ãã§ããããã¦ãã¦ã§ãããEclipseã§ã¯ããè¦ããã¾ã (@see "This interface is not intended to be implemented by clients." - Google 検索)ã
ãªãã¸ã§ã¯ããå¤æ´ãããªã
ãªãã¸ã§ã¯ããç°å¢ãå¤æ´ãããã¡ã½ããããªããã°ãJavadocããå¯ä½ç¨ããªãã¸ã§ã¯ãã®ç¶æ ã«é¢ããè¨è¿°ãå ¨é¨åãã¾ãã
Effective Javaã® "Item 15: Minimize mutability" ã«è©³ããããã¾ãããå¤æ´ä¸å¯è½ãªãªãã¸ã§ã¯ãã¯ãããããªã¨ããã§å©ç¹ãããã¾ãã
- 常ã«ã¹ã¬ããã»ã¼ã
- å®å¿ãã¦å ±æã§ãã
ãã ãããªãã¸ã§ã¯ããå¤æ´ä¸å¯è½ã«ããã«ã¯ããããªãã«ããããã¨ãããªãããªããªããã¨ãããã¾ã (ãããEffective Javaã«è©³ããããã¾ã)ã
- ã³ã³ã¹ãã©ã¯ã¿å¼æ°ã«å¤æ´å¯è½ãªãªãã¸ã§ã¯ãã渡ãããå ´åããã¹ã¦ãã£ã¼ãã³ãã¼ãã¨ã£ã¦ä¿æãã
- @see "Item 39: Make defencive copies when needed"
- ã¡ã½ãããå¤æ´å¯è½ãªãªãã¸ã§ã¯ããè¿ãå ´åããã¹ã¦ãã£ã¼ãã³ãã¼ãè¿ã
- Collections.unmodifiable*(...) ãªã©ã§ãå¤æ´ä¸å¯è½ãªãã¥ã¼ãè¿ãã¦ããã
ããªãã¸ã§ã¯ãã®çæãç¡é§ã ãã¨æãæ¹ã¯ãä¸åº¦ããã©ã¼ãã³ã¹è¨æ¸¬ãã¦ã¿ãã¨ããã¨æãã¾ããä¸æã«ã¹ã¬ããã»ã¼ãã®ããã®åæãçµãããéããªããã¨ãå¤ãã§ãããã¹ã¬ããã®ã¡ã¢ãªã¢ãã«ãæè¿ã®GCã®ä»çµã¿ãèããã¨ãã©ã¤ããµã¤ã¯ã«ã®çãå°ããªãªãã¸ã§ã¯ãã¯çæãååããã£ããéãã¯ãã§ãã
ã¸ã§ããªã¯ã¹ã使ã
éå»ã«ä½åãã¸ã§ããªã¯ã¹ã«ã¤ãã¦è°è«ãã¾ããããã¸ã§ããªã¯ã¹ã¯Javadocã®ããã©ããããæ¸ããããã«ãæå¹ã§ãã
List<String> getHogeList(); List getFooList();
åè
ã®"getHogeList"ã¯æããã«æååã®ãªã¹ããè¿ããã¨ããããã¾ãããå¾è
ã®"getFooList"ã¯Javadocã«ãªã¹ãã®è¦ç´ ã®åã¾ã§æè¨ãã¦ãããªãã¨ãããã¬ã§ãã¬ã¼ã¯ãã¤ã³ãã®å¯¾è±¡ã«ãªãã¾ãã
åææ¡ä»¶ãå³ãããã
åææ¡ä»¶ãå³ããããã¨Javadocã¯éã«çããªãã¨ãã主張ã§ãã次ã®(極端ãª)ä¾ãè¦ã¦ãã ããã
/** * äºã¤ã®æååãæ´æ°ã¨ã¿ãªãããã®åãè¿ãã */ long add(String a, String b);
ãã¡ããããã§ã¯Javadocã¨ãã¦ã¯ä¸ååã§ã次ã®ãããªãã¨ãèããªããã°ãªãã¾ããã
- æ´æ°ã®ãã©ã¼ãããã¯ï¼
- 符å·ãã¤ãã¦ã¦ãOKï¼
- éä¸ã«ã¹ãã¼ã¹ãå ¥ã£ã¦ãããï¼
- æ¼¢åã¯ï¼
- 16é²æ°ã¨ãã¯ï¼
- æ°å¤ã®ç¯å²ã¯ï¼
- æ°å¤ã表ç¾ããªãå ´åã¯ï¼
- nullã®å ´åã¯ï¼
ããããå ´åã«ã空æåãnullã®ã¨ãã¯0ã¨ãã¦æ±ããã¨ããa~fãå«ã¾ãã¦ããã16é²æ°ã¨ãã¦æ±ããã¨ãããã¾ãã¾ãªåææ¡ä»¶ã®ç·©åæ¹æ³ãæãã¤ãããããå ¨é¨Javadocã«é·ã ã¨æ¸ãã®ãæ¹æ³ã®ã²ã¨ã¤ã§ããããç§ã¯åç´ã«ä¸ã§ããã¨æãã¾ãã
/** * äºã¤ã®æ´æ°ã®åãè¿ãã * ... */ long add(int a, int b);
ã¡ãªã¿ã«ãã®ä¾ã¯ã"Item 50: Avoid strings where other types are more appropriate" ã«ãé¢é£ãã¦ã¾ãã
ãã®ããæ¹ãAPIã®ã¦ã¼ã¶ããªãã£ãèæ ®ããå ´åã«å¿ ãé©åã§ããã¨ã¯æãã¾ããããåºæ¬çã«ã¯åææ¡ä»¶ãå³ãããã¦ãå°ãã§ãå¤ãããç¡æ æ²ã«ä¾å¤ãã¹ãã¼ããã°ããã¨æãã¾ãã
ãã¨ãã°ã
/** * å¼æ°ã«æå®ããã3æåã®æååããéé ã«ä¸¦ã³æ¿ãã¦è¿ãã * å¼æ°ã3æåã«æºããªãå ´åã¯å é ã«ã¹ãã¼ã¹ãå ã㦠* 3æåã«èª¿æ´ããå¾ã«éé ã«ä¸¦ã³æ¿ããæååãè¿ãã * å¼æ°ã3æåãè¶ ããå ´åã¯4æåç®ä»¥éãé¤å»ã㦠* 3æåã«èª¿æ´ããå¾ã«éé ã«ä¸¦ã³æ¿ããæååãè¿ãã * ãã ããå¼æ°ã«{@code null}ãæå®ãããå ´åã¯ãã®ã¾ã¾{@code null}ãè¿ãã ...
ã¨ããã¡ã½ããã¯ã¡ãã£ã¨æ æ²æ·±ããã§
/** * å¼æ°ã«æå®ããã3æåã®æååããéé ã«ä¸¦ã³æ¿ãã¦è¿ãã * @param string 3æåã®æåå * @return 対象ã®æååãéé ã«ä¸¦ã³æ¿ããæåå * @throws IllegalArgumentException * å¼æ°ã«æå®ãããå¤ã{@code null}ã¾ãã¯3æåã§ãªãå ´å */
ãããã®æ絶æã§ããã¨ç°å¸¸ç³»ã®è¨è¿°ãçããªã£ã¦Javadocãæ¸ãæ°ã«ããªãã¾ããä¾ã«ãããããã«ãåææ¡ä»¶ãããããã¦ãã¾ãã¾ãªã±ã¼ã¹ã«å¯¾å¿ãããã¨ããã¨ãæ¬æ¥ãªãç°å¸¸ã§ããæ¡ä»¶ãã«ãã´ãªåããã¦ããããããã©ã®ããã«å¯¾å¦ããã®ããã¡ã½ããã®ä»æ§ã¨ãã¦æè¨ããªããã°ãªãã¾ããã
åææ¡ä»¶ãå³ãããããã¨ã§ãã»ãã®ãã°ãæµ®ã彫ãã«ã§ããã¨ããå©ç¹ãããã¾ãããã¾ãåææ¡ä»¶ãããããã¦ç°å¸¸å¤ãæ£å¸¸å°ãã®ããã«æ±ã£ã¦ãã¾ãã¨ãã»ãã®ãã°ã§çºçããç°å¸¸å¤ãè¦éãããã¦æ£å¸¸ã«åãã¦ãããã®ããã«é¯è¦ããã¦ãã¾ãå ´åãå¤ã ããã¾ãã
ã¡ãªã¿ã«ç§ã®éçºç°å¢(Eclipse)ã§ã¯ãã¡ã½ããã®ã³ã¡ã³ããã³ãã¬ã¼ãã次ã®ããã«ãªã£ã¦ã¾ãã
/** * ${tags} * @throws NullPointerException å¼æ°ã«{@code null}ãæå®ãããå ´å */
ã¤ãã§ã«ãã¨ãã£ã¿ãã³ãã¬ã¼ãã«æ¬¡ã®ãããªãã®ãããã¾ãã
if (${cursor}${} == null) { throw new NullPointerException("${}"); //$$NON-NLS-1$$ }
æå¤ã¨ä¾¿å©ã§ãã
ãã§ã¤ã«ãã¡ã¹ã
Effective Javaã® "Item 64: Strive for failure atomicity" ã«ãããããã«ãã¡ã½ããã®å¦çä¸ã«ã¨ã©ã¼ãçºçããããªãã¸ã§ã¯ãã®ç¶æ ãã¡ã½ããå¼ã³åºãåã«ãã¼ã«ããã¯ããã®ããªã¹ã¹ã¡ã§ãã
以ä¸ã®ã¡ã½ããã§ãmap.get("a")ã¨map.get("b")ãåç §å¯è½ã ã¨ä»®å®ããã¨ããä¸ã®put2ã¯ã©ããªè¨è¿°ãå¿ è¦ã§ããããã
private Map<String, String> map; ... public void put2(Object a, Object b) { map.put("a", a.toString()); map.put("b", b.toString()); }
å®è£ ãè¦ãã¨ãaãbãnullã ã¨ã¨ã©ã¼ã«ãªãã®ã¯åããã¾ãããbã ããnullã®å ´åã«put2ãå¼ã³åºãã¨ãmap.get("a")ãç¡é§ã«å¤æ´ããã¾ããJavadocã«ã¯ãã¹ã¦ã®å¯ä½ç¨ãæè¨ããã«ã¼ã«ãªã®ã§ããããJavadocã«ææåãããã¨ã«ãªãã¾ãã
ããããå ´åã¯ããã©ããªã®ã§ããã§ã¤ã«ãã¡ã¹ãã§å®è£ ãã¦ããã¨Javadocãçããªãã¾ãã
public void put2(Object a, Object b) { if (a == null) throw new NullPointerException("a"); if (b == null) throw new NullPointerException("b"); map.put("a", a.toString()); map.put("b", b.toString()); }
ããã¯Javadocã§å¿ããããã¨ã§ã¯ãªããå®è£
è
å´ã®ãã©ã¯ãã£ã¹ããããã¾ãããã©ã¡ãã«ãããbã ããnullã®å ´åã«å¯ä½ç¨ãæè¨ããã¦ããªããã°ãå®è£
è
ã¯ãã§ã¤ã«ãã¡ã¹ãããã©ã³ã¶ã¯ã·ã§ã³ãã¼ã«ããã¯ã®ä»çµã¿ãä½ã£ã¦ã¢ãããã¯æ§ãä¿è¨¼ããªãã¨ãå®è£
ã¨Javadocãããã¾ãã
ã§ã
ã»ãã«ãããããã¨ããæ°ããã¾ãããå¿ããã¦ãããã©ã¯ãã£ã¹ãæãã¤ããé ã«æ¸ãã¦ã¿ã¾ãããé·ããªããããï¼ç ããªã£ã¦ããã®ã§ãã®è¾ºã§ããã¦ããã¾ãã
ã»ãã®ãªã¹ã¹ã¡ãããã°æãã¦ãã ããã¾ãã
*1:æè¿ã§ã¯ãabstractã¨æ¸ãã¦ããªããã®ã¯åºæ¬çã«ç¶æ¿ããªãã®ãæ®éã ã¨ã¯æãã¾ãã