- PR -

こんなクラスいかがですか?

1
投稿者投稿内容
でこ
会議室デビュー日: 2005/05/24
投稿数: 4
投稿日時: 2005-05-24 20:50
面白いと思って作ってみました。
こんなクラスダメでしょうか?
(そもそもこんな書き込みがダメ・・・?)

利点:Debuggerを使わなくても何行目で問題が発生しているかわかる。
欠点:遅い!!または、人によってこういったExceptionの使い方に拒絶反応を起こす。

乱用すると大変なことになると思いますが、楽しいクラスではないかと思っています。
ちょっとしたクラスを作成し、ちょっとテストするときなどどうでしょうか?

使い方:
java -Ddebug=true ITest

実行結果:
[BEGIN] ... ITest.main(ITest.java:3)
[OK] ... ITest.test(ITest.java:13)
[NG] ... ITest.test(ITest.java:16)
ITest.test(ITest.java:19)
[ABORT] ... ITest.main(ITest.java:7)
[FINISH] ... ITest.main(ITest.java:9)

テスト用:

コード:

public class ITest {
public static void main(String[] args) {
I.begin();
try {
test();
} catch (Exception e) {
I.abort();
}
I.finish();
}

public static void test() throws Exception {
I.ok();

if (true) {
I.ng();
}

I.here();

throw new Exception();
}
}




本体:

コード:

public final class I {

private static boolean isEnabled = Boolean.getBoolean("debug");

private I() {
}

public static void here() {
if (isEnabled) {
Position p = new StackTrace().getPosition(0);
System.out.println(p.out());
}
}

public static void begin() {
if (isEnabled) {
Position p = new StackTrace().getPosition(0);
System.out.println("[BEGIN] ... " + p.out());
}
}

public static void finish() {
if (isEnabled) {
Position p = new StackTrace().getPosition(0);
System.out.println("[FINISH] ... " + p.out());
}
}

public static void abort() {
if (isEnabled) {
Position p = new StackTrace().getPosition(0);
System.out.println("[ABORT] ... " + p.out());
}
}

public static void ok() {
if (isEnabled) {
Position p = new StackTrace().getPosition(0);
System.out.println("[OK] ... " + p.out());
}
}

public static void ng() {
if (isEnabled) {
Position p = new StackTrace().getPosition(0);
System.out.println("[NG] ... " + p.out());
}
}

private static class Position {

private final String className;

private final String methodName;

private final String lineNumber;

private final String fileName;

Position(StackTraceElement element) {
int ln = element.getLineNumber();
if (ln <= 0) {
lineNumber = "UNKNOWN";
} else {
lineNumber = String.valueOf(ln);
}

className = element.getClassName();
methodName = element.getMethodName();
fileName = element.getFileName();
}

public String out() {
return className + '.' + methodName + '(' + fileName + ':' + lineNumber + ')';
}
}

private static class StackTrace {

private StackTraceElement[] element = (new Exception()).getStackTrace();

public Position getPosition(int index) throws ArrayIndexOutOfBoundsException {
return new Position(element[index + 3]);
}
}
}




[ メッセージ編集済み 編集者: でこ 編集日時 2005-05-24 20:57 ]
a-san
ベテラン
会議室デビュー日: 2004/06/01
投稿数: 53
投稿日時: 2005-05-24 22:30
[BEGIN]、[OK]、[NG]だけではなく、引数で任意の文字列を表示できるようにしてはどうでしょうか?
また、出力先をSystem.outだけではなく、ファイルなどにもできるようにしてはどうでしょうか?
出力フォーマットも指定できるといいです。

結局、log4jやjava.util.loggingを使えばいいのでは?

それと、こういう試みはキライじゃないです。
でこ
会議室デビュー日: 2005/05/24
投稿数: 4
投稿日時: 2005-05-24 23:01
ご指摘通り書き直して、こんなクラスに改良してみました。

いかがでしょうか?
(もしかして会議室汚してますか・・・?こういうことをしても面白いかなと思いましてやってみましたが、反感招きましたら申し訳ないです)

コード:

