ローカル環境では標準出力(または標準エラー出力)にデバッグプリント文を出力し、
リモート環境ではなにもして欲しくない。
これをすべて自動で実現させるための方法についてまとめておく。
具体的には、プログラミングコンテストでデバッグコードの除去ミスがあったので
同じミスを二度と起こさないようにするための方法。
単純な方法(ただし手作業あり)
一番簡単なのは、デバッグモードを表す変数を準備しておくこと。
ローカルではデバッグモードを有効にしてデバッグプリント文を有効にしておき、
リモートにソースコードを提出する際には変数を切り替えておく。
簡単な実装例は以下の通り
boolean DEBUG = true; public void debugPrint(Object obj) { if(DEBUG) System.out.print(obj); }
簡単だけど、
といったデメリットが発生する(特に焦ってると変数の書き換えを忘れる)。
自動化する方法
方針としては、以下の通り。
変数の書き換えが面倒なのでローカル/リモートを自動判定させる。
また、デバッグプリントにはPrintStreamを利用する。
環境の自動判定にはSystem.getProperty()を利用する。
取得するプロパティ値には、"user.dir"を利用した。
他にもいろいろあるけど、この値が偶然一致することはないと思ったので。
実装例は以下の通り
private static PrintStream debug; private static boolean DEBUG = true; static { if (System.getProperty("user.dir").toString().equals(<ローカルディレクトリ名>) && DEBUG) { debug = System.out; } else { debug = new PrintStream(new OutputStream() { @Override public void write(int b) {} }); } }
このあたりの実装は過去のデバッグプリントの通り。
Javaにおけるデバッグプリントの実装 - 出力を入力へ
あとは上記の<ローカルディレクトリ名>に固有の値を入れておけば、
固有情報が一致するローカル環境でのみデバッグ文が有効になる。
もちろん、ローカル環境でデバッグプリントを無効化したい場合は
変数DEBUGにfalseをセットすればよい。
自動化する方法(プロパティ値が取得できない場合)
セキュリティ設定によってはgetProperty()でプロパティ情報を取得できない。
具体的には、Codeforcesで上記コードを実行すると
以下のような例外を投げるため上手くいかない
java.security.AccessControlException: access denied ("java.util.PropertyPermission" "user.dir" "read")
取得できないのであれば、取得できない場合をリモートと判定させる。
実装例は以下の通り
private static PrintStream debug = null; private static boolean DEBUG = true; static { try { if(System.getProperty("user.dir").toString().equals(<ローカルディレクトリ名>) && DEBUG) { debug = System.out; } } catch(Exception e) { } if (debug == null) { debug = new PrintStream(new OutputStream() { @Override public void write(int b) {} }); } }
これでDEBUG変数によらず、リモート環境ではデバッグ文が無効化できる。
加えてPrintStreamの各種メソッドが利用できるので便利。