ソフトウェアの設計は、静的構造と動的構造の二つの視点で図面化することが大切です。今回は、動的構造の典型的な課題と設計原則を紹介します。

動的構造とは、リアルタイムOS上のタスク設計、LinuxやJava環境のスレッド設計、OSを使わないタイマー駆動設計、及び、メインルールのモニタ設計、が相当します。動的構造の設計では、タイミングに関わる、パフォーマンスや同期を考慮することになります。動的構造の設計を失敗すると、再現性の低いバグが発生したり、入力に対する応答性が低下したり、ちょっとした修正で思わぬ副作用を引き起こしたりする現象が発生します。

■制御スレッドの寄り道

イベントの入力に応じて制御スレッドが走り始めて、途中で特定のイベントを待つことが問題を引き起こします。途中で特定のイベントと待ち合わせすることで、そのイベントを受け取るまで他の処理ができません(スループットの低下)。そして、イベントの順番が変わると、とたんに動かなくなってしまいます(再現性の低いバグの原因)。途中で待っている箇所に、他のイベント待ちを追加すると、プログラムの複雑さを増していきます(スパゲティ化)。

スレッドベースのアーキテクチャで、イベント応答性の高いソフトウェアを作ろうとすると、パフォーマンスが低下するのも、これが原因です。

設計原則としては「走り切り」です。制御スレッドが始まったら、途中で待たずに、処理を「走り切る」で作り、すぐに次のイベント待ち状態に戻る設計です。このためには、イベントの受け口で、状態遷移表を作り、アクションを走り切りで実装する、という設計ルールになります。

■フラグの裏取引

特定の場所で状態を覚えておくためにフラグを立てて、他の箇所でそのフラグに応じて処理を変える、という構造も品質低下の原因です。明示的なインタフェースになっていない場合が多く「裏取引」と呼んでいます。アドホックなフラグの多用は、あとで、その関係が見えなくなってしまうので、予想しない副作用が発生し、なかなかバグが収束しないという現象にもつながってしまいます。

設計原則としては「状態変数」にまとめることです。そして、状態とイベントの組合せを状態遷移表として管理することで、厳密な設計ができます。複数のフラグを、意味のある状態変数へまとめることが大切です。状態変数を中心にモジュール化することで、凝集度の高い堅牢な設計になります。