設定ファイルとプログラム

設定ファイル用組み込み言語 Lua

d.y.d経由でLL3のメモLuaの話が非常に面白かった。

この人 (Robertoさん) が最初に Lua をつくったのはじつは「設定ファイル用の言語として」だったという。 ".なんとかrc" 形式のファイルには非常に多くの書式があり、その多くはちっとも統一されていない。 (中略) Lua が作られたのはまさにこういう状況であって、彼は「どうせならいっそのこと設定ファイル記述専用に、まともな文法をもった、コンパクトな組み込み用の full-blown 言語をつくっちまおう」と考えたのだという。

LuaJavaScriptに似ているなあというところで理解が止まっているので、今後ちゃんと勉強しておきたいと思っている。

「設定」ファイルとしてのXML

それで、その後のXMLについてのコメントも面白い。

しかし設定ファイル業界(?)にはその後「XML馬鹿」というまったく新しいタイプの強力なアホ集団があらわれ、こいつらがゴミをまきちらかしている。

確かにまき散らしていると思う。

XMLになってから共通パーサーが提供されて、誰でもいくらでも複雑なツリー構造のデータを簡単に読み込めるようになったことが一つのきっかけなんだと思う。単に構造を持った設定を表現する道具として使うだけではなく、Javaで硬いコンポーネントを用意してXMLでつなげるという方法が登場(推奨?)して、プログラムがXMLに移動してきた。そして、「設定ファイル」という名のプログラムが大氾濫してきた。

このようなXMLファイルに設定や設計情報を書くようなブームについて振り返ってみて、より良い設定ファイルとは何かについて考えてみる。

プログラムをXMLで書くメリット

XMLならではというのは、標準化されているということ。パーサーも多数提供されているし、品質も非常に高い。周辺技術もかなり成熟しているため、「XMLを使った何か」が非常に作りやすくなっている。パーサーより後の工程は頑張る必要があるのだけども、少なくともシンタックスではない点では、書くほうにとっても多少都合はよい。

次に、よく言われるのがコンパイルがいらないこと。ただ、Eclipseで開発したりするとコンパイルは自動でやってくれるし、一方で設定変更を確実に行うためにはアプリケーションサーバーの再起動が必要になるので、個人的にはあんまりこのメリットは無かったように思う。そもそも、このメリットはXMLでなくても良いし。

後でXMLで組み立てやすいように設計の抽象レベルが上がって、部品化が積極的に行われてきたと思う。ただ、これは副作用になるのかもしれない。

プログラムをXMLで書くデメリット

まず、XMLというシンタックス。もともとマークアップ用だったので、こんなにタグだらけになることは想定されてなかったのではないかなと。XMLで出来たプログラムや複雑な設定ファイルは、見るのも読むのも辛い。将来はGUIになるからとバラ色の未来が言われ続けてきたのだけども、仕組み的にGUIにしやすいとはいえ、使いやすいGUIはあまり見かけたことが無かった。

次に、ノードを解釈するインタプリタの能力がばらばらという問題がある。大抵はDTDに基づく形式的なチェックで、RELAXなどを使った積極的な内容に対する型チェックはほとんど無い。また、エラーは動作時に発生するのでエラーが出ても何が原因か分かりにくい。

さらに、スコープや、依存関係の解決、動作制御などのシンタックスに依存しないインタプリタ自体の言語能力も貧弱であることが多い。特に、SAXイベントの段階で最終的な解釈までやってしまうのは、プログラム言語としては多少能力不足では無いかと思う。

デメリットは、要するにXMLを手で書くプログラム言語として見たときの問題点なので、結局Luaなどの組み込みスクリプト言語にさせるべきであるという結論になる。組み込み言語にしてしまえば、書きやすく、読みやすく、言語としてもパワフルで、利用アプリケーションから見てもXMLと同じ程度の使いやすさになるはず。

現状を移行するのならそういう結論で良いと思う。ただ、さらに根の深い設計上の問題がその付近にはあるのではないかと思っている。現在の「設定ファイル」の複雑さの原因はどこにあるのか、設定とプログラムの関係について、もうすこし考察してみる。

設定とプログラムの境界

上では、プログラムはXMLではなくてプログラム言語で書くべきだという結論に至った。そこで、プログラムと設定の境界はどこにあるのか。どんな内容だったら設定ファイルで、どんな内容だったらプログラムであると言えるのかはっきりさせたい。

