常識の範囲かも知れないけどDI関連のテクニックをメモ書き程度に。こういうコンテンツって需要あるのかな?
いわゆる外部リソースへのアクセスは抽象化し、設定の外部化をしたほうが良いです。例としては、以下のようなモノがあげられます。
・データベースなど外部システムとの接続情報(IP、IDなど)
・ログの出力位置や形式
・システム日付
理由としてはテストのためです(ポータビリティについては、テスト容易性の2次的な効果と思っています)。
1.単体テストのため
単体テストは再帰的に実行される必要があるため、常に実行結果が同じになる必要があります。もっともローレベルの単体テストは、実リソースにアクセスすることなくテストされるようにできるか、見当の必要があります。
2.システムテストなどのシミュレーションのため
上記と似ていますが、システムテストや運用テストの場合、本番とは異なる特定の状況(日付、リソース配置)をシミュレーションして実施されることが一般的です。そう言った場合、アプリケーション側で融通が効くと、テストが実施しやすくなります。
なお「付日処理」のように、本番環境においても特定の状況であることを前提にシステムを動かすこともあります。こういう場合にも便利です。
■設定情報系
Springframeworkであれば、以下のような手順で利用が可能です。詳しい設定はこちら。
1.プロパティファイルを準備
2.プロパティファイルを読み込み
3.プロパティファイル内のキーを${KEY}で参照
・プロパティファイルの読み込みについては、classpath:だけでなくてfile:とかも使えます。詳しくはこちら。
・本番環境だけ設定を変えたい場合は、プロパティファイルを切り替えるのが一般的でしょう。ビルド時に本番専用のプロパティファイルをWARに含むようにします。Maven2のProfile機構を組み合わせると便利です。詳しくは「Maven2で環境に合わせて設定ファイルを切り替える方法(改訂版)」。
・JVMシステムプロパティは自動的に読み込まれます。${KEY}で、システムプロパティも読み込み可能です。
・相当マニアな事でもない限り、大抵のことは設定でできてしまいます。が、その設定方法を見つけるのが難しいのがSpringの悪いところ。
■ログ
ログは、もうライブラリを使いましょう。現在であればlogbackが良いです。log4jの後継になります。また、SLF4J(Simple Logging Facade for Java)をセットで導入してください。commons-loggingの後継です。ここらのログ実装は歴史的に色々あるのです。logkitとj.u.l(java.util.logging)とかね。
さて、既存のライブラリ群がcommons-loggingに依存している可能性が非常に高いのですが、その場合には、「Spring2.0でLogbackを使う」を参考にしてください。Maven2を使っている場合は、dependencyに対してexclusionを使って依存先の依存を丁寧に取り除く必要があります。
あ、全然、DIの話じゃないことに気づいた。
■システム日付
システム日付に限らず、コードの中で直接的に取得するモノはResolverパターン(と呼ぶのか?)を使います。Resolverは解決者という意味で、DNSの名前解決やXMLでの名前空間解決などで使われている名称です。
たとえば、システム日付であればinterface SystemDateResolverを作って、その実装をDIコンテナ上ですり替えます。
//インターフェース
public interface SystemDateResolver {
Date resolveSysmteDate();
}
//本物
public class SystemDateResolver implements SystemDateResolver {
@Override
public Date resolveSysmteDate() {
return new Date();
}
}
//ダミー(固定値を使う)
public class SystemDateFixedResolver implements SystemDateResolver {
private Date fixedSystemDate;
private void setFixedSystemDateAsString(String fixedSystemDate) {
//変換して設定
//プロパティエディタを使う方法もありますが、ややこしいので別の機会に
}
@Override
public Date resolveSysmteDate() {
return fixedSystemDate;
}
}
