まず、プログラマが自分の作ったソフトウェアについて誰かに聞かれたとき、あのモジュールのあの関数の部分とパッと頭の中に浮かぶソフトウェアの規模はだいたい5000行くらい、そして一人のソフトウェアエンジニアがソースコードだけで保守できる範囲はせいぜい10000行くらいとのこと。また、プロジェクトチームは人数が増えてきたらチームリーダを含めた一チーム6人に分割し、プロジェクト全体では最大5~6チーム以上にはしないようにした方がよいだろうという話だった。これを超えるようならプロジェクト自体を分割して別々のプロジェクトになるようにマネージメントした方がよいのだそうだ。
井上さんの話から、プログラマのソースコードレベルでの守備範囲が10000行だとすると、1プロジェクトの限界が30人で30万行となり、冒頭の30人、30万行の話を符合する。30人、30万行の指標はソースコードレベルで把握できるレベルの限界であるというのは、ソフトウェアエンジニアの管理限界の平均値に近いのだろう。
ちなみに、プロジェクトメンバの数は簡単に数えられるが、ソフトウェアのコードの規模としてコード行数を数えるのはそれほど簡単ではない。自分の中ではソースコードの行数と言えば、コメント行や宣言文を除いた実行コード行数ということになる。実行コード行数を目視でカウントするのはあまり現実的ではない。そうなると何らかのツールを使わないとある程度正確なカウントができない。でもツールがないからといってコード行数をカウントしないとソフトウェアシステムの規模が把握できない。組込みソフトの場合、実機にアップロードするときのコードサイズをソフトウェア規模の指標にする場合もあるが、プログラミングをソフトウェアエンジニアの文章書き作業だと考えると、ソフトウェアの複雑性を計る意味ではプログラムサイズよりも実行コード行数の方が実態に近いのではないかと思う。
もしも、実行コード行数を計るツールを持っていない場合は、C,C++,java,htmlプログラムの行数を計算する C&C というフリーツールがあるので参考にしてはどうかと思う。(このツールはSESSAMEメンバーの國方さんに教えてもらった。このブログでツールを使うときは宣伝文句に惑わされるなといったことを何回も書いているが、できるエンジニアは大抵いくつかのツールを上手に使いこなしている。常にアンテナを張っているので、ツールの選び方も上手い。)
さて、30人、30万行の規模に達していないプロジェクトは何もしなくてよいのだろうか。それは、もちろんそうではない。ソフトウェアの規模が徐々に拡大して何の危機感も感じることなく試行錯誤的なアプローチで30人、30万行の規模に達してしまったら、もう身動き取れないし、その状態からソフトウェアの構造やプロジェクトを立て直すのは相当大変だと思う。
感覚的には10人、10万行くらいの規模に達したら、何かしないとまずいと感じないといけないし、その時点から対策を打っていけば、30人、30万行に達したときでも破綻することはないと予想する。そもそも組込みソフトでゼロからスクラッチで作ることはないので、一回の開発で作るソフトウェアの量はそんなに多くないと思っていると、いつの日か痛い目にあうときがくる。もともと先々のことまでよく考えずにスクラッチでソフトウェアを作っていると CPUやOSが変わったとたんに、これまで作ったソフトウェアのいろんなところに手を入れないといけなくなる。結果的にスクラッチでゼロから作り直したのと同じぐらいの時間がかかってしまうこともある。
さて、そうなると最初に考えるべきはソフトウェアシステムをどのように分割すべきかということだ。ソフトウェアシステムのモジュール分割については30年以上も前から不文律がある。それは「システム分割に際しては分割したモジュールを高凝集、疎結合にすべし」という考え方だ。
【凝集の種類】 (数字が大きくなる方がよいとされる)組込みシステムでよく見られるのは、3の時間的凝集を意識したモジュール分割だ。リアルタイム性を重視する余り、10ms毎、100ms毎、1秒毎に起動するモジュールといった感じで時間的な視点のみでモジュールを分割する。リアルタイム性が非常に強いシステムでは当然時間的凝集を意識したモジュール分割も必要だが、ソフトウェアシステムが巨大化した場合は、時間的凝集や手順的凝集だけを意識していると移植性や保守性、再利用性が悪くなる。※参考文献:平成16年度 ソフトウェア開発技術者合格教本 ISBN4-7741-1882-6
- 暗号的凝集度 プログラムを単純に分割しただけで、モジュールの機能を定義できない。または、複数の機能をあわせもつが、機能間にまったく関連はない。
- 論理的凝集度 関連した複数の機能をもち、モジュールが呼び出されるときの引数(機能コード)で、モジュール内の1つの機能が選択、実行される。
- 時間的凝集度 初期設定や終了設定モジュールのように、特定の時期に実行する機能をまとめたモジュール。モジュール内の機能間にあまり関連はない。
- 手順的凝集度 複数の逐次的に実行する機能をまとめたモジュール。
- 連絡的凝集度 手順的凝集度のうち、モジュール内の機能間にデータの関連性があるモジュール。
- 情報的凝集度 同一のデータ構造や資源を扱う機能を1つにまとめ、機能ごとに入口点と出口点をもつモジュール。
- 機能的凝集度 1つの機能だけからなるモジュール。
巨大化したソフトウェアシステムに立ち向かうには、機能的凝集の考え方が必要であり、責務ごとにモジュールを分割する必要がある。システム全体を責務に分割し、機能的凝集に成功すると分割したモジュールの内部でやっていることについて、モジュールの外部は意識する必要がなくなり、そのモジュールが外部に対して公開しているサービスについてのみ考えればよくなる。ようするにシステムの上位層から見たときにモジュール内部の(不要な)データや処理を隠蔽していかないと、システム全体を把握することが難しくなる。人間が一度に把握できる構造には限界があるので階層的にソフトウェアシステムを眺めていくには、機能的凝集のモジュール分割、責務に基づいたモジュール分割が必要になる。
このようなモジュール分割の考え方は、ビジネス系でオブジェクト指向設計を行う際には普通に行われていると思うが、組込み系のシステムで制約条件のことに考慮せずに機能的凝集のことだけ考えてモジュール分割を行っていると、リアルタイム性やメモリ容量、CPUパフォーマンスをクリアできない場合もあるから注意が必要だ。だから、『組込みソフトエンジニアを極める』では、第1章で時間分割のハードルを越える 第2章で機能分割のハードルを越える といった順番で、時間分割、機能分割の考え方を書いた。
だから10万行を超えた組込みソフトウェアシステムでは、いろいろな凝集についての考え方があることをきちんと理解しながら、トップダウンの視点(機能分割)とボトムアップの視点(時間分割)の両方の視点でシステムを眺めることが大事だ。組込みソフトエンジニアは機能分割と時間分割の最良のバランスポイントを見つけなければいけない。
次に、結合の種類 6種類を挙げておく。ちなみに、この分類は最初に提唱したのは、G.J. マイヤーズだと思う。
【結合の種類】 (数字が大きくなる方がよいとされる)G.J. マイヤーズがこの6つの結合を分類したのは30年以上前のことだ。だから、この結合の分類はC言語ならば関数と関数の結合といった関係のことしか書かれていない。オブジェクト指向設計で考慮の対象になる、結合の方向性(結合の方向性は一方向にした方が結合度が低い)については考えられていない。※参考文献:平成16年度 ソフトウェア開発技術者合格教本 ISBN4-7741-1882-6
- 内容結合 絶対番地を用いて直接相手モジュールを参照したり、相手モジュールに直接分岐する。
- 共有結合 共通領域(グローバル領域)に定義されたデータを参照する。
- 外部結合 必要なデータだけを外部宣言し、ほかのモジュールから参照を許可し共有する。
- 制御結合 機能コードなど、モジュールを制御する要素を引数として相手モジュールに渡し、モジュールの機能や実行を制御する。モジュール凝集度の論理的凝集度がこれに相当する。
- スタンプ結合 相手モジュールで、構造体データ(レコード)の一部を使用する場合でも、構造体データすべてを引数として相手モジュールに渡す。
- データ結合 相手モジュールをブラックボックスとして扱い、必要なデータだけを引数として渡す。
何はともあれ、巨大化してしまったソフトウェアシステムは何らかの視点でシステムを分割していかないとすぐに手に負えなくなる。何らかの視点の何らかの部分は組織や商品やプロジェクトによって異なるのだか、多くの場合は機能的な分割をベースに、時間的分割を考慮する方法がセオリーになると思われる。
また、データの取り扱いが重要とされるシステムでは、プレゼンテーションレイヤー、ドメインレイヤー、データソースレイヤーといったレイヤリングの分割視点が有効な場合もある。
さらに、商品に求められる価値をQFD(品質機能展開)で分析して、その要求・価値を実現する機能や性能をモジュールとして括りだすという視点もある。
どっちにしても、大規模・複雑化した組込みソフトウェアシステムでは、どんな視点でシステムを分割するかといった戦略(=アーキテクチャ)が、製品の開発を効率化し、信頼性や安全性を高めるカギとなるのは間違いない。
0 件のコメント:
コメントを投稿