ソフトウェア品質(ソフトウェアひんしつ、英: Software quality)は、ソフトウェアの品質を指し、プログラマの観点からはソースコードの品質、エンドユーザーの観点からはアプリケーションソフトウェアの品質を意味する。

ソフトウェア品質の定義は様々である。ジェラルド・ワインバーグは著書 Quality Software Management: Systems Thinking v. 1 で「品質とは誰かにとっての価値である」と書いている。この定義は品質が本来主観的なものであることを強調している。同じソフトウェアであっても人によって品質の感じ方は全く異なる。この定義の利点は、ソフトウェア開発チームに「このソフトウェアは誰のために作っているのか?」とか「彼らにとって価値とは何か?」といった疑問を抱かせる点にある。

品質を「目的への適合性」と定義する場合、品質を測定するのに使うべき尺度(属性)を決定する際に、そのソフトウェアの目的を考慮する必要があることを意味する。

## 概要

### ソフトウェア製品品質

- 商品品質
  - 要求仕様やプログラム仕様への適合性(後述する「ソフトウェアの信頼性」に関連する)
- スケーラビリティ
  - 正当性
- 完全性
- バグが無いこと
- フォールトトレラントシステム
  - 拡張性
  - 保守性
- ソフトウェアドキュメンテーション

### ソースコード品質

コンピュータにとっては、きれいに書かれたソースコードという概念には意味が無い。しかし人間にとっては、プログラムがどう書かれているかはそれを保守する際に重要な意味を持つ。様々なプログラミング作法は、可読性や言語固有の規約を強調してソースコードの保守性を向上させ、デバッグや修正を容易にする。他にもうまく書かれたコードという概念には、コードが管理可能な部分に論理的に分割されていることなども含まれる。

- 可読性
- ソフトウェア保守、ソフトウェアテスト、デバッグ、バグ修正、改造、移植の容易性
- 複雑すぎないこと
- リソース(記憶装置、CPU)を過度に必要としないこと
- コンパイルやlintでの警告数
- 適切なコメント

品質向上の手法: リファクタリング

### CLEAN

デビッド・スコット・バーンスタインは、レガシーコードからの脱却で良いソフトウェアの土台となる5つのコード品質として以下を挙げ、CLEANと名付けている。

- Cohesive(凝集性):特性が明確に定義されているべき
- Loosely Coupled(疎結合):はっきりした責務を担うべき
- Encapsulated(カプセル化):実装は隠蔽されるべき
- Assertive(断定的):オブジェクトの状態は自分自身が管理すべき
- Nonredundant(非冗長)オブジェクトの定義は一度だけにすべき

## ソフトウェアの信頼性

ソフトウェアの信頼性(reliability)は、ソフトウェア品質を測る重要な尺度であり観点である。品質(quality)という用語には主観的(定性的)要素が含まれるが、ソフトウェアの信頼性は客観的な基準で測定可能である。このような測定基準を一般にソフトウェアメトリックと呼ぶ。ソフトウェアの信頼性改善の実際の作業は、ソフトウェア開発を扱いやすく理解可能なものにするという圧力によってなされてきたもので、収益を求めてのものではない。しかし、ソフトウェア産業の成熟と共に、ユーザーがソフトウェア製品に期待する品質レベルは高くなり、信頼性の確保が収益に繋がるという状況ができつつある。

組み込みシステムでは、ソフトウェアの問題は単なる不便以上の問題を生じる。場合によっては人命にも関わる。その原因はユーザインタフェースの貧弱さから直接的なバグまで様々である。多くの人命に関わったプログラムのバグについては、Levenson の論文 Medical Devices: The Therac-25 に詳しい。結果として、ソフトウェアの信頼性に関する要求仕様が生まれた。アメリカ合衆国では、アメリカ食品医薬品局 (FDA) と連邦航空局 (FAA) がソフトウェア開発についてその種の要求仕様を策定している。

### 信頼性の目標

現代の工学分野の技術をソフトウェア開発に適用するため、ソフトウェアの品質を客観的に判断する方法が必要とされる。これは、誰が見てもコンピュータソフトウェアは予定通りの動作をしないという一般的観測結果に基づいた動機である。言い換えれば、ソフトウェアは何らかの問題を抱えていると不適当な動作を見せる。その原因は処理中のデータの問題だったり、ソフトウェアが動作するハードウェアの問題だったり、操作者などがそのマシンに悪影響を及ぼしたためだったりする。経済活動や生産プロセス、生命維持に直接関わるシステムなどのより重要なソフトウェアでは、ソフトウェアの信頼性を評価する必要性も大きくなる。

あるソフトウェアアプリケーションの重要さの度合いによらず、ソフトウェアは我々の生活のあらゆる面に深く浸透している。我々の社会基盤がソフトウェアに依存している限り、この浸透は続くと予想される。社会基盤がソフトウェアへの依存を強めるにつれて、ソフトウェアの信頼性のレベルの向上が求められるようになってきた。すなわち、ソフトウェアは意図したように動作すべきであり、常に改良が求められる。

