🦔

TDDを自分の手でまとめて理解をしていく_No1

2022/04/26に公開

出典

https://t-wada.hatenablog.jp/entry/clean-code-that-works

TDDとは

Test Driven Development。テスト駆動開発。

TDDといえばこのイメージ。TDD = @t_wadaさんな感じ

TDDの目的とアプローチ

「動作するきれいなコード」  = 「Clean code that works」を作ること。

「動作するきれいなコード」。Ron Jeffriesのこの簡潔な言葉が、テスト駆動開発(TDD)のゴールだ。動作するきれいなコードはあらゆる意味で価値がある

しかしながら、実際の開発現場においては、
「きれい」であることのみならず、「動作する」ことを担保するためにも、様々な制約が存在し、それらを達成することは難しい場合が多い。
きれいに書けないかもしれない、動作しないかもしれない、そんな不安を抱え込むことをやめにして、自動化されたテストによって、動作するきれいなコードを目指し開発を推し進めていくアプローチをとるのがTDD

TDDはテスト技法ではなく、TDDは分析手法であり、設計技法であり、実際には開発のすべてのアクティビティを後続化する技法なのだ

  • Kent Beck

動作するコードを書くためには、ビジネスロジックに対する振る舞いの分析が必要であり、きれいなコードをかくためには設計を工夫する必要があり、テストが書きやすい実装を考える必要がある。
TDDをうまく使うことで、ただテストを書くだけでなく、ソフトウェアに対する欠陥をへらし、欠陥を見つけるまでの時間を減らし、欠陥を修正するまでの時間を減らすことができる。なによりもプログラマの心配ごとを減らすことができる。

動作するきれいなコードを書くための考え方

最初から、きれいで、動作するコードを書くのは難しい。
なので、問題を小さな問題に分割し、1つ1つ対処していくと考える。
「clean code that works」は"claen code" と "that works"に分けることができ、
それぞれの逆を取ると"Dirty code"と"does not work"に分けることができる。
つまり、「Dirty code that does not work」から初めて、「clean code that works」を目指す、
という考え方ができる。

Does not work that works
Clean
Dirty

1. Dirty code -> Clean codeから始めるアプローチ

きちんと設計してからコードを書くアプローチ。
良い設計には明確な終わりがなく、非常に長い時間考えてしまう傾向が増える。
「みせるには恥ずかしい設計だ」=羞恥心、「的確にドメインを切り取ってやろう」=虚栄心、「まだ検討できていないことがあるはずだ」=完璧主義に陥る、

Analysis Paralysis、プロジェクトマネジメントのアンチパターンの1つ

②->④の工程にて、②で 時間を使いすぎる、YAGNIであるなど、
「書いて動かしてみるまでわからないことがまだまだ多すぎる」

2. Does not work -> that worksから始めるアプローチ

1のアプローチは少し見通しが悪い(相対的に見て)。
なので、まず汚くても動くものを作ろうとする。確かに「きれいだけど動かないソフトウェア」と
「きたないけど動くソフトウェア」では後者に価値があるが、
「きたない」から「きれいに」変える過程を、様々な理由で断念してしまう。
「動いているならいいじゃないか」、「きれいにする工数で新しい機能をつくってほしい」、「動いているので触りたくない」など、「きたないけど動作するコード」を「動作するきれいなコード」にしていく過程で 「きれいだけど動かないコード」にすることを恐れるには十分な言い訳になってしまう。
プログラマは8000点を支払って後の3巡を買えないのである。なるほど凡夫だ。

https://meigen.info/?p=1023

2のアプローチから、きれいな動かないコードへ恐れずに進むには

ソフトウェアは手を触れなければ動き続けられるものではない、つまり、動いているコードに手を入れていかなければならない。むしろ、作ってからが本番となるケースが現代。避けては通れない道と考え方をシフトしていく必要がある。「書き換えること」を前提として、いかにアジリティを高く維持していくか、不安を軽減していくか、を考えていかなければいかない。

むしろソフトウェアを作ってからがスタートで、市場のニーズや状況に適応して欲しいときに望ましい形に姿を変えることができて、変更しやすく手を入れ続けられるような、変化し続ける、変化し続けられるソフトウェアの方が資産になる時代です。
https://t-wada.hatenablog.jp/entry/clean-code-that-works より引用

現代のソフトウェア開発で用いるべき3つの技術
  • バージョン管理システム
    ソフトウェアに触れ続けるためには、他人も含めて開発の記録をさかのぼれる必要がある。
    ※ 余談: commitメッセージにはhowを書くべき。変更の「what」と「how」はGitが教えてくれるが、「why」は記録からは読み取れない
    ※ ないとお話にならないレベルのもの。

  • テスティング
    もう引用のほうがいい言葉なのでそのまま、

