テスト駆動開発における進化的設計とデザインパターンの勘所とは?〜テスト駆動開発をやめて、なお残すべき習慣とは(9)

TDDの際にデザインパターンをどう使うのか、または、どう使わないのかを考えるお話。

Eiji Ienaga
時を超えたプログラミングの道

--

前回から、書籍を辿り、TDDの再考を試みています。TDDを既に知っている、実践しているという人にとっては、TDDについて新しい発見、ジャメヴ(未視感)が起きれば幸いです。たとえTDDが不要だったとしても、不要だと判断したものが一体何だったのか知ることは欠かせません。

忘れないで、テスト駆動開発にもデザインパターンの話が出てくるよ

TDDはテストファーストやベイビーステップのインパクトがありすぎて、あまり目立っていないですが、書籍『テスト駆動開発』にもソフトウェアパターンの話が出てきます。そう、出てくるんですよ。

余談ですが、テスト駆動開発3部におけるSingletonパターンの説明はGoFの説明とは違ったユニークな内容になっています。(本で確認してみてね)

1回だけ設計ではなく繰り返し設計

注意点ですが、テスト駆動開発においてのソフトウェアパターンは、プロジェクト初期に1回だけパターンを使って設計をするのではありません。不確実性がある前提で、Red Green Refactorの繰り返しの中で、当初は理解していなかったが、コードという形で具体的なアウトプットを出すことで気づき、設計を見直して適応するのがポイントです。

「テストが難しいコードを発見したか?」「機能追加を邪魔するコードを発見したか?」「インタフェースが使いづらいか?」「読んで理解するまでの時間が長すぎるか?」「コードを読んで不快を感じたか」がYesなら、どこかにコードや設計の悪臭があり、修復が必要です。必要であれば、パターンを参考にリファクタリングします。

書籍『テスト駆動開発』の1部では副作用ありのプロダクションコードのまずさを確認して、Value Objectパターンを導入して解消し、またFactory Methodパターンを使ってプロダクションコードとテストコードを疎な関係にしてリファクタリングしやすいように工夫する様子が描かれています。2部ではPluggable Selectorパターンが出てきます。詳しくはぜひ1,2部を写経してパターンを取り込んでいる様子をトレースしてみて下さい。

TDDを使った設計改善の方向性については、GoF以外のソフトウェアパターンのほかSOLID原則も参考になります。

設計の終焉やDDDなどでの設計の取扱

初期に一回だけの設計(計画的設計)とサイクルの中での繰り返し設計(進化的設計)については、マーチン・ファウラーの「設計の終焉?」が有名です。

この論文において私は、設計のやり方に関する二つのスタイルについて、説明 するつもりだ。おそらく最もよく見受けられるのが「進化的設計」だ。進化的設計とは、要はシステムの実装が進むにつれて、設計のほうも成長するという ことだ。設計もプログラミングの一環であり、プログラムが進化すれば設計も 変化する。

ファウラーによる、エクストリームプログラミング実践者へパターンに関するアドバイスは次になっています。

XP実践者にアドバイスを与えるとすれば、

* パターンについて学ぶ時間を投資せよ
* パターンを使うべき時についてよく考えよ(早すぎてはいけない)
* まずは、最も単純なかたちでパターンを組み込む方法について考え、 複雑なものは後から追加せよ
* パターンを入れてみて、後で「失敗したな」と思ったら — 躊躇せず 取り除け

継続的な設計改善については、書籍『パターン指向リファクタリング』も参考 になります。

TDDと継続的なリファクタリングは、無駄がなく規律のある反復型のプログラミング技法であり、最大限に焦点を絞れて、負担が少なく、生産性が高められる。[急がば回れ]とはマーチン・ファウラーがこのやり方を評して言った言葉だが[Beck, TDDより]、ウォード・カニンガムは、この方法はテスト手法というよりも継続した分析・設計であると述べている。

「ジョシュア・ケリーエブスキー, パターン指向リファクタリング入門」 テスト駆動開発と継続的なリファクタリング

https://www.amazon.co.jp/dp/4822282384

ソフトウェアパターン本の代表格であるドメイン駆動設計でもリファクタリングなどを使った設計改善の重要性を強調しています。

忘れないで欲しいのだが、こうした モデルに基づく設計は一度に現れるものではない。ドメインの重要な概念を蒸留して、シンプルで鋭いモデルにするには、 リファクタリングと知識のかみ砕きを何度か反復しなければならないのだ。

「エリック・エヴァンス,エリック・エヴァンスのドメイン駆動設計 」
モデル駆動設計

https://www.amazon.co.jp/dp/4798121967/

まとめ

TDDをやめてもなお、不確実性の高い状況でインクリメンタルかつイテレーティブな開発をしているとき、要望変更に適応していくには、設計を初期に一回だけ行うではなく、リファクタリングをベースにした継続的な設計改善を続けることが欠かせません。

DDDの場合は、少なくともイテレーションのサイクルを使って、ドメイン知識を噛み砕き、理解を深めようと試み続けます。

TDDの場合は、イテレーションのサイクルよりもさらに小さいサイクルのなかで設計改善をベイビーステップで行うように仕組み化されています。

設計改善で何処に向かうべきかについては、必要な時に備えチームで設計判断の揃えるためにも、先人の知恵が凝縮されたソフトウェアパターンを継続的にキャッチアップしておくのがお勧めです。

ソフトウェアパターンは現在、GoFだけではなく多数広がっています。実装パターンリファクタリングXUnit Test Patternsドメイン駆動設計エンタープライズアプリケーションアーキテクチャパターンEnterprise Integration PatternsMicroservice patternsAWSクラウドデザインパターンなどなど。

ただしパターンを覚えたからといって、今の状況や抱える問題を無視して、大量にパターンを利用して解決しようとするパターン魔のダークサイドに陥ってしまうに注意して下さい。「必要なときにパターンを利用する」だけでなく、「不要なときはパターンを利用しない」のスキルを身につける必要があります。

--

--