2012/02/26

C/C++でTDDする時の手順をステートマシン図で描いてみた


タイトルで描いてみたと言いつつ、「Test-Driven Development for Embedded C (Pragmatic Programmers)」の第3.7節「Test-Driven Development State Machine」より引用です。著者のJames W. Grenning氏はTDDの作業を以下のステートマシン図のように捉えると良いと書いています。

TDDの作業を状態遷移として表現したステートマシン図


※作業を状態として書いているので良い書き方じゃないのですが、そこは置いときましょう。

TDDをやっている人ならご存知だと思いますが、テスト対象を実装する前にいきなりテストを書いて、わざわざコンパイルエラーを起こすとこからやるのが大事です。そして、コンパイルエラーの次は、リンクエラー、テスト失敗と来てからようやくテストを通るように実装します。

この一連の流れをやる目的は、

  • 今あるテストを通すための最小限の実装を常に維持する
  • テストが通っていないなら、どこに問題があるか明確に分かるようにする

です。

まずはテストを書いて目標を定めておいて、エラーまたはテスト失敗で作業ステップを確認しつつ、1歩1歩歩いていくのです。本当に1歩ずつです。ちょっとでも道から外れていれば、そこ道外れているよ!と警告を上げてくれます。

(TDDをやらない人でもIDEを使っている人は、IDEについている構文チェックのサポートを受けてコードを書いているので似ているようなことをやっているかもしれません。)

TDDをやらないコーディングの場合、本人が気付かないだけで、作業と並行して細かなミスが蓄積していったり、実装モレがあったりします。実装が一通り終わったという状態になっていても、どこにバグや実装モレが潜んでいるか分からない状態でテスト or デバッグをすることになります。

しかし、このステップをきれいに守ることで、何か問題が起こっていれば明確に問題の箇所が把握できます。テストしていないとか、実装し終わっていないとか、不安定な状態でいる期間が短くなります。常に動くコードをさわっているという核心を持ち、非常に安心感をもって作業ができます。

慣れてくるとビシッと歯車がかみ合った状態で1個1個作業が進んでいる感覚が得られて気持ち良いです。少なくとも読書会をやっているときはきっちりTDDのステップでコードを書き続けてみます。

2012/02/25

TDDする時は少しでもコードを書いたら即ビルド・テストを実行させる

Test-Driven Development for Embedded C (Pragmatic Programmers)」の第1章「Test-Drivern Development」 p.8に以下の記述がありました。
With every change, run the tests. The tests show you when the new code works; they also warn when a change has unintended consequences. In a sense, the code screams when you break it!
この本ではコードがテストされていない期間を可能な限り短くすることを強調していて、理想的には少しでもコードを書いたらビルドしてテストすべきと推奨しています。聞いたところによると、Kent Beckもかなり短いサイクルでコーディングとテストをまわすことを推奨しているとか。これはアジャイル開発に共通する考え方ですね。

Eclipse CDTでやる場合は、プロジェクトのプロパティ -> C/C++ Buildタブ -> Behavior -> Build on resource save (Auto build) にチェックを入れます(下図を参照)。必要に応じてビルドターゲットも設定しましょう。


実際にやってみるとちょっとした記述ミスがあると、すぐにテスト失敗が起きて知らせてくれるので割と便利です。ただし、前提としてテストが数秒で終わらないと作業が止まってので、単体テストの処理時間は短くした方がよさそうです。

それでもテストが増えてくると、そうも言っていられないと思うので、自分が開発中のところだけテストを実行するようにテスティングフレームワークの設定をしておくと良いと思います。
一部をテストさせるやり方はまた後日ブログにのせたいと思います。


2012/02/18

BlogにCoderwallのバッジを貼ろう

Githubのリポジトリの内容をかっこいいバッジで表現してくれるCodewallというサービスがあります。リポジトリの内容、言語の種類やforkされた数などを解析してバッジにしてくれます。

このサービスを利用するメリットとしては以下が考えられるかなと思います。
  • 見た目にもCodewallのバッジはかっこいい。
  • Githubの活用度合いを視覚的に表現するツールとして使える。
  • バッジを増やしていく楽しみもあり、ゲームのようで楽しい。 
バッジを増やすためにがんばる!ってのもどうかと思いますが、がんばった結果がバッジの種類や数として表現されているとなんか勲章のように感じられるかもしれません。

気に入ったので、ちょっとブログのサイドバーにつけてみました。今のところバッジ2つ。C++のリポジトリとJavaのリポジトリを持っていることの証明のようです。今度、種類と数が増やせるようにがんばりたいと思います。

#今、C言語でTDDするコードをコミットしてるので、少なくともC言語のバッジは増えると思います。

ちなみに以下のようなJavaScriptのコードを埋め込むとバッジを表示できます。”yohei1126”は私のアカウント名なので自分のものに置き換えてください。

<script="" type="text/javascript">
    function display_coderwall(args) {
        var badges = args["data"]["badges"];
        for ( var i = 0; i < badges.length; i++ ) {
            document.write('<img '"="" +="" badge"]="" height="48" src="'+ badges[i][" width="48" />');
        }
    }

  <script src="http://coderwall.com/yohei1126.json?callback=display_coderwall"/>
  
</script>


2012/02/05

「Test Driven Development for Embedded C」読書会第1回をやりました #tdd #tdd4ec

Test Driven Development for Embedded C」読書会第1回をやりました。