### 信頼性への挑戦

前節の循環しているような文章は偶然ではない。これはソフトウェアの信頼性の測定に関する基本的問題を表している。信頼性は判断が難しく、特に事前にソフトウェアがどう使われるかを正確に想定することは難しい。問題は、従来ならば人間が担っていたであろう役割をソフトウェアが代替しているという共通の概念的錯覚から生じる。この問題は2つのレベルに分けられる。第一に、最新のソフトウェアは人間にはできないようなことを実行し、特に人間に比較するとその信頼性は非常に高い。第二に、ソフトウェアは人間の精神的な面を代替することはできない。つまり、融通を利かせるとか、常識を働かせるとか、概念的なことを理解する能力はない。

それにもかかわらず、多くのソフトウェアプログラムは何らかの目的を持つと見なすことができる。目的が明確に定義されるならば、ソフトウェアにある環境であるデータを与えたときに、予測される結果と実際の結果を比較することでその信頼性を客観的に判断することができることが期待される。しかし今のところ、プログラムに環境とデータを与えたときに、予測される結果や実際の結果を正確に求めることが可能かどうか定かではない。そして、そのような手段がなければ、プログラムの信頼性を確実性をもって決定することはできない。

しかし、実際のプログラムやプログラムの理論的記述について、その環境や入力による振る舞いを明らかにしようという試みはこれまでも数多くなされてきた。ソフトウェアの信頼性を改善するためのその種の試みは、実際のソフトウェア開発では様々な工程(要求仕様、設計、プログラミング、テスト、実行時評価)に適用される。ソフトウェアの理論的な信頼性の研究は、主に正当性の概念を扱い、形式言語やオートマトンといった計算機科学の数学的分野から派生している。

### プログラム開発における信頼性

#### 要求仕様

プログラムの開発者が「どう動作すべきか」を事前または開発中に詳細に把握していなければ、それが望ましい動作をすることは期待できない。どの程度詳細に把握すべきかは議論の余地がある。完璧な詳細さという考え方は魅力的だが、実際問題としては現実的ではない。なぜなら、「こうあるべき」という要求仕様は試行錯誤的に変化するものだからである。

事前に要求仕様をうまく記述できるかどうかは信頼性の分かれ目であり、要求仕様の形式化(モデリング言語などの利用)が採用されるのはそのためである。また、プログラマ以外の専門家でない人々にそのソフトウェアの振る舞いを正しく伝達する手段でもある。実際には、プログラマも「どう動作するか」を事前に把握していないことが多く、それが要求仕様に関する議論を困難にしている。

#### 設計

要求仕様がプログラムがすべきことを記述するのに対して、ソフトウェア設計ではプログラムがそれをどのようにすべきかを記述する。設計工程の有用性には異論もあるが、信頼性の観点からはソフトウェア設計工程の重要性が指摘されている。ソフトウェア設計では、ソフトウェアを部品にわけ、それらのすべきことを記述する。そのようにしてプログラムを細分化していき、部品群が全体として正しく機能するようにする。

高レベルな設計の目的は次のようになる。アーキテクチャ上の問題やプログラムの概念や構造に関する問題を実際のデータ処理に関わるコード上の問題と分離する。ソフトウェアコンポーネントを細分化することで個々のコンポーネントの開発に関わるものに制約を与え、結果としてバグを作りこみにくくする。コンポーネント間のインタフェースを定義することで複数のチームがそれぞれ別のコンポーネントを並行して開発できるようにし、各チームがその役割を認識できるようにする。また、実装言語を指定せずにプログラムの機能を記述することで、言語に依存した偏向を排除する。

#### プログラミング

プログラミング言語の開発史は、プログラムの複雑さを克服する試みの歴史であり、言語の発展がなければプログラムはその規模に対して指数関数的に理解が困難になっていただろう。プログラミング言語はコンピュータにより多くの仕事をさせるべく進化したと言う事もできるが、これは同じことを別の観点で言っているだけである。プログラム全体の構造や機能を見失うと、バグを見逃すことが多くなる。従って、よい言語を使えば理解が容易になり、バグも減らせる。

言語はソフトウェア設計の意図していることをなるべく簡単に記述できるよう進化してきた。文、サブルーチン、ファイル、クラス、テンプレート、ライブラリ、コンポーネントといった概念の導入により、プログラムの記述が抽象化・階層化・モジュール化され、コードの理解が容易になってきた。

さらに言語の進化によってデータの構造や利用に関しても正確な制御が可能となってきた。

#### テスト

プログラムが要求仕様などの通りに動作するかを判定するのがソフトウェアテストである。単体テストは、プログラムのごく一部(多くの場合1つのサブルーチン毎)を対象に仕様通りに動作することを確認する。結合テストは、より大きなモジュール単位での動作を確認する。

