« SNMPのhello-worldレベル具体例 | トップページ | ◆ケーブルをからまらないように巻く方法:「逆相巻」と「8の字巻」 »

javadocでジェネリックメソッドの@linkを書く、他

メモです。

本当はjavadocなどでソースを汚すべきではないのですが、htmlでのオンラインドキュメント を作成するには重宝しますので、使うことはあります。

Javadocは著しくソースの視認性を阻害しますので、ライブラリのオンラインドキュメント を作るといった場合を除いては決して利用すべきではありません。

内部仕様書を書く代わりなどというのはとんでもないことです。
大きなプロジェクトにおいて 決して工数低減にはなりません。この点を管理者は良く認識すべきです。
読んでもらおうとしていない、読んでもらう工夫をしていない javadocなどゴミを散らかしているのと同じです。重要なソース コードをゴミに埋もれさせてはならないのです。

さて、それはともかく本題。

 Java8以降の注意点(2020/03/08)

  • @depricatedによる注釈ができなくなった
    @depricatedを書くと"@deprecated"という文字列が表示されます。
  • HTMLタグのネストがエラーになる
    例えば<P>の中に<pre>を置くことはできなくなりました。
  • <table>には空の<caption>が必要。次のように記述します。
    <table><caption>&emsp;</caption>・・・</table>

 javadocをIEで見るための設定

javadocで生成したindex.htmはIEで直接は開けません。鬱陶しい警告が出て、 それを開いて、クリックするという遠い道のりを経なくてはなりません。

何度も繰り返し出る警告は、重要な警告をマスクし、yes癖をつける 極めて無神経で危険なものです。
この警告をなくす必要があります。

IEで直接開くためにはIEの設定を変更する必要があります。

[ツール]メニュー [インターネットオプション]の「詳細設定」で [マイコンピュータのファイルでのアクティブコンテンツの実行を許可する] にチェックを入れます。

なお、HTMLの冒頭に

<!-- saved from url=(0014)about:internet -->
を挿入する方法では、なぜかframeの枠のみが表示され中身が出ません。

 先頭行の終わりはとにかくドット.

各記述は始まりからドットまでが概要部に乗ります.

なお、とんでもないことですが、先頭説明文には半角ドットは記述できません。 例えば次のような説明を先頭に置くことはできません。
 文字列に...を付加する。
.は先頭行の終わりとみなされます。
これは{@literal }を用いてもできません。
なお、ドットを記述できないのは先頭だけで、第2行以降は大丈夫です。

。(丸)も有効との記述も見られますが、残念ながら私のところでは 無効でしたし、他で確認したところやはり無効でした。

最初の行は短く、かつドットで締める.

//次のコードでは「とあるジェネリッククラス。put(T)でデータをセットし」と見出しに出てしまいます。
//まるではなくドットにすれば見出し部は「とあるジェネリッククラス.」までとなります。
/**
 * とあるジェネリッククラス。
 * {@link #put(Object) put(T)}でデータをセットし
 */
public class SomeGenericClass<T> {
   public void put(T obj_)throws Exception{
      //...
      }
   }

見た目が変ですが仕方ありません。

 ジェネリッククラスのメソッドの@link

ジェネリッククラス(テンプレートクラス)でパラメタライズド型を引数とする関数を@linkで参照する場合、コードに 書かれた型名前で直接参照することはできません。
Objectを引数とする形で記述した上で後ろに本来の形を書く必要があります。

// 動く書き方
/**
 * とあるジェネリッククラス.
 * <p>
 * {@link #put(Object) put(T)}でデータをセットし....
 * </p>
 */
public class SomeGenericClass<T> {
   public void put(T obj_)throws Exception{
      //...
      }
   }
// 以下の真っ当な書き方は残念ながら受け付けられません
/**
 * とあるジェネリッククラス.
 * <p>
 * {@link #put(T)}でデータをセットし NG!
 * </p>
 */
public class SomeGenericClass<T> {
   public void put(T obj_)throws Exception{
      //...
      }
   }

 javadocキー文字のエスケープ@literal

javadocの中に@があったり、あるいは"*/"があるとエラーになってしまいます。

これを避けるため、javadocの中に@を書く場合{@literal @}と書きます。
*は{@literal *}と書きます。

ソースが汚くなりますが仕方ありません。