public final class I {

private static Log log = LogFactory.getLog(I.class);

private I() {
}

public static void say(Object obj) {
if (log.isDebugEnabled()) {
Position p = new StackTrace().getPosition(0);
log.debug(String.valueOf(obj) + " ... " + p.out());
}
}

public static void caller(int n) {
if (log.isDebugEnabled()) {
Position p = new StackTrace().getPosition(n);
log.debug(n + "個上の呼び出し元は" + p.out());
}
}

public static void here() {
if (log.isDebugEnabled()) {
Position p = new StackTrace().getPosition(0);
log.debug(p.out());
}
}

public static void begin() {
if (log.isDebugEnabled()) {
Position p = new StackTrace().getPosition(0);
log.debug("[BEGIN] ... " + p.out());
}
}

public static void finish() {
if (log.isDebugEnabled()) {
Position p = new StackTrace().getPosition(0);
log.debug("[FINISH] ... " + p.out());
}
}

public static void abort() {
if (log.isDebugEnabled()) {
Position p = new StackTrace().getPosition(0);
log.debug("[ABORT] ... " + p.out());
}
}

public static void ok() {
if (log.isDebugEnabled()) {
Position p = new StackTrace().getPosition(0);
log.debug("[OK] ... " + p.out());
}
}

public static void ng() {
if (log.isDebugEnabled()) {
Position p = new StackTrace().getPosition(0);
log.debug("[NG] ... " + p.out());
}
}

private static class Position {

private final String className;

private final String methodName;

private final String lineNumber;

private final String fileName;

Position(StackTraceElement element) {
int ln = element.getLineNumber();
if (ln <= 0) {
lineNumber = "UNKNOWN";
} else {
lineNumber = String.valueOf(ln);
}

className = element.getClassName();
methodName = element.getMethodName();
fileName = element.getFileName();
}

public String out() {
return className + '.' + methodName + '(' + fileName + ':' + lineNumber + ')';
}
}

private static class StackTrace {

private StackTraceElement[] element = (new Exception()).getStackTrace();

public Position getPosition(int index) throws ArrayIndexOutOfBoundsException {
return new Position(element[index + 3]);
}
}
}




[ メッセージ編集済み 編集者: でこ 編集日時 2005-05-24 23:01 ]
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2005-05-24 23:03
私も昔に似たような事をやって、感動した覚えがあります
こだわるとキリがなく、結局Log4Jを使うようになりました。
当時はパフォーマンスの為に、非同期で実装した覚えがあります。

フォーマッターが遅かったので、
・ロガー利用側はログのキューにエンキューして復帰
・別スレッドで動いているロガー本体がデキューしながらログ出力
って感じで実装しました。

ちなみに、JDK1.3ではStackTraceElementが使えないので、
printStackTraceの出力先をStringWriterなどにしてStringを解析するか、
行番号やメソッド名は捨てて、SecurityManager#getClassContextから
Class配列を取得するという方法があります。

では頑張ってください
でこ
会議室デビュー日: 2005/05/24
投稿数: 4
投稿日時: 2005-05-25 13:28
なるほど、最終的に行き着く先はLog4jやJ2SE1.4からのロギングAPIなどに落ち着くわけですね。
たしかに、フォーマットを変更するだけで様々な情報を取得することが出来たり、パフォーマンス劣化を最小限に抑えていたり、さすがLog4jですね。

しかし、例えば、このクラスをメモ帳で開発を行う際に使うといったふうに捕らえると、どうでしょうか?
一度は、ご指摘の通りCommons-Loggingを使って書き直してみましたが、あれをSystem.outなどのPrintWriterクラスを通して出力するように置き換えることで標準のAPIのみで使用が可能になるという利点があると思います。
# そもそも、いまどきメモ帳などのテキストエディタで開発している人なんて少数派!? Throwable.getStackTrace()が1.4からというのも問題ですね・・・

とまぁLog4jなどのロギングAPI(フレームワーク)に対する利点を絞りだして見ましたが、このクラスで例外からは、こういった詳細な情報も取得出来るということも勉強になり、スレッドを立てた甲斐があったと思います
レスくださった方ありがとうございます m(__)v


[ メッセージ編集済み 編集者: でこ 編集日時 2005-05-25 13:35 ]
MMX
ぬし
会議室デビュー日: 2001/10/26
投稿数: 861
投稿日時: 2005-05-25 14:37
思い出したもの
http://nikkeibp.jp/wcs/leaf/CID/onair/jp/news/376183
デバッグコード挿入用 アスペクト指向 プログラミング ( AOP ) のためのEclipseプラグイン
デバッグコードをソースコード中に記述する必要がない (デバッグコードとソースコードを分離)
http://www.csg.is.titech.ac.jp/~usui/bugdel/

なお、どのタイミングでAspectを実現〜コンパイル時 ですね。
http://pcweb.mycom.co.jp/articles/2005/05/20/javaeod/
でこ
会議室デビュー日: 2005/05/24
投稿数: 4
投稿日時: 2005-05-25 15:22
なるほどAspectですか・・・
Bugdelには少し興味が湧きませんでしたが(すいません偏見なのでスルーしてください。
AspectJ 5のAnnotationを使ってAspectを実現はソソられました。
まだまだ勉強が足りない(情報収集も)ようなので、ネットの海で勉強してきます!!

皆さんありがとうございます
1

スキルアップ/キャリアアップ(JOB@IT)