テスト駆動開発は設計技法である~組み込みアジャイルコーチ James Grenning さんインタビュー
「テスト駆動開発による組み込みプログラミング ―C言語とオブジェクト指向で学ぶアジャイルな設計」の著者のインタビューが公開されていたのでメモ。
幾つかの内容を抜粋しながら、ラフなメモ書き。
【元ネタ】
組み込みアジャイルコーチ James Grenning さんインタビュー ( 前編 )
組み込みアジャイルコーチ James Grenning さんインタビュー ( 後編 )
[ 技術書籍紹介 ] Test Driven Development for Embedded C
O'Reilly Japan - テスト駆動開発による組み込みプログラミング
なぜ Agile Japan 2013 の基調講演に James Grenning さんを呼びたかったか:An Agile Way:ITmedia オルタナティブ・ブログ
「テスト駆動開発における組み込みプログラミング」 - Yasuo's Notebook
【1】プロセスありきではなく、優秀な開発者ありきが大前提であり、優秀な開発者にプロセスを任せれば良い、という考え方がアジャイル開発の基本であると指摘している。
プロセスありきで、開発者を交換可能にするやり方は、プロセス標準化にもつながる。
いくら頑張って標準化して、属人化を排除しても、技術の進歩が早ければ、標準化された技術は陳腐化されてしまいゴミになる弱点がある。
(引用開始)
驚いたことの一つが、彼らの考え方はその当時主流だった考え方と違っていたことです。90年代に一般的だったのは「正しい開発プロセスがあれば、開発者はもっと上手くやるだろう」というものでした。しかし、アジャイルソフトウェア開発宣言を共に検討したメンバーの意見は「スキルのある優れた開発者がいれば、彼ら自身が学習して開発プロセスを決めれば良い」です。
それとは対象的に、多くの会社ではソフトウェア開発の管理や開発プロセスの改善の話をするとき、会社がやって欲しい通りに仕事をさせようとします。IT産業のやっていることは「うちには取り替え可能なプログラミングユニットの開発者がいる。彼らが開発プロセスに従えば、ソフトウェアの問題はなくなるだろう。」というもの。しかし、アジャイルソフトウェア開発宣言で我々が語っているのは人の重要性です。これは驚くべきものでした。
(引用終了)
【2】TDDのモチベーションは、バグの防止。プログラミングしながらバグを未然に防ぐ。
(引用開始)
私は、新しく TDD に興味を持った人に対してバグの防止を最重視していることを強調します。もし、TDD のアプローチに従うなら、実装中にバグが検出されるので、多くのバグを未然に防ぐことができます。全てではありませんが、多くは防げます。企業経営者に話をする時も、TDD がバグを防止する仕組み、そして debug later programming の問題について説明しています。もし、コードの欠陥によるリスクを取り除くができれば、開発はより良いものになるでしょう。
もう1つモチベーションがあります。手動テストが持続可能ではないということです [13]。テストを手動でやるなら、ちょっとした修正をやった時や新しい機能を追加する時に全ての機能を自分でテストする必要があります。こうなるとテストの工数が制御できなくなります。私の知っている限りでは、テスト工数を低く保つにはテストを自動化するしかありません。
他の影響として、適切に書かれたテストコードは実行可能なドキュメントになります。これは開発の後に得られる2次作用のようなものです。
(引用終了)
【3】TDDは最初は単体テストの観点で小さく始める。
しかし、QAのプロセスでは、反復的なアプローチを考える。
QA 担当者が各イテレーションにおいて開発者が作った成果物に対してテストを書くやり方。
開発者がイテレーションの仕事を 1~2 週間で完了し、QA 担当者がテストし、成果物の受け入れを行う。
QA 担当者がやるテストは、単体テストよりもレベルの高いテスト。
振る舞い駆動開発(Behavior Driven Development; BDD)、ストーリーテスティング、受け入れテスト駆動開発(Acceptance Test Driven Development; ATDD)、統合テストなどいくつかの呼び名がある。
「実行可能な仕様」を書くためのツールとして、FitNesse/CSlim 、Cucumber、robotframework などがあるらしい。
アジャイル開発でテスト駆動する時は、人を役割や境界で縛らない。
QA担当者の作業負荷が高ければ、開発者も自ら支援しに行く。
彼らの仕事をそのまま担当できなくても、手伝えることはある。
【4】モデリングやアーキテクチャ設計はTDD と密接な関係がある。
TDDは継続的な設計を促し、インターフェイス中心の考え方を徹底させる。
(引用開始)
SOLID 原則を紹介している第11章「SOLID, Flexible, and Testable Designs」の中でいくつか責務 [4] の分割に関する設計を行なっています。ここで重要な原則の一つが「関心事の分離 [5]」です。書籍では蛍光灯の点灯や消灯のスケジュールを管理をするソフトウェアを設計する中で、全体を異なる関心事の領域に分割し、システムを構築する上で必要なインタフェースを用意する場所を特定しています。例えば、ここには蛍光灯のスケジューリングに関するロジックがあって、ここはスタブに置き換えられるようにしよう、というように。そういうわけで、いつどの程度やるかを明記していないだけで、一定量のモデリングはやっているわけです。設計や実装の活動の最初にモデリングを通じて、自分がどこに向かっているのか検討することは良いことだと思います。
(引用終了)
(引用開始)
多くの人がTDDのコード中心な側面を見て、「TDDは設計しない手法だ」と誤解しますが、実際に我々がやっているのは継続的な設計です。オブジェクトのインタフェースを定義する時はいつも、そのインタフェースを実際に使うテストを書きます。それは設計の活動です。私の書籍の例をいくつか見れば分かると思いますが、テストケースの作成によって最初にインタフェースを作ります。なので、最初の方のテストケースがインタフェース設計を駆動するのです。そして、後の方のテストケースで設計の詳細を検討します。
そして、私はコードに翻訳可能で実行可能なレベルの詳細なUMLモデルは書きません。個人的には時間の無駄だと思っています。モデルの適切な詳細さは、オブジェクトの名前、責務、そしてモジュールのいくつか代表的な属性や操作くらいです。C/C++コードのシグニチャレベルの詳細さが適切だと考えている人もいるでしょうが、私自身はそれは詳細すぎると考えています。
(引用終了)
(引用開始)
以前、アーキテクチャ設計を行うプロジェクトに参加した時に事前に大量のモデリングを行いましたが、それは間違っていると気づきました。私は堅苦しくモデリングするより、小さいモデルを書く方が好きです。設計が実際に動くかどうかを確かめるためにモデルを書くことも良いでしょうが、その代わりに私はテストを書いて確かめるのが好きです。テストはオブジェクトがどのように動くかを明確に示してくれます。そしてインタフェースが使いやすいかも示してくれます。これは私が長年の経験の中で得た結論です。
(引用終了)
【5】TDDで難しいのはシステムテストの運用。
単体テストは開発中にできても、ユーザ視点の受入テストやシステムテストをイテレーションに全て埋め込んでテストするのは難しい場合がある。
システムテストは別イテレーションを別途設けて、反復的に品質を上げていく期間を用意したほうがいいだろうと思う。
また、システムテストでは、受入テストケースの品質が肝になる。
テストケースの内容が曖昧な仕様になっていないか、テストケースの網羅性が担保されているか、などの観点で吟味する。
すると、例外系やたくさんの条件分岐の機能もテストが必要になってくる。
著者は、テストケースを詳細化しながら、設計を汎用化していく方法を勧めている。
(引用開始)
このように要求仕様を受け取って、テストケースでソフトウェアの仕事を詳細に表現するのです。最初のテストケースでは仕様で求められていることのうち狭い範囲をパスします。そして、テストケースが増えるにつれて設計を汎用化していきます。例えば、最初に月曜日のテストケースを作成し、月曜日にだけ動くようにします。次に火曜日のテストケースを作成し、任意の曜日に対して動く様に設計を汎用化していきます。
そういうわけで、私は設計に注意を払うというより、コードを汎用化してくれるようなテストケースを選んでいきます。テストケースを選ぶことで設計を汎用化していく過程を見れば、多くの人はTDDの設計の側面を理解してもらえると思います。テストケースがひと通り終わった時に汎用的な設計が完了しています。
おそらく、あなたの質問は「要求仕様を受け取った。さて、これからどう段階的にテストを進めていくのか?」でしょう。例えば、2週間で5つのストーリーを完了させるとします。実際にはもっとストーリーはあり、まだ開発していない蛍光灯のスケジューリングはずっと先にあるとします。最初のイテレーションでこれらのテストを完了する計画を立てます。受け入れテストがないと次のイテレーションにリリースするのが困難になるので受け入れテストも用意するでしょう。そして、実験室に行って実際のハードウェアにつないでテストできるようになります。ここがゴールです。それぞれのイテレーションの中で作業を完了していきます。
(引用終了)
【6】著者の本「テスト駆動開発による組み込みプログラミング ―C言語とオブジェクト指向で学ぶアジャイルな設計」では、組み込み系特有のテスト技法についても書かれているらしい。
組み込み系でTDDが難しい理由の一つは、C言語の言語仕様でテストしなくてはいけないことだ。
モック(Test Double)やリフレクションをそのまま実装できないため、テクニカルな技法が必要になる。
RubyやJavaなら簡単に使えるのに、C言語ではそれらのライブラリを用意しなくてはならない。
また、TDDはオブジェクト指向と密接に絡むが、オブジェクト指向の最大の利点であるポルモルフィズムをC言語で実装する場合、テクニカルな技法が必要になってくる。
インスタンスを構造体で表現したり、テスト対象の関数をインスタンスごとにポリモルフィックに表現したい時に関数ポインタで動的に表現する手法があるだろう。
また、組込系では、ハードとソフトをセットにしてテストする所が難しい。
そして、更に継続的にビルドしていく環境も準備するのも難しい。
それらについても、色々なノウハウが書かれているらしい。
XPJUG関西でも細谷さんや西さんが、組み込み系のテスト駆動開発について、技法を色々試されていたのを思い出す。
関西では組み込み系の技術者が多いので、「テスト駆動開発による組み込みプログラミング ―C言語とオブジェクト指向で学ぶアジャイルな設計」は必須の本になってくるのではないだろうか?
【追伸】
「テスト駆動開発による組み込みプログラミング ―C言語とオブジェクト指向で学ぶアジャイルな設計」のまえがきは平鍋さんが書いている。
平鍋さんはその本の主張や本来の意図を的確に詳しく書いてくれているので、平鍋さんが書いたまえがきやあとがきを読むだけで、本を全て読んだ気になるようになるから不思議だ。
以下、Amazonのレビューを引用。
(引用開始)
「日本語版まえがき」より
本書は、C言語を使う組み込み開発の現場用に書かれた、テスト駆動開発の具体的な指南書である。そう、C言語で! テスト駆動開発はオブジェクト指向言語が前提となることが多かったのに、本書は組み込み開発現場でのC言語を前提としている。この手法をあなたの組み込み開発に取り込めないだろうか? きっと試す価値はあるはずだ。組み込み開発のソフトウェア開発現場では、なかなか障害が収束せず、出荷ぎりぎりになってデバッグに追われる日々を強いられる状況も多い。そして、みんなそんな状況から逃れたいと思っている。ジェームズは、その1つの答えになるのがテスト駆動開発だと信じて本書を書いた(私もそう考えている一人だ)。チームや個人が自らのソフトウェアの品質をよりよくしたい、と考えているなら、ぜひすぐにでも試してみてほしい。組み込み開発の現場で日々ソースコードと格闘している、まさに、あなたのための手法だ。
私は著者のジェームズ・W・グレニング氏と数年来交流している。昨年は彼の開催するテスト駆動開発のワークショップにも参加し、実際に手を動かしてC言語のコードを書いた。そこで気づいたのは、彼のとても真剣な組み込みソフトウェア開発に対する情熱だ。彼は、ワークショップが始まる前に、参加者の全員に一人ずつ自己紹介をしながら資料を手渡していた。そして、ワークショップがはじまると、静かに、しかし熱く、組み込み開発の現場の悲惨な現状を語った。彼も組み込み開発の現場を変えたいと考えている。そして、その鍵がテスト駆動開発にあると信じている。
よく誤解されるのだが、テスト駆動開発は「テスト手法」ではない。ユニットテストをうまく利用して、よりよい設計を導くための手法である。この手法で開発されたソースコードは、「テストしやすい設計」になると同時に、動くユニットテスト群が同時に開発される、という優れものだ。このユニットテスト群は回帰テストで利用されるとともに、将来の設計変更を安全に導く基礎になる。私が本書で特に気に入っているのは、ボブおじさんこと、ロバート・C・マーティンのソフトウェア設計原則である「SOLID原則」にも章を割いて解説している点だ。テスト駆動開発は、テストしやすい設計を導く設計手法であり、ソフトウェア設計原則と不可分なのである。本書を読むことで、テスト駆動開発だけでなく、よい設計とは何か、というより大きな問題を考えるきっかけにもなるだろう。
さあ、本書を手に、すぐに試してみてほしい。テスト駆動開発のよさに感染するだろう。そして同時に疑問を抱くだろう。どうやったら自分の現場に適用できるか、と。そしたら、チームの仲間と勉強会をはじめてみてほしい。開発の仲間を作ることが、ソフトウェア開発の現場をよくすることの第一歩だから。組み込み開発のやりがい、そして楽しさ、を取り戻そう。
(引用終了)
| 固定リンク
「ソフトウェア」カテゴリの記事
- Javaのモジュールシステムの考え方をまとめてみた(2022.10.21)
- Javaのenum型はシングルトンクラスみたいだ(2022.06.20)
- テスラが従来の自動車メーカーと異なるところは工場までソフトウェア化すること(2022.02.09)
- 「RubyやRailsは終わった」という記事のリンク(2022.01.09)
- 実践した後に勉強するのがエンジニアの本来の道(2022.01.09)
「ソフトウェア工学」カテゴリの記事
- 「システムアーキテクチャ構築の原理」の感想part2~非機能要件がシステムのアーキテクチャに影響を与える観点をプロセス化する(2024.05.06)
- 「システムアーキテクチャ構築の原理」の感想(2024.05.06)
- ソフトウェア工学の根本問題から最近のソフトウェア設計を考えてみる(2024.03.03)
- マイクロサービス設計は従来のアーキテクチャ設計と何が違うのか(2024.01.02)
- 「ソフトウェアアーキテクチャ・ハードパーツ」の情報リンク~マイクロサービスの設計技法の課題は何なのか(2023.11.12)
「Agile」カテゴリの記事
- 「システムアーキテクチャ構築の原理」の感想part2~非機能要件がシステムのアーキテクチャに影響を与える観点をプロセス化する(2024.05.06)
- 「スクラムの拡張による組織づくり」のScrum@Scaleの感想(2024.03.31)
- ソフトウェア工学の根本問題から最近のソフトウェア設計を考えてみる(2024.03.03)
- 「GitLabに学ぶ 世界最先端のリモート組織のつくりかた」の感想(2023.12.10)
- 概念モデリングや設計原則は進化しているのか(2023.10.21)
コメント