コンポーネント設計

引き続き、新エンジンを開発しています。状態遷移やコンテキストの管理など細かい部分の実装は一段落したので、エンジンを包み込むコンポーネント部分の抽象化を考えてみました。まず、アプリケーションとコンポーネントの関係をおさらいしておきます。


アプリケーションを起動すると、対応するコンポーネントインスタンスが作成されます。コンポーネントには全ての処理の入口である『エントリポイント』が必要で、Text Service Manager から送出されるイベントを受信すると、適切なコンポーネント関数を呼び出すことになります。鉛筆メニューの構築・イベントハンドリングもコンポーネントの責任です。


アプリケーションから文書を開く、あるいは、新規作成すると「セッションが必要だ」というイベントが飛んできます。そこで、必要なセッションを生成します。文書への入力イベントは対応するセッションによって処理されます。文書を閉じると「セッションは不要になった」というイベントが飛ぶので、該当セッションを破棄します。


アプリケーションを終了すると、対応するコンポーネントインスタンスも破棄されます。このタイミングで、鉛筆メニューなどの各種リソースを片付ける必要があります。ちょっとややこしいので、図にしてみました。


http://aquaskk.sourceforge.jp/images/overview.png


では、「概念をクラスとして表現せよ」というスローガンに従いながら進めてみます。まずエントリポイントですが、ここでは Universal Procedure Pointer という古の黒魔術を使うことになるので、C++ のクラスにはできません。そこで、単純な振り分け関数として独立させておくことにします。振り分け後の実質的な処理は、コンポーネントクラス(薄いブルー)としてカプセル化できます。アプリケーションとコンポーネントの関係は一対一なので、コンポーネントクラスは Singleton です。コンポーネントクラスのコンストラクタとデストラクタで鉛筆メニューの構築と破棄ができそうですね。


次に、文書と対応するセッション部分(濃いブルー)もクラスとして分離します。自然とコンポーネントクラスは、セッションのインスタンスを管理するコンテナクラスになります。各セッションではエンジンクラスのインスタンスを保持するわけです。簡単ですが、これで良さそうです。クラス図も更新してみました。


http://aquaskk.sourceforge.jp/images/class_diagram3.png



SKKFrontEnd が Session を「使う」のは「入力エリアの表示更新」が Session のメソッドとして実装されているためです。この関連は違和感があるかもしれません。本当にこうする必要があるのかどうか、もう少し検討したいと思ってます。


なにはともあれ、全体的な整理はほぼ終了した気がします。クラスの数が増えてラビオリ気味な感もありますが、AquaSKK の実装に『必要な複雑さ』としては、まあ許容範囲かなぁと。あと一ヶ月ぐらい作業すれば、アルファ版を出せそうです。