@literalは本来javadoc自体の不具合を避けるためのものですが、<などのHTML文字 などのエスケープにも用いることができます。

次の2つの行は同じものとなります。

&lt;A&gt;&lt;B/&gt;&lt;/A&gt;
{@literal <A><B/></A>}
{@literal ...}は複数行に渡っても構いません。
残念ながら[@literal}内では<b>などのHTML制御もエスケープされてしまいますので 細かな表現が必要な場合は使うことができません。

 図形他のファイル

<img src="XXX">による図形参照などを入れることもできますが、 参照が相対の場合参照不能となります。

通常doc-filesというフォルダをソースフォルダ上に作り、そこに 画像ファイルなどを置き、ソースからは
 <img src="doc-files/XXX.gif">
といった形で参照するようにします。

javadocの解説ではそれだけで良いらしいのですが、現実にはdoc-files の転送も行われず、結局人が手で改めてdoc-filesの転送を行う 必要があります。
javadocで.javaを指定せずパッケージを指定する場合は転送が行われる ことが分かりました

とはいえ、毎回人手で行うという馬鹿げた方法は絶対とるべきでは ないので、バッチファイル化しました。

 cssのマージ

本当に読んでもらおうとすると、独自のcssを当然用意することに なります。

javadocはjavadocでcssを作ります。そしてそれをマージする機能は javadocは持っていません。

「一旦javadocが生成したcssに手を加える」という解説が多いのですが 馬鹿げたことです。

別立てのcssをマージすることになります。

とはいえ、毎回人手で行うという馬鹿げた方法は絶対とるべきでは ないので、バッチファイル化しました。 (バッチに関する記述は古くなりました;現在はantで行っています; 詳細はいずれ記事にします)

javadoc起動バッチファイル雛形

次の標準手続きバッチファイル雛形を作成しました。

@echo off
pushd %~dp0
:: 環境設定
SET CLASSPATH=%CLASSPAH%
SET DOC_DIR=doc
SET ADD_FILES=
SET PKG_DIR=%DOC_DIR%\jp\co\Me\MyPkg1
SET CSS_FILES=my_style.css
SET DOC=-d %DOC_DIR%
SET JAVAS=ClassA.java ClassB.java ClassC.java javadocに載せるクラス

::-------- javadoc生成 -------
echo JAVADOC
rd /Q /S %DOC_DIR%
javadoc %DOC% %JAVAS%
if errorlevel 1 goto ERR:
::-------- doc-filesの転送
xcopy /S /Y /C /I doc-files %PKG_DIR%\doc-files
::-------- 付加ファイルの転送
for %%f in ( %ADD_FILES% ) do copy %%f %PKG_DIR% >NUL
::-------- cssのマージ
move %DOC_DIR%\stylesheet.css .
for %%f in ( %CSS_FILES% ) do (
   copy stylesheet.css + %%f temp.css
   move temp.css stylesheet.css
   )
move stylesheet.css %DOC_DIR%
::---------- 結果表示 ----------
:OK
set result=0
echo ===== OK =====
goto END: 
:ERR
set result=1
echo ===== SOME ERROR OCCURED =====
:END
if not "%1"=="" goto NOPAUSE
pause
:NOPAUSE
popd
exit /b %result%

 javadocのマージ:できません

おどくべきことに、javadocにはマージ機能がありません。-linkがその機能 のようにも読めたのですが違うようです。

複数のpackageからなるdocを作りたい場合、一旦それのための フォルダ構成を作り、javadocはただ1回で全てのパッケージを指定 して行う必要があります。 小さな開発ではパッケージ構成とフォルダ構成を完全に 一致させることも可能ですが、少し規模が大きくなれば、それは 現実的ではありません

そこで、javadoc作成専用フォルダに一旦ソースをコピーするバッチファイルの 雛形と、javadoc作成専用フォルダでjavadocを作成するバッチ雛形を作りました。 (バッチに関する記述は古くなりました;現在はantで行っています;詳細はいずれ記事にします)

自分用のcssもjavadoc作成専用フォルダにおきます。

どんどんと汚くなっていきますが仕方ありません。javadocは最悪の選択でした。。