#### 実行時

実行時の信頼性の判定はテストと似ているが、その観点はより単純であり、性能、他のコードとの相互運用性、特定のハードウェア構成で動作可能かといった点で評価される。

## ソフトウェア品質の要因

ソフトウェア品質要因は機能面以外の要求仕様と考えられるが、顧客との契約に明記されることは少ない。しかし、ソフトウェアの品質を強化することは望ましい。

以下に主なソフトウェア品質要因を列挙する。

### ソフトウェア品質要因の測定

ソフトウェア品質の測定には様々な観点がある。しかし、万人が納得する測定の観点は珍しい。人によってはソフトウェア品質の定量的測定が必須であるとされるが、他の人は定量的測定が有効な場面は限られると考えており、そのため定性的測定を好む。真に望ましい測定を行うことの難しさはソフトウェアテストの分野の権威が何人か書いている。例えば、Cem Kaner の Software Engineering Metrics: What Do They
Measure and How Do We Know? と Douglass Hoffman The Darker Side of Metrics がある。

よく使われるメトリックの例として、検出バグ数がある。バグの少ないソフトウェアはバグの多いソフトウェアに比べて品質が高いとされる。以下のような質問の回答を考えることで、このメトリックが特定の場面で役立つかどうかを考えることができる。

1. どんなバグが多いのか? ソフトウェアの目的の違いを考慮しているか? ソフトウェアの規模や複雑さの違いを考慮しているか?
2. バグの重大性を考慮しているか? 障害の重大性やユーザーへの影響によって重み付けしているか? もし重み付けしていない場合、100件のバグと1000件のバグのどちらが品質が良いのかをどう判断するのか?
3. 検出バグ数が時と共に減っている場合、その意味をどう判断するか? 例えば、その製品が従来よりも品質が良くなっていると判断できるのか? あるいは、改造を以前ほどしなくなっただけか? あるいは、評価を行う者が変わって以前よりバグを検出できなくなっただけか? あるいは、チームが意図的にバグ数の報告を少なくしようとしているのか?

最後の質問は、特に管理上の難しさを示している。ソフトウェアは人間が作るものであるため、ソフトウェア品質のメトリックは、ある意味で人間の振る舞いを測定することである。チームがバグを過少に報告することで何らかの利益が得られるなら、そのチームは少なくバグを報告する傾向が強くなる。バグ追跡システムを出し抜く方法を見出したり、4、5件のバグを1件の報告にまとめてしまったり、些細なバグを報告しないことで作業量を減らすといったことである。意図したとおりの測定をすることは難しい。特にプログラマや評価者が、意識的か無意識的かに関わらず、測定そのものにゲームとしての誘因を見出さない場合、その傾向がある。例えば、品質保証部門がそのチームの過去のバグ傾向などから新たなソフトウェア開発におけるバグ収束曲線を予測し、実際のバグ報告とその予測を比較することで残存バグ数を見積もるとする。予測が正確であれば学習効果によって実際に報告されるバグ数は予測よりも少なくなる。予測通りのバグ数の報告が無ければ出荷が認められないとすれば、チームがバグ報告を過少に行うことはなくなる。しかし、予測が不正確であれば、実際のバグ数が予測を超過することになり、様々な目先の利害関係からバグを過少に報告するということが発生しうる。

ソフトウェア品質要因はその記述が曖昧であるために測定できない。しかし、機能以外の要求仕様を満たしているかどうかを明らかにするためには、何らかの測定が必要となる。例えば、信頼性はソフトウェア品質の要因のひとつであるが、そのままでは評価できない。しかし、信頼性という属性に関連して測定可能なものが存在する。例えば、障害発生間隔 (MTBF)、障害発生率、システムの可用性などである。同様に、移植性の属性はプログラム内のプラットフォーム依存の文の数で表される。

ソフトウェア品質要因の評価に使われるスキームを以下に示す。それぞれの要因(特性)について、関連する質問群がある。こういった質問への回答に基づいて一種の採点を行うことができ、それによって品質上の特性が定量化される。

## ユーザーの観点

ソフトウェアの技術的品質に加えて、エンドユーザーの経験もソフトウェアの品質を決定する。この種のソフトウェア品質をユーザビリティと呼ぶ。ソフトウェア製品のユーザビリティを定量化することは困難である。ユーザビリティを定性的に明らかにするための重要な質問を以下に列挙する。

- ユーザインタフェースは直観的か?
- 単純な操作はやさしいか?
- 複雑な操作は適切か?
- エラーメッセージは分かりやすいか?
- ウィジェットは期待通りに動作するか?
- 文書は十分か?
- ユーザインタフェースの反応性は良いか?

また、有料か無料かを問わず、サポートが得られるかどうかもソフトウェアのユーザビリティを左右する。