― Web Technology and Life ―

テストをしやすいコードの書き方

2011-04-18
「コードを書くのは楽しいけど、テストコードとなるとちょっと・・・。」「いざテスト書こうとすると、一体何から手をつけてよいかわからない」そんなときに注意したいコードの書き方についてまとめます。

テストしづらいコードなる

根本的にテストに焦点に当てた場合のコーディングとしてテスト駆動開発というコーディングスタイルがあります。まず、仕様に即したテストを書いてから、実際の本コードを書いていくという書き方です。
しかし、常にインプットとアウトプットが明確な仕様書があってから実装に至ることはありませんし、「こんな感じだから、とりあえず、作ってみて」と営業マンやディレクターからアジャイルを意識した(?)口頭による依頼はよくあり、とりあえずイメージわかないからなんとなくのコードを書くことから始めるのはしばしばよくあることだと思います。あるいは、テストを気にしないで、好きにコードを書いているとスパゲッティコードと呼ばれるような可読性が低いコードになり、さらにいざ事後的にテストを書こうとすると、インプットするデータを用意することが難しかったり、アプトプットのデータが不明確で自動テストが用意しづらかったり、あるいは、インプットとアウトプットが多すぎて結局ちゃんとテストできているかどうか不安になることがよくあることだと思います。ぼくも、しばしばこんな状況に陥って、「とりあえず、今は確実に動くんだけど、あとで直すのは難しそうだな」、というコードを量産してしまいす。

コードの論理的検証

テスト駆動開発ではなくてもコードの論理的検証性を意識して、コードのリファクタリングをしていくことでより適切なインプットとアウトプットになるコードつくることが可能です。そんな方法を解説していたのが、『プログラマが知るべき97のこと』という本の「コードの論理的検証」という記事です。この記事では、コードの半形式的証明という方法を紹介しています。

まずすべきことは、対象となるコードを全て短いセクション―1行、ファンクションコールひとつだけのブロックから10行くらいのブロックまで―に分割することです。そうして短く切った上で、個々のセクションが正しいかどうかをチーム内で話し合うのです。その場合、どのセクションについても、メンバーの中で最も懐疑的な態度の人が正しいと納得すれば、一応「正しい」とみなしていいでしょう。
コードをセクションに分ける際には、まずセクションの終端までの間で、プログラムのステート(プログラムカウンタや、すべての「生きた」オプジェクトの持つ値)が、簡単に説明できるようになっていることが重要です。また、セクションの中での機能(状態変化)は1つのタスク(仕事)に絞りこまれていて、これも簡単に説明できることが大切です。このガイドラインを守ると、検証が容易になり、関数の事前条件事後条件、ループやクラス(のインスタンス)の不変条件(invariant)といった概念の意味を統一することにもつながります。個々のセクションをできるだけほかから独立させるよう努力することもじゅうようです。これも、もちろん検証を容易にすることに役立つわけですが、セクションに変更を加える際に、他への影響を考えずにすという意味でも、絶対に必要なことと言えます。 『プログラマが知るべき97のこと』「コードの論理的検証」p.30

長々と引用してしまいましたが、端的にまとめると、ひとつの関数について以下のようなことに気をつけてまとめるとインプットとアウトプットが明確になるということだと思います。

  • できるだけ短くし、長くなったら別の関数に切り出す
  • 変数などがわかりやすくする
  • 機能はひとつに絞り、わかりやすくする
  • 他の関数に依存しないようにする

個人的に見落としがちなのは「機能はひとつに絞り、わかりやすくする」ということと、「他の関数に依存しないようにする」ですね。

機能はひとつに絞り、わかりやすくする

これは、極端に言えば、関数の返り値は1にすることです。ほとんどのいけないコードは一つの関数からいろいろな返り値が返ってきます。HTTPのレスポンスの場合、ステータスコードとその他のヘッダーとボディが返ってくるので、一見いろいろ返ってくるように見えますが、HTTPのレスポンスが返ってくるという意味では1の返り値が返ってきています。一つの返り値として適切にまとまっているかを考えるのは非常に重要なことだと思います。様々な事象の階層構造を考えることで、ビジネス的な、技術的なスコープを意識することでプログラムのスコープが適切にすることができると思います。

他の関数に依存しないようにする

あまりに複雑なリファレンスがインプットになっていたり、複雑にいろいろなインスタンスがラップされているインプットになっていたり、そんなことがたまにあります。あるいは、いまだによくやりますが、インプットとして得られたリファレンスを書き換えつつ別の変数を返すような関数をよく書いてしまいます。

以上、常にメンテナンス性を考えた、息の長いコード書いていきたいと思い、自戒の念をこめて自分なりにまとめみました。テストコードもさくさく書ければ、メンテンス性も上がりますし、バグが潜んでいる可能性も減りますし、精神的な負荷も下がりますし、いいことばかりですね!!

ビジネススキル update_at : 2011-04-18T11:40:04
hirobanex.netの更新情報の取得
 RSSリーダーで購読する   
blog comments powered by Disqus