:: ソースをjavadoc作成用フォルダにコピーする(ソースフォルダ毎にある)
::@echo off
pushd %~dp0
:: 環境設定
SET JDOC_DIR=..\..\..\..\jdoc javadoc作成用フォルダ
SET PKG_DIR=jp\co\Me\MyPkg1   パッケージのフォルダ
SET JDOC_PKG_DIR=%JDOC_DIR%\%PKG_DIR%
SET JAVAS=ClassA.java ClassB.java ClassC.java javadocに載せるクラス
rd /Q /S %JDOC_PKG_DIR%
md %JDOC_PKG_DIR%
for %%f in ( %JAVAS% ) do copy %%f %JDOC_PKG_DIR% 
xcopy /S /Y /C /I doc-files %JDOC_PKG_DIR%\doc-files
call %JDOC_DIR%\A20_buildJDOC.bat
:OK
set result=0
echo ===== OK =====
goto END: 
:ERR
set result=1
echo ===== SOME ERROR OCCURED =====
:END
if not "%1"=="" goto NOPAUSE
pause
:NOPAUSE
popd
exit /b %result%

:: javadoc作成専用フォルダに置くバッチ(ただ1個あるここではA20_BuildJDOC.bat)
::@echo off
pushd %~dp0
:: 環境設定
SET CLASSPATH=%CLASSPAH%
SET DOC_DIR=doc
SET ADD_FILES=
SET CSS_FILES=hi_style.css
SET DOC=-d %DOC_DIR%
SET PKGS=jp.co.Me.MyPkg1 jp.co.Me.MyPkg2 javadoc化するパッケージ
::-------- javadoc生成 -------
echo JAVADOC
rd /Q /Q %DOC_DIR%
javadoc %DOC% %PKGS%
if errorlevel 1 goto ERR:
::-------- cssのマージ
move %DOC_DIR%\stylesheet.css .
for %%f in ( %CSS_FILES% ) do (
   copy stylesheet.css + %%f temp.css
   move temp.css stylesheet.css
   )
move stylesheet.css %DOC_DIR%
::---------- 結果表示 ----------
:OK
set result=0
echo ===== OK =====
goto END: 
:ERR
set result=1
echo ===== SOME ERROR OCCURED =====
:END
if not "%1"=="" goto NOPAUSE
pause
:NOPAUSE
popd
exit /b %result%

なお、この作業で分かったのですが、doc-filesはパッケージ指定の時 は機能し、javaファイル指定の時は機能しないようです。

 結局

利用者APIを持つクラスと実際に動作するクラスを分けてしまいました。
利用者APIのクラスのメソッドは内部に持つengineインスタンスに 関数をそのまま投げる形です。
engineクラスはpublicだがjavadocは作成しない。engineクラスでは余程 の場合を除いてコメントは//で書く。/* */によるブロックコメントアウト を可能にするため。

/**
 * APIの殻だけクラス.
 * 使い方などの詳細を丁寧に書く
 */
public class SomeTool {
   SomeToolEngine engine=new SomeToolEngine();
   /**
    * 使い方などの詳細を丁寧に書く
    */
   public int foo(int i,String s){
      return engine.foo(i,s);
      }
   /**
    * 使い方などの詳細を丁寧に書く
    */
   public String boo(String s,boolean b){
      return engine.boo(s,b);
      }
   }

// 実際に動作するクラス
// メンテナンスのためのコメントをしっかり書く
public class SomeToolEngine {
   //  メンテナンスのためのコメントをしっかり書く
   public int foo(int i,String s){
      // ...
      }
   //  メンテナンスのためのコメントをしっかり書く
   public String boo(String s,boolean b){
      // ...
      }
   }

使ってもらうためのドキュメントとメンテナンスのためのドキュメントは 全く異なる観点から書かれます。

一つのソースに混ぜ込むのは無理です。だから中途半端で何の役に立たないjavadocが 乱造されるのだと思います。

最終的には、これも排して、完全にjavadoc生成のためだけの 擬似コードとするのが最も美しいやり方ではあると思う。

javadocと書いて「ほんまつてんとう」と読みます。

|

« SNMPのhello-worldレベル具体例 | トップページ | ◆ケーブルをからまらないように巻く方法:「逆相巻」と「8の字巻」 »

トラックバック


この記事へのトラックバック一覧です: javadocでジェネリックメソッドの@linkを書く、他:

« SNMPのhello-worldレベル具体例 | トップページ | ◆ケーブルをからまらないように巻く方法:「逆相巻」と「8の字巻」 »