典型的なソフトウェア劣化パターン6種類
続いてインディ氏は、ソフトウェアの劣化について話を向けた。ソフトウェアの劣化は、開発プロジェクトでよく見られる現象であり、新製品の開発時にはソースコードが比較的シンプルであり、正しいアーキテクチャを持ち、複雑化していないため容易に理解できる。しかし、機能の追加が進むにつれて複雑度が増し、設計が急速に複雑化し、人間が理解しづらい状態に陥る。すると、新たな機能の追加、エラーの修正、バグ修正のコストが大幅に増加する。これにより、計画された製品ライフサイクルが終わる前に製品の維持が困難となってしまう。
ソフトウェアコードの複雑さや複雑度が発生する背景には、複数の劣化の種類が存在する。インディ氏は、自動車のダッシュボードに温度を表示するシステムを例に紹介した。センサーが温度を摂氏で測定し、その後で単位の変換を行い、ダッシュボードのディスプレイに表示される仕組みだ。
単位の変換で、欧州向けは摂氏そのまま、米国向けには華氏にする処理が必要というアーキテクチャだったとする。しかしその間に展示会に出展することになり、時間的制約から摂氏から華氏への単位変換の処理が省略されてしまった。センサーの値がそのままダッシュボードに表示されるようなアーキテクチャ違反・隠れ依存性となった。
展示会には問題なかったものの、この違反を放置して米国向けに出荷する際に華氏への変換が行われないまま出荷されたとする。その場合、摂氏30度が華氏30度(摂氏-1.1度)と判断され「路面凍結注意」という不適切なアラートが表示されるような事態が発生する可能性がある。
インディ氏は、「アーキテクチャ違反・隠れ依存性を防ぐにはアーキテクチャ図を描き、その後の実装をこのアーキテクチャと比較する検証作業が必要」と説明した。解析ツールを用いれば、先のような単位変換が省略された違反が発見でき、適切な対処が可能となる。
アーキテクチャ違反に対処するため、検証をせずに急場しのぎで既存コードのコピー&ペーストによる修正を行った場合、更なる劣化が発生し、アーキテクチャ違反だけでなく、冗長な処理が複数の場所に点在する隠れた依存関係が生じてしまう可能性もある。これは、「コードクローン」と呼ばれる、ある場所で正しく動作している処理を別の場所でも利用する行為によるソフトウェアの劣化だ。
コードクローン自体は悪いことではないが、バグが発生した際に影響する範囲が広くなることが問題だ。複数の箇所で同じようなバグレポートが生じ、複数回の修正を必要とすることになる。このような状況は、そもそもコピー&ペーストを行わないか、行った場合でもどこで同じ処理が使われているかを把握してクローンを管理するシステムを利用することで対処できる。
続いてインディ氏はスタイル違反によるソフトウェア劣化について説明した。
#define Square(x) x*x
というC++コードに対して
Square(5) = Square(2+3) =
と、一見結果が同じになるような引数を与えた2つの式を提示した。
5を引数にする場合、「5*5=25」となるが、2+3を引数にすると「2+3*2+3=11」となってしまう。
これはスタイル違反であり、バグではないものの混乱が生じる原因になる。対処するには、以下のように正しい括弧の使用を要求するコーディング規約を定義し、使用する。
#define Square(x) ((x)*(x))
インディ氏は、典型的なソフトウェア劣化の種類は、前述したアーキテクチャ違反・隠れ依存性、コードクローン、スタイル違反のほかに3つあるとした。ファイル内に大量のコード行が存在する場合や、関数のネストレベルが多い場合に生じるメトリクス違反、記述されているが使用されていない処理であるデッドコード、関数およびモジュール間の循環依存だ。これら6種類の劣化に対処することで、ソースコードを元の清潔な状態に復元する、あるいは少なくともさらなる劣化を防ぎたい。