Entry

GUI ライブラリの設計思想とか

2011年10月20日

Windows 上で GUI の簡単なツールを作るときは,MFC やら Qt やら GTK やらは使わずに,Win32 API を直接叩いて作っているんだけれども,毎回書くことになる同じ処理はライブラリにまとめていたりします。

で,せっかく作っているから,もう少しライブラリとして体裁を整えようとも思っているもんで,参考までに他のソースをボチボチ読んでいます。そこで思ったこと。

MFC や Qt を読んでいて思うんだけれども,C/C++ の文法的にどうとかとか,書きやすい/書きにくいとかいった話ではなく,機能的な意味を表現する階層が随分と薄いなぁとか思ったりします。

「機能的な意味を表現する階層」が「薄い」というのは,例えば,メニューから「ファイルを開く」を選んだときの挙動を実装する場合,CWnd 的なウィンドウ一般の基底クラスから派生した自前のクラスに対して,OnFileOpen 的なコールバック関数を用意するなり,基底からのメンバ関数をオーバーライドして作ることになるけれど,これが薄いと思うわけです。「ファイルを開く」といった機能は,プログラムの根幹的な動作のひとつなわけだけれども,それすら(クラスではなく)関数として実装されている点が「薄い」と思う。もすこし実装寄りの表現をすると,プログラムの処理単位をそれ以上細かく分割することが難しいということです。

もちろん,これらの薄い関数から他のクラスに委譲すれば,処理単位を広げることができるわけで,多くの経験者さんはそのように実装していると思います(UI と処理の本体を分離させるため)。しかし,それだったら,直接クラスにディスパッチする機構をライブラリ内部に作った方がいい。どうせ委譲するのに冗長なので。

これは結局設計思想の話になってしまうので,何が正しいとかいった話ではないと思うんだけれども,例えば,MFC の例を挙げるならば,UI 上で「『ファイルを開く』ボタンをクリックする」ということは,「ファイルを開く機能を呼び出す」ことと直接的な必然性がない。ボタンを押すとファイル選択ダイアログが出て選択したファイルを開く機能は,間接的に ID_FILE_OPEN 的な定数(ウィンドウメッセージでもいい)を渡しているという事実のみによって実現されています。そして,この定数に「ファイルを開く」という意味を与えるのは,ライブラリの利用者だったりする。なんなら,この ID が来たときに,利用者はファイルを削除するように実装することもできる。「間接的に」というのはそういう意味です。このように,たかが定数が,その UI の機能にまつわる唯一のよすがとして取り扱われている点がまず薄く,この定数を足がかりにしてディスパッチされる先が,一介の関数に過ぎないという点も薄い。

仮に,ファイルを開くクラスがあるなら,そのオブジェクトに対して直接ディスパッチするのが(オブジェクト指向的には)自然な気がするんだけれども,どうなんだろう。

……と,思いつつ,実際に直接ディスパッチするクラスを実験的に作ってみたんだけれども,これがなかなか難しい。ゴリゴリの GoF に擦り寄って作るとすると,Command パターンでメッセージクラスを構成して,こいつを Visitor パターンやらで受け付け,さらに Chain Of Responsibility パターンで子クラス(ウィンドウとか UI とか)に回すような塩梅になるのだと思う。元の API をあまり見せたくないので,pImpl も併用して,公開クラスは主にインターフェイスのみになるんだろうな,多分。

ま,ソース読んでてちょっと思っただけ。UI 上のアクションとアプリケーションの機能そのものは別モノで,両者を結びつけるのがプログラマ(ライブラリの利用者)だと考えると,それ以前にやることが多すぎるなと思ったり,思わなかったり。ま,ただそれだけ。

Trackback
Trackback URL:
Ads
About
Search This Site
Ads
Categories
Recent Entries
Log Archive
Syndicate This Site
Info.
クリエイティブ・コモンズ・ライセンス
Movable Type 3.36
Valid XHTML 1.1!
Valid CSS!
ブログタイムズ

© 2003-2012 AIAN