Test だけでなく "ing" が大事で、テストを書き、行うだけでなく、テストを書き続け、実行し続けることによって人間の把握力の限界を補います。
https://t-wada.hatenablog.jp/entry/clean-code-that-works より引用

テストを自動化し、自動テストと共にコードを書き続けることで何を得られるかというと、 1年前のコードは覚えていないし、1年前の仕様も覚えていないけれども、 1年前にこう動くべきと自分が考えて書いたコードは、いまこの瞬間にも当時の想定通り動いているということだけは、断言できるようになります。
https://t-wada.hatenablog.jp/entry/clean-code-that-works より引用
- 自動化(Automation)/自働化(Autonomation)
人間は単純な繰り返し作業が苦手なのに対し、プログラミング・ソフトウェア開発には、単純な繰り返しの工程が多数含まれる。
そういった作業を自動化することで、よりクリエイティブな部分に注力できるようになる。また、自動化を進めていくことで、「おかしなことがあるかどうかを機械が自分で判断し、報告すべき内容のみ人間につたえる」、トヨタ生産方式で言うところの自働化の状態まですすめていくべきである。この考え方が反映されたのが、CI(Continuous Integration、継続的インテグレーション)である。

これら3つの技術をもとに汚いコードをきれいにしていく、それがリファクタリング。

リファクタリング(名詞) 「外部から見たときの振る舞いを保ちつつ、理解や修正が簡単になるように、ソフトウェアの内部構造を変化させること」
リファクタリング(動詞) 「一連のリファクタリングを適用して、外部から見た振る舞いの変更なしに、ソフトウェアを再構築すること」
https://t-wada.hatenablog.jp/entry/clean-code-that-works より引用

3つの技術をもとにやること = 「リファクタリング」

自動テストとともに開発されたコードでは、リファクタリングは「成功しているテストが成功しているままで」あればコードの変更が可能と解釈することができる。ソフトウェアに変更を加えても。ソフトウェアが実現する状態と振る舞いが変わらないことをプログラマが検証する必要がなくなる(確認の工数が少なくなる)。
また、CIにより「人間が気付かなくとも機械が気付いて教えてくれる」状態となり、さらにバージョン管理システムによって動いていたコードによって、動かなくなってしまったら、切り戻せばいい状態となります。
これによって「汚い動くコード」から「きれいな動くコード」への変えていく過程を乗り切る事ができる。

フィードバックフィードバックサイクルを回す(ソフトウェアは書いてからがスタート)

「手を入れ続けられるコード、安心して積極的に変化し続けられるソフトウェア」の方が、資産価値が高ぃ、
それを実現するためには、「ある時点で動作するきれいなコードであるだけでなく、ずっと動作するきれいなコードであり続けさせる」必要があり、変化し続け、対応し続けることが求められてくる。

>フィードバックループを常に回し続け、テストとリファクタリングを両輪にして不断の改善を続けるための
   >プログラミングプラクティスがテスト駆動開発であり、その改善のサイクルがテスト駆動開発の本質です。

https://t-wada.hatenablog.jp/entry/clean-code-that-works より引用

Red - Green - Refactoring のサイクル

ここまでの話を頭にいれると、このサイクルでコードを書く意義を捉え直すことができた。(個人の感想)

レッド: 動作しない、おそらく最初のうちはコンパイルも通らないテストを1つ書く。
グリーン: そのテストを迅速に動作させる。このステップでは罪を犯してもよい。
リファクタリング: テストを通すために発生した重複をすべて除去する。

上記を繰り返していくこと自体を開発のプロセスに組み込む。

テストコードを書く上で気をつけなければいけないこと
  • テストコードは本番コードと同じレベルで記載しなければいけない、テストコードだから簡易的に書いてはいけない。
    TDDはテストコードをメンテナンスしていく開発手法であり、テストコード自体に質を求めていかないと、よいRGRのループが回せなくなる。
  • リファクタリング、TODOは後回しにされる。書くべきときに書き続けなければならない

ユニットテストのコードは本番コードを同じくらい専門的な標準で作成し、保守する必要があるのです。 カプセル>化の維持、DRY原則の遵守、結合度の軽減など、優れた設計に関する通常の規則は、本番コードと同じようにテ>ストコードにも適用する必要があります。
Test code is real code.
https://t-wada.hatenablog.jp/entry/clean-code-that-works より引用

Discussion