SE Can't Code

A Tokyo based Software Engineer. Not System Engineer :(

TDDとデバッグ.

僕はデータ解析やモデリング的なコードを書くことが多いので、これまでテストを書いてもかなり簡易的なテストしか書いていなかったり、各ファンクション単位でテストは書かずに最後のmainファンクションといったラッパーに対しての最終的な結果のチェック程度でしかテストは書いていなかった。ただ、少し前から割としっかりとテストを書くようになってきていて、理由は結局、テストを書いた方がテストを書かなかった場合よりも早くコードを仕上げることが出来ると気付いたからだ。

500行程度のコードなら特にテストを書かなくともなんとなく全体の各ファンクションを頭の中で整理することはできる。ただ、それ以上の規模になった途端に頭がついて行けなくなる。

規模が大きいと一つの変更が様々なところに影響を与える場合がある。いくら疎結合にしても結果の形が変わると影響は他のファンクションに出てしまうので、ここの修正は必ず入る。その時、想定していたインプットが処理を通過してコンパイラをすり抜けてしまった場合、その時点で気付くのがかなり難しくなる。恐らくもっと後ろで気付くことになるだろう。そして、そこから始まるデバッグはかなり労力を伴う。デバッグだけで1日の大半を潰してしまうこともあるだろう。特に原因が深ければ深いほどに。

こうしたデバッグは予想以上に時間がかかる。体力も持って行かれるし、気も萎える。そして気付くことになる。テストを書いておけば良かったと。

TDD、いわゆるテスト駆動開発はその点かなり有効だ。まず中身の無いファンクションを書いてから、テストを書き始める。テストに書くことは様々だが、ファンクションの仕様が正しいかどうかの判断をダミーデータなりを使って出した結果をもって判定する。テストを先に書くと必ずエラーが吐かれる。そしてエラーが消えるように実際にファンクションを実装していく。これは最初から最後までファンクションの仕様というゴールを頭に置いておくことが出来るのでとても良い。実装を変えようとした時も他のテストのチェック内容を見れば、どこに影響が出るのかがとてもわかりやすくなる。

特に良い点は、自分以外の第三者がテストを読めばファンクションの振る舞いを理解しやすい点にある。テストを読めばまずどのようなインプットが投入される前提で、どのようなアウトプットが期待されるのかがわかる。ロジックについてはテストやファンクションのコメントに書くと良いだろう。ファンクション名や変数名でわかるレベルのものならそれで良いが、複雑な処理をしているファンクションは説明を入れてあげるのが良い。

僕はもう最近はずっとTDDでコードを書いている。なんとなくだがこっちの方がスピードが出る気がするからだ。少なくともデバッグのスピードは段違いだと思う。テストを一つ一つクリアしていくことが小さな目標となっていくので、終わりも見えやすい。テストがこけても「よし、やるぞ!」という気持ちになれる。

TDDなんて昨今当たり前の開発フローだと思うが、なんとなく有り難みがわかってきた。検証コードでもテストを書くのは大事だ。規模が大きくなりそうなタイミングが来たら、テストを書く方向に切り替えると良いと思う。

Remove all ads