仕様の静的検査器のブログ記事について質問や添削を匿名ダイアリーでいただいたので私の意見を回答します。
前書き
まず上記の匿名ダイアリー記事を書いてくださった方へ。記事を閲覧しさらにご意見を書いてくださったことに感謝いたします。 おそらく著者様は検証に携わる立場の方なのかなと推察します。いただいたご意見は大変参考になりました。 ここに私からの回答を付け加えることで、記事の訂正及び補足ができると嬉しいなと思っています。
本文
「実装のふるまいを誤っていると判断する」のは本当に仕様の欠陥といえるのか?
→ テストで気づくことを想定しているんだろうけど、テストは仕様書から作られるわけで、テスト設計ミスでは?
「本来正しいと意図した実装の振る舞いを誤っていると判断したり、その逆に誤っていると意図した実装を正しいと判断する仕様には欠陥があります」の読点前の部分に対する疑問でしょうか。以下はそうだと仮定して話を進めます。もしそうでなければ読み飛ばしてください。
まず元記事の文を図解し、元記事の意図していた仕様の定義を確認します。 というのも仕様には複数の定義があり、この記事ではそのどれを意図しているのかを明らかにしなければよい議論にならないからです。 なお元記事で採用している仕様の定義は、数理論理学に立脚した仕様の定義で形式仕様と呼ばれるものです。
図1の矩形は過去・現在・未来にわたってありえるすべての実装の集合を意味しています。
元記事における仕様は、図2のようにこの実装の集合を正誤判定によって2つの部分集合へと分割する役目をもちます。
仕様記述をする際、仕様記述者の脳内には意図した仕様があるはずです。 これが図3の左上です。 実際に記述された仕様は図3の右上です。 この左上と右上が一致しなかったとき仕様に欠陥があります(図3の②と④の部分)。
元記事の読点前の部分は図3の②を指し、読点後の部分は図3の④を指します。
図3の②の典型的な例は記事中に示している矛盾した記述です。 他にもパスワード入力画面にあるはずのパスワード入力フォームの配置の指示を書き忘れてしまってパスワード記入フォームが存在しないことが正解という仕様書になってしまっていたケースもこの例に当てはまります。 このいずれの例も「テスト設計ミス」と呼ばれることに違和感があります。
「誤っていると意図した実装を正しいと判断する仕様」は、通常の開発において起こり得るのか?
要求定義〜仕様作成〜テスト設計の流れを踏む以上、このような逆転は起こりにくいのでは?
この話は入力によって出力が一意に決まるシステム、すなわち関数的なシステムの仕様である、事前条件・事後条件の組を表で表したときに起こりうる例がわかりやすいと思います。 事前条件・事後条件については「契約による設計」に解説があります。 大雑把にいうと、事前条件はシステムに入力してよい入力を決める条件です。 事後条件は、事前条件を満たす入力について、どのような出力を返さないといけないかを決める条件です。この事前条件・事後条件の表し方はいくつかあります。 ここでは入出力の表として表現したとし、事前条件を満たさない入力は行を書かかないこととします。 これには2つの理由があります。
- 事前条件を満たさない入力は無数にあり、その全てを表に書ききると膨大になってしまい読みづらくなるため
- 事前条件を満たさない入力について実装はどのように振る舞ってもよいため
例えば FizzBuzz 関数の仕様をこの規則にしたがって表にすると次のようになります:
入力 | 出力 |
---|---|
1 | "1" |
2 | "2" |
3 | "Fizz" |
4 | "4" |
5 | "Buzz" |
... | ... |
注目して欲しいのは、0 以下の整数や浮動小数点数、文字列などは事前条件を満たさないことから表に書いていないところです。 このときFizzBuzz 関数の仕様の表に 100 のときの入力だけ書き忘れてしまったとしましょう。 すると100 の入力は事前条件を満たさないということになり、本来実装に100を入力すると"Buzz"が出るべきなのにどのように振る舞っても正しいと判定されてしまいます。 つまり100以外の入力についてはすべて仕様を満たすが100の入力に対する出力を"100"とする実装や"FizzBuzz"とする実装が正しいと判定されてしまいます。 これはまさに誤っている意図した実装を正しいと判定してしまう仕様を書いてしまった例になっています。
実装が顧客の要求にたまたま合っていたとしても、それが仕様書に沿っていないなら「正しい実装」とはいえないのでは?
→ この場合、実装がたまたまあっていただけで、テストもされていない状況。仕様も実装も両方が誤っていたというべきでは?
仕様と同じように要求にも複数の定義があるため用語を整理してから解釈を説明します。 私は Michel Jackson の要求の定義を採用しています。 この定義では、問題領域に属する事柄が要求であり、機械領域に属する事柄が仕様であるとされます。 また、仕様が要求を満たしかつ実装が仕様を満たすならば自動的に実装は要求を満たす、というふうに要求と仕様、実装の間の関係が満たすべき性質が与えられています。
ここで、要求と仕様、要求と実装のそれぞれの間で満たすべき性質を妥当性(Validation)といい、仕様と実装の間で満たすべき性質を正当性(Verification)といいます。 この定義では、おっしゃる状況は実装が妥当であるが正当ではない状況ということになります。
そして元記事では意図しない妥当性違反のみをスコープとし、意図した妥当性違反と正当性違反についてはスコープ外1とするよう構成しました。 この立場からおっしゃる状況を解釈すると、仕様書に沿っていない実装は正当でない、つまりおっしゃる通り正しくない、となります。 元記事はこの解釈で一貫して書いているつもりです。
「さて」が不要
接続語としての意味が弱く、文の格調を下げている印象。
参考になりました。ありがとうございます。
仕様や満たすという言葉の用法の定義直後に「仕様の欠陥」の話が始まり、論点が拡散する
仕様の性質や運用について触れた後に、欠陥の話題を出した方が構成として自然。
「運用」を仕様という成果物を取り巻くプロセスというふうに解釈して回答します。 もしそうでない場合は読み飛ばしてください。
仕様がどう使われるかによって仕様の備えるべき性質が決まります。 したがって仕様という成果物を取り巻くプロセスが重要であるというご指摘はごもっともです。 ただそれが元記事において説明する優先度は低いと判断しここに関する説明をしていません。
今回の構成は、仕様の欠陥を見つける静的検査器を実装した成果を説明するために以下の構成をとっています:
用語定義
用語の混乱を避けるために元記事で用いる「仕様」および「仕様を満たす」、「仕様の欠陥」の意味を定義した
問題提起
仕様の欠陥はあるべきではないが現実にはあるというギャップを問題として提起した
解決方法
仕様の欠陥を防ぐアプローチとして仕様書の形式を整え静的検査器を実装し解決を頃みた
今後の展望
論点が拡散するように見えたのは1の文量が多く、そこが主題だとご認識いただいたからかもしれません。 ただ私は3を主題として設定しているつもりです。 そのため仕様という成果物を取り巻くプロセスについてはあまり言及していません。 1が長くなってしまったのは「仕様」という複数の定義をもつ語を混乱しないように解釈してもらうための苦肉の措置でした。
仕様における「正しさ」の基準と、実装やテストの誤りの区別が曖昧
仕様の欠陥と、テスト設計・実装のミスは分けて扱うべき。
元記事では次のようにそれぞれの欠陥を定義しました:
- 仕様の欠陥
- 意図と表現物の相違による妥当性違反、意図と表現物の相違によらない妥当性違反(元記事のスコープ外)
- 実装の欠陥
- 正当性違反(元記事のスコープ外)、妥当性違反(元記事のスコープ外)
これによればいずれも厳密に区別される認識です。 そうでない場合、ぜひご指摘をいただきたいです。
例示が適切でない
→ 「仕様と実装がどちらも間違っていたが、結果的に要求に近かっただけ」のケースであり、 「正しい実装を誤っていると判断した仕様」ではない。
言及先の文を見つけられませんでした。 よろしければ言及先の文をご教示願います。
「無価値」という語の使用が不用意に攻撃的
仕様のすべてが誤っているわけではない状況であるので、特定の部分が誤っている・矛盾しているという事実の指摘にとどめるべきで、感情的な評価語は避けた方が望ましい。
「無価値」という言葉が感情的な評価語であるという認識を持っていませんでした。 そのような解釈があることに気づけていなかったため、ご指摘に感謝いたします。
私の解釈では、ソフトウェア開発プロセスに登場するすべての成果物はそれに誤りがなければ(客観的な)価値があるというという認識を持っています。 ここから仮に(客観的に)無価値なものがあるとしたらその成果物に誤りがある、というふうに背理法で導くことが本記事の意図でした。 客観的な価値評価は合理的なソフトウェア開発プロセスにおいて極めて重要な概念であると認識しています。 「無価値」を感情的な評価語であるとするのはおそらく主観による評価であるからだと思っていますが元記事ではそれを意図していません。
ていうか、仕様矛盾の例示いらなくない?
単なる文言の誤りをここまで冗長に書く必要ないし、無用に攻撃的だしで、なんだかなという感じ。ここ以外もなんだけど、全体として実装やってるやつは悪くないんだ!って気持ちがあふれてる感じがする。気持ちはわかるが書きたいことと関係なくない?
これはのちに登場する静的解析期の検査ルール12に対する事前の説明を意図して書いたものです。 特定の誰かを悪くいう意図はありませんでした。 そのような意図に取られる表現であったことをお詫びいたします。
添削後( 「仕様に欠陥があるとどうなるか」も別に言いたいことと直接関係ないだろうし軽く触れる程度でいいでしょってことでマージした場合)
仕様の定義にはいくつかの解釈がありますが、ここでは「仕様」を、要件定義に基づいて作成され、実装の正しい振る舞いを定める基準と定義します。実装が正しいと判定される場合、それは実装が仕様を満たしていることを意味します。
要件定義を元に作成された仕様に誤りがあった場合、実装の段階でその誤りに気づくことは難しいことが多いです。このような誤りは、通常、顧客レビュー(受け入れテストやUAT)で判明します。しかし、顧客とのコミュニケーションコストや調整が必要になるため、テスト段階で問題を発見するよりも、対応に要する工数が多くなりがちです。
この添削は私の意図した構成から大きく逸れたものになっています。 前述の通り、ここは用語を厳密に定義することでその後の説明の意味解釈の混乱を避けるために用意したセクションです。 「要件定義」や「要件定義に基づく」といった複数の定義があり混乱している用語がその定義の説明なしに登場することは望ましくありません。 また「仕様」の定義の説明がほとんどなくなってしまったことも残念に感じます。
後書き
上記の匿名ダイアリー記事を書いてくださった方へ。記事を閲覧しさらにご意見を書いてくださったことに感謝いたします。 私の見解や意図を説明してみましたのでもしよろしければまたご意見・ご指摘をいただけると嬉しく思います。