Windows Vista時代の防衛的なWindows Formsプログラミング

大げさな標題になってしまった。ようは今まで、そしてこれからも暫くは作り続けていくであろうWindows Formsアプリケーションを、今後Windows Vistaが普及して行く中でどうしていこうかということだ。
Windows Vista以降のGUIプログラミングの主流はWPF(Windows Presentation Framework)と呼ばれる技術、具体的にはXAMLと呼ばれるマークアップで記述されたGUIと.NETプログラミング言語で書かれたコードビハインドの組み合わせがメインストリームであり、古のWindows FormsはGDI(GDI+)とともに衰退していく運命なのは既定路線だ。(個人的には現在のWPFには未だ懐疑的だ -> Beyond WindowsForms?)
このような端境の中でWindowsForms等のGDIアーキテクチャを用いたGUIアプリケーションはどのような事に気をつけて書き、保守していくべきだろうか?(ASP.NETユーザは気にしなくても良いだろう。同様にWPF/EやXBAP(XAML Browser Application)はASP.NETをリプレースするポジションでは無いと思われる)

GUIプログラミングを生業としてきた経験から書くが、これに関しては特別な配慮は必要無いし特効薬も無い。とにかくプレゼンテーションレイヤ、つまりGUIとその記述に関する部分は今のうちにコード(ロジック)とできるだけ分離するように癖を付けておくことである。
例えばWindows Formsアプリケーションを書く際に、デザイナを使ってフォームの上に貼り付けたボタンのクリックイベントで処理を実行するコードを書くとしよう。具体的にはVisual Studio 2005でボタンコントロールのクリックイベントを選択してプレースホルダに処理を記述するのが極めて一般的だろう。

private void button1_Click(object sender, EventArgs e)
{
    //ボタンが押下された際に動作するロジック、又はロジックを呼び出すコードを記述
    〜
}

昔々はこれでも良かったが、今の私にはこれはまずい書き方だ。

GUIプログラミングで犯し易い誤解はGUI(フォーム及びコントロール)をコードの主体にしてしまうことである。本来はロジックがプログラムコードの主体であり実際そのように書くべきだ。具体的にはイベントハンドラにコードを書くのでは無く、コードにGUIのイベントを接続するように書く。
この方法の実現方法はいろいろあるが、私が実現した方法に関しては以前のエントリに詳しく書いたのでここでは省略する。
Controlのイベントに動的に処理をアタッチする
GUIプログラミングに関しては、何時だったかどこかに「デザイナが吐いたコード以外はできるだけ書くな」という事が書いてあった気がするが、この考え方はこれとは全く反対であり「できるだけデザイナが吐いたコードを使うな」ということである。(全ては無理だが、デザイナにロックインされたコードをできるだけ減らしておきたいのだ)

例えば、プレゼンテーションレイヤをWindowsFormsからWPF(XAML)に変更することを考えてみよう。イベントハンドラに長々と書いたコードはコピペはできるが全ては記述し直しだろう。
前述した方法であれば、予めGUIと分離しておいたロジックはWPFに変わってもそのまま使えるし、コントローラであるアクション(IAction)とイベントの接続部分も最小限の修正で済むことだろう。(WindowsFormsのイベントの基本形は、EventHandlerデリゲートを用いたコントロール単位に発生するイベント処理だが、XAMLはEventHandlerを継承したRoutedEventHandlerデリゲートを用いており、イベントはコントロール階層を遡るイベントバブリングが採用されている)
先日言及したQtもこのようなGUIを分離する考え方がフレームワークに組み込まれている。シグナルとスロットの考え方がそれであり、GUI側で発生するイベント(シグナル)と他のクラス(ロジック)を綺麗に分離することが可能になっている。

もっともQtのシグナルとスロットはGUIプログラミングに限ったことではなく、オブザバパターンやオブジェクト間通信をスマートに且つ安全に実装する為の仕組みであり、ルートクラスからこの仕組みを利用することができる。
Qt - Signals and Slots
ロスプラットホームであることを最初から意識しているからか、この辺の分離を無意識に強制させるための設計は見事だと思う。