S-JIS[2009-09-23] 変更履歴
ひしだま作の、Excelに記述したメッセージ一覧からJavaの定数クラス及び文言のプロパティーファイルを自動生成するツールです。
msgcode.zip | (30.9kB) | [2009-09-23] |
メッセージコードの仕様(形式や連番の桁数とか)はシステムによって異なるので、カスタマイズするのが前提です。
A | B | C | D | E | F | G | |
1 | |||||||
2 | レベル |
コード |
概要 |
テキスト |
可変部の説明 | ||
3 | 0 | 1 | |||||
4 | I | 0001 | サンプル | サンプルメッセージ:{0} | 自由文言 | ||
5 | I | 0002 | 処理開始 | {0}処理開始 | 処理名 | ||
6 | I | 0003 | 処理終了 | {0}処理終了:コード={1} | 処理名 | 終了コード | |
7 | W | 0001 | 警告終了 | 警告終了 | |||
8 | E | 0001 | 異常終了 | 異常終了:コード={0} | 異常コード | ||
9 |
/**
* メッセージコード定数.
*/
public enum MsgCodeEnum {
/** サンプル */
MSGCODE_I_0001(Level.INFO),
/** 処理開始 */
MSGCODE_I_0002(Level.INFO),
/** 処理終了 */
MSGCODE_I_0003(Level.INFO),
/** 警告終了 */
MSGCODE_W_0001(Level.WARNING),
/** 異常終了 */
MSGCODE_E_0001(Level.SEVERE),
;
protected Level level;
/**
* コンストラクター.
*
* @param level メッセージレベル
*/
MsgCodeEnum(Level level) {
this.level = level;
}
/**
* メッセージレベル取得.
*
* @return メッセージレベル
*/
public Level getLevel() {
return level;
}
protected static ResourceBundle RESOURCE_BUNDLE;
/**
* メッセージテキスト取得.
*
* @return メッセージテキスト
*/
public String getText() { //TODO synchronizedした方がいいか?
if (RESOURCE_BUNDLE == null) {
RESOURCE_BUNDLE = ResourceBundle.getBundle(MsgCodeEnum.class.getPackage().getName() + ".msgcode_text");
}
return RESOURCE_BUNDLE.getString(name());
}
}
##############################
# メッセージコード文言
# (日本語用)
##############################
#サンプル
MSGCODE_I_0001=サンプルメッセージ:{0}
#処理開始
MSGCODE_I_0002={0}処理開始
#処理終了
MSGCODE_I_0003={0}処理終了:コード={1}
#警告終了
MSGCODE_W_0001=警告終了
#異常終了
MSGCODE_E_0001=異常終了:コード={0}
#END
import jp.hishidama.msgcode.excel.Message; import static jp.hishidama.msgcode.excel.MsgCodeEnum.*;
Message m = MSGCODE_I_0001.createMessage("引数の例"); Message e = MSGCODE_I_0003.createMessage("サンプル", Integer.toString(123)); String text = m.getText();
メッセージコードを表すクラスは、ここではあえて列挙型(enum)を使っています。
昔からよくあるコーディングでは、この手のメッセージコードはString型で記述されることが多いような気がします。
しかも下手をすると、定数クラスにすらなっていない!
//メッセージコードを直書きする駄目な例 Message m = MessageCodeManager.getMessage("I_0001"); Message m = MessageCodeManager.getMessage("I_0009"); ←存在しない値を書いても実行するまで発覚しない
文字列で直書きすると、存在しないコードを使ってもコンパイルエラーになりません。
また、あるコードを使っている箇所を検索しようとした場合、別の文字列が一部だけマッチして引っかかってくる可能性があります。
最低限、定数フィールド化(static finalなフィールドにする)は必須でしょう。
public interface MsgCodeConstant { /** サンプル */ public static final String MSGCODE_I_0001 = "I_0001"; /** 処理開始 */ public static final String MSGCODE_I_0002 = "I_0002"; /** 処理終了 */ public static final String MSGCODE_I_0003 = "I_0003"; /** 警告終了 */ public static final String MSGCODE_W_0001 = "W_0001"; /** 異常終了 */ public static final String MSGCODE_E_0001 = "E_0001"; } Message m = MessageCodeManager.getMessage(MsgCodeConstant.MSGCODE_I_0009); ←存在しないのでコンパイルエラー
しかしこういった個数の限られた値群にこそ、列挙型を使用すべきだと思います。
Stringでは、結局、他の全然関係ない値を指定することが許されてしまうからです。
Message m = MessageCodeManager.getMessage("zzz"); ←存在しない値を書いても実行するまで発覚しない
そして、これらを手でいちいちコーディングするのは馬鹿らしいし、どうせメッセージ一覧はExcelで管理することがほとんどだから、Excelマクロ(VBA)で自動生成するのが自然の流れでしょう。
(また、Excelで管理していても、“設計書としての体裁を優先して、マクロで自動生成できない”ようなものは工数の無駄だと思う)
個人的には、文言を管理する為にプロパティーファイルやXMLファイルを使うのも嫌いです。
仮にプロパティーファイル内に存在しないキーをJavaプログラムで使ってしまった場合、それを実行するまで問題が発覚しないからです。
(また、Eclipse上でのF3キーを使った移動も出来ないから)
まぁExcelから自動生成してその定数を使っていれば、プロパティーファイルとの不整合は起きないはずですが。
列挙型を使えば、コード値のクラスにメソッドを追加できる為、文言だって指定するのは簡単です。
public enum MstCodeEnum {
/** サンプル */
MSGCODE_I_0001(Level.INFO, "サンプルメッセージ:{0}"),
/** 処理開始 */
MSGCODE_I_0002(Level.INFO, "{0}処理開始"),
/** 処理終了 */
MSGCODE_I_0003(Level.INFO, "{0}処理終了:コード={1}"),
/** 警告終了 */
MSGCODE_W_0001(Level.WARNING, "警告終了"),
/** 異常終了 */
MSGCODE_E_0001(Level.SEVERE, "異常終了:コード={0}"),
;
〜
}
とは言うものの、多言語対応を考えれば、ResourceBundleというクラスがそれに対応している訳だし、その仕組みを使うのがきっと無難でしょう。