AP開発時に決めておくこと(2)−設定ファイル

設定ファイルの分割を間違えると、設定項目が至る所で重複しはじめる。もしくは細かくなりすぎて管理が煩雑になる。システム毎に多少異なるにしても、基本的な分割の考え方は変わらない。なお、ここでは、ファイルに限らず、APから外出しにしたスタティックな情報全てを設定ファイルと呼ぶことにするため、DBのテーブル上に定義された値や環境変数も、それに該当する場合があることに注意。

差異が生じる要件の認識(システム面)

何らかの理由で設定値を変更することが出来るようにするために、設定値を作成する。例えばシステム面においては、おおむね、以下のような区分で、変更する要件が生じやすい。
重要なことは、この単位で設定ファイルを分割することではなく、どの項目が、どういう状況で変更される可能性があるかを予測し、各設定項目をグルーピング出来るか腕の見せ所となる。
これ以外にも、業務的観点で差異が発生することがある。例えば、処理対象データを顧客ごとに区分けしていれば、それ単位で設定値を変える必要が生ずる可能性がある。その場合は、その単位ごとに設定ファイルを用意することを検討する。

1.環境単位での差異の発生

環境毎、例えば、開発環境、性能試験環境、商用環境等の差異。
例えば、ホスト名/IPアドレス、ログ出力レベル、各種(システム的な)パスワード等は環境差分のある設定項目となる。
なお、物理環境だけではなく、論理的な環境、例えば開発チームが同一サーバを共用で利用する際に良く出てくる「面」という概念もこれにあたる。(どうでも良いけど、いい加減、ディレクトリで面分割して手動で管理するとか、伝統的かつ歴史的実績溢れる手法はもう止めて、Dockerとか使おうよ。疲れる。)

2.サーバ種類単位での差異の発生

サーバの種類毎、例えば、APサーバとバッチサーバ、DBサーバ等の差異。
例えば、オンラインAPとバッチサーバでは、将来の拡張性を考えて、現状は同一DBを参照するものの、将来的には接続先DBを分けたいと考えた場合、接続先DBの設定値はこの種類の差異となる。(OracleRACで構築してても、キャッシュフュージョン対策で、こういうことを考えたりする。)

3.○号機での差異の発生

1号機や2号機等の差異。
サーバ間連携を実装する場合、通常は1号機同士で連携するが異常時には接続先を切り替えるというようなケースの場合、1号機と2号機での設定値に差異が発生する。

4.プロセス単位の差異の発生

同一サーバ上に複数のプロセスが存在する場合でも、プロセス単位でも分ける必要があることがある。

設定ファイルの持ち方と読ませ方

さて、差異を認識したら、次にそれを複数の設定ファイルに分散して定義する。
ここで重要なことは、各グループに所属する設定項目の数を視野に入れつつ、設定値の管理方法、設定ファイルの管理方法、設定ファイルの分割の単位、設定値のAPへの読ませ方、設定ファイルの作り方を同時に考えて、設定ファイルの単位を定義することだ。ばらばらに考えると、後で苦労する。
実装面で考えた場合、一番重視するのは設定値のAPへの読ませ方だ。設定値を複数ファイルから読み込めること、valueがネストして定義できること、ファイルと項目が紐付かない形で読み込めることが重要となる。spring等では、placeholderを使えば簡単に実現できる。springを使っていない場合、自分で作らないといけないので、どこまで汎用的に作るかは、QCDを考えて決定する。
AP再起動を行わずに動的に変更する要件があるかどうかも重要となる。動的に変更する要件がある場合、設定値を参照するために都度設定ファイルを読む形やいっそDBに格納しておいたり、もしくは、設定値再読み込みのためのメソッドを用意しJMX経由で呼び出すか等、考える。
設定値をネスト化させることが出来る場合、設定値のツリー設計も行う必要があるだろう。その場合、設定ファイルのツリーの最下層に、共用設定ファイルを用意した方が良いかもしれない。ここまで来ると、クラス設計/テーブル設計並みに、設定値設計に力を入れることになる。
忘れてはいけないのが、設定値は必ずしもファイルにpropertyファイルに書く必要はない。環境変数で定義するものも出てくる。例えば、shellとjavaで同じ設定値を見たい場合、propertyではなく、環境変数で読み込ませるような工夫が必要となる。
設定ファイルの置き場所も重要となる。シンプルにクラスパスに置けば良いのだが、たまに、なぜか絶対パスを指定しないといけないPJが存在する。(共通部品を作ってるチームに文句を言ったが、もはや変えられるタイミングじゃなかった。馬鹿かと。)その場合、プロセス毎に読ませるファイルを変えたい場合には、システムプロパティ(もしくは環境変数)経由でブートストラップとなる設定値(主に設定ファイル群がどこのディレクトリに集められているか)をAPに渡し、それ用いて読み込む設定ファイルのフルパスを確定し、実際の設定ファイルをAPに読み込ませる。springの場合は、そんなダサいケースでも楽出来るが、自作の場合は泣きたくなる。

設定値設計のレビュータイミング

ソースコードはレビューしても、設定値をレビューしていないPJをたまに見かける。馬鹿かと。
設定値が関わるレビュータイミングは大きく3回ある。1回目は、設定値のキー設計時。これは、APからどういう設定値を外だしするかというレビューになり、APの内部設計と合わせて実施し、ファイル構成は意識せず、論理名で設定項目の外だし妥当性と変更タイミングについて議論する。2回目は、設定項目の実装フェーズで、設定項目のファイル配置、物理名、ネスト関係を議論する。合わせて、APのソースコードRV時に、正しい設定項目を読み込んでいるかも合わせてレビューする。3回目は主に環境差分反映時だ。開発環境、検証環境、本番環境等のリリースタイミングで、環境差異のある設定値が正しく設定されているかをレビューする。

おわり

疲れたので、ここで終わります。
昔、サーバごとに設定値どころか設定項目を変えられないという凄いPJに出くわしたことがあり、設定値設計というものに少しでも光が当たるよう、勢いで書いてしまいました。