そもそものきっかけは、2011年の「TDD Boot Camp 東京 for C++」というイベントです。これは組み込みやゲーム業界でC/C++の開発をやっているエンジニアがTDDを実践的に演習するというイベント。

その時に私がポジションペーパーに「Test Driven Development for Embedded Cの読書会をやりたい」と書いたところ、2名が名乗りを上げくれたのでやってみようとなりました。Twitterで呼びかけたところ、10名のエンジニアが参加を表明してくれて、それなりの規模の会になりました。

参加者のモチベーションは?

参加者は、複合機、医療機器、通信機器、家電などの組み込みソフトウェアを開発しているソフトウェアエンジニアです。皆それぞれプロジェクトの中で、レガシーコード(テストコードのない製品コード)を大量に抱えていて、いつも開発時間の大半をデバッグ時間に費やすという不毛な状況に追い込まれているようです。

そのような状況に対して、どうにかしてデバッグ時間を減らすために、不具合を早期に見つけるために、解決策の1つとしてTDDを使えないかと考えていました。

今回読んだ内容

第1回の今回は、第1章「Test Driven Development」、第2章「Test Driving Tools and Conventions」、第3章「Starting a C Module」をやりました。

第1章ではTDDをやる目的、TDDとは何か、TDDをやることで得られる恩恵は何か?を書いていました。
TDDは設計手段の1つとのことで、TDDの目的の1つとして設計改善があることは挙げられます。ただ、私は最大の目的は迅速にテスト結果のフィードバックを受けることで、即場に間違いを見つけること、バグを未然に防ぐことだと思いました。この点は、皆のやりたいことと一致していると思いました。

第2章では、この書籍で扱うテスティングフレームワークの使い方を紹介していました。C向けのUnity、C/C++向けのCppuTestの使い方が紹介されていました。
googletestと同様にCppuTestは自動的にTestRunnerにテストを追加する機能もあり、TDDにはもってこいのツールだと思いました。また、C++の枯れた仕様しか使っていないとのことで、古いコンパイラを使っている人にも安心して使えるツールです。
Unityは単体ではTestRunnerに自動的にテストを追加する機能はないそうですが、Rubyスクリプトでそれを代替しているようです。

第3章では、LEDのドライバソフトを題材に本格的にTDDをやって行く手順について紹介されています。
この章の中では、組み込みの中でのDevendency Injectionのやり方として、物理的なLEDドライバのアドレスを実行時に与えるというやり方を紹介していました。実行時に物理アドレスを与える方法を取ることで、ハードウェアとソフトウェアが分離され、ハードウェアがない状態でもテストできるというメリットが得られるようです。

分からなったこと

分からないなと思ったことが2つありました。
まず1つ目は、第3章のLEDドライバの例はシンプルだからアドレスを渡すみたいな設計にできるんだということです。実際に複雑な例であれば、アドレスを書き換えることによって、別のハードウェアのステータスが変わって・・・という依存関係が複雑になる問題があるので、そういう設計にはしないよねとのこと。

おそらくは、複雑なハードウェアの相互作用、あるいは複雑なタイミングの問題などを全て再現することなく、テストしたいところだけ取り上げてテストできるようにしたりするか(いや、どうするのか分かりませんよ?)。

あるいは、もっとも底辺なレベルのテストをTDDでやらずに、もう1段上のレイヤー、ハードウェアを抽象化している部分のテストをメインにやるのではないかということ。こちらは、全てをTDDしないので網羅的ではないですが、ポイントを絞ってテストすることで、実機を使ったデバッグに専念できるようにする効果はあると思います。

2つ目はレガシーコードが大量にあるシステムに対して、どうやってTDDをやっていくのかという問題。テストを動かすまでの準備が巨大であれば巨大であるほど、最初にTDDをやるモチベーションが下がっています。現場で実戦するなら、初期コストを抑えながら、徐々にTDDを導入する方法が必要です。
どうやらレガシーコードとの戦い方は13章に書いているらしいとのことで、このあたりの考え方は後半解消できるかもしれません。

第1回を終えて

当たり前ですが、第1回では我々の疑問に対する答えは部分的にしか解消できませんでした。しかし、共通した問題意識を持っているメンバーがそろうことができたのが今日の成果だと思います。
この会を重ねていくことで、現実とどう折り合いをつけていくか、何かしらの解を出せるのではと思います。

まず、この会のきっかけを作ってくれた「TDD Boot Camp 東京 for C++」の主催者の皆さんや、「Test Driven Development for Embedded C」の著者James W. Grenning氏には感謝したいです。

さて、主催者として参加者が満足できるような会にしていきます :)


2012/02/02

#読書 2012年1月に読んだ本

なんかbooklogに月単位で読んだ本を整理する機能があったので記念ポスト。

1月に読んだ本の中では「弱い日本の強い円 (日経プレミアシリーズ)」が一番良かったですかね。為替のトレーダーの著者が為替の仕組みを紹介しています。
為替がどういう原理で決まるのか良く知らないのにFXでリバレッジをかけて大損した人多いんじゃないでしょうか?この本で基本原則を理解すると少なくとも長期的なトレンドで失敗することは防げると思います。

legobokuの本棚
2012年01月
アイテム数:5
錯覚の科学
クリストファー・チャブリス,ダニエル・シモンズ
読了日:01月17日
{book['rank']

世界でいちばん!日本経済の実力
三橋 貴明
読了日:01月17日
{book['rank']

powered by ブクログ