よく言われるのが、環境によって変化するような情報は設定としてプログラムから分離しようということ。DBの接続情報とかサーバーの場所、ディレクトリなどのリソース情報や、ログの動作、テスト時やリリース時の動作の切り替えなどの動作、さらには汎用的な部品などの組み合わせや、画面遷移なども設定と呼んだりする。後半はフレームワークとしてから見れば「設定」ではあるが、サイトごとにはプログラムと同じレベルの固有の情報が入るのでプログラムの一部であると見なすことが出来る。ということで、「環境によって変化する」などの変化のしやすさでは分けることが難しい。

一般のプログラム言語が持っているような特徴があるかどうかで分けるという方法もあるかもしれない。たとえば、スコープとか、条件分岐、ループなどの制御構造を備えていればプログラムとして見なせる。しかしながら、ほとんどのフレームワークXML設定ファイルは、まともな制御構文を持っていない。また、逆にRubyなどのスクリプト言語は、DSLとして評価したり、設定ファイルをそのまま load したり eval したりするので、言語の力を生かした省力化が出来る。このような高度なことが出来てもいいと思うので、設定ファイルの言語の能力でプログラムかそうでないかを分けるのは難しそう。

個人的にこれだと思う分け方は、設定ファイルを扱う人や目的で分けるという方法ではないかと。普通の人が設定ファイルに期待することは、設定対象がブラックボックスとして完全に隠蔽されていて、実装を知らなくても動作を変更できるというものなのだと思う。たとえば、struts-config.xml や dicon ファイルは、アクションやコンポーネントの実装を知らなくてはならないという点で、プログラムの一部であって設定ファイルではない。tomcat の server.xmlapachehttpd.conf は、非常に複雑ではあるが設定対象をブラックボックスとして扱える(ことになっている)ので、設定ファイルであるといえる。

ということで、プログラムの実装に関わってくるような「設定」はプログラムの一部だといえるので、プログラムで書けた方がうれしいに違いない。一方で、設定対象をブラックボックスとして設定ファイルを設計することで、設定ファイルを触る人が知らなければならない情報を減らすことが出来る。知らなければならない情報を減らすと、学習コストが下がったり、結局本質的な設定項目だけ残ることになり、設定ファイルが分かりやすくなるはずだと思う。

あとは、誰がブラックボックスだと思うかという部分を詰める必要があるかもしれない。

ちなみに、この利用者のことを意識するという切り口はいろいろな設計の場面で重要なのではないかと思う。少なくとも「使う人へのやさしさ」を考えるのであれば、アプリケーションやフレームワークの設計において、利用者の視点やスキルの仮定は外せない。単なる抽象化や省力化の結果として設定ファイルというものが出てくるのではなくて、どうやったら楽になるか、普通のプログラマが躓いているところはどこかということに注意を払う必要がある。

プログラムの一部としての設定

最後にフレームワークにおける「プログラムの一部としての設定」についての考え。

最近のフレームワークの複雑さはこの設定ファイルにあると思っている。フレームワークを使うことで抽象度を上げることが求めらるだけでなく、さらに新しいフォーマットのファイルを書いたり、その内容とプログラムとの連携が求められる。この技術ギャップは大きく、フレームワーク導入や乗換えの障害になるだけでなく、Webプログラマのレベルアップにとっても超えにくい壁になっているように思われる。

ただこのあたりはフレームワーク全体の設計思想に左右されたり、まだまだ全力で研究されているように思うので、これという答えはまだまだ出てきていないと思っている。自分の中でもまだ意見が固まっていない。もう少し研究してみて、議論のポイントでもまとまったら後で書くかも。

今のところ確かなところは以下のような感じ。

  • 中途半端な俺言語は覚えたくも無いし書きたくないが、普通のちゃんとした言語で必要なプログラムは書くことはやぶさかではない。
  • プログラムが分かりやすく抽象化されてそれが規約として普遍的になって、全体として書く量が減るようなものなら、それは歓迎であることですよ。

先の勉強会では、一般的なWeb開発とフレームワークについて「状態が切れすぎ」「状態をつなげるのに多大な苦労が行われている」「その結果かどうか知らないが設定が多い」という問題提起をして、継続を使ったWebフレームワークについて紹介した。上の新山さんのところにも継続とWebについて書いてあって、まさに今そんなフレームワークを開発中。JavaScriptでサーバーのプログラムを書いているので、現在継続中のコンテキストにアクセスして値を取ってくるとか書き換えるとかだけでなくて、動作中のプログラムの関数を書き換えたり追加したり、そうやって動作確認できた関数やコンテキストを toSource() して保存したりとやりたい放題。表に出せそうな状況になったら公開してみたいかなと。

書きたいことはたくさんあったのだけども、うまくまとまらない・・・。