厳密なTDDとDDDを組み合わせる方法


15

TDDは、テストによって導かれるコードの設計に関するものです。
したがって、通常、典型的なレイヤーは事前に構築されていません。それらはリファクタリング手順でわずかに表示されるはずです。

ドメイン駆動型設計には、アプリケーション層、インフラストラクチャ層、ドメイン層、永続層などの十分に確立された層を定義する多くの技術的パターンが含まれます。

DDDプロジェクトのコーディング部分をゼロから開始するには、どのように動作するのですか?
DDDの技術的なパターンに適合するために、設計をテストから厳密に浮かび上がらせる必要がありますか?

または、それらの空のレイヤー(アプリケーション、エンティティ/ドメインサービス、インフラストラクチャ)を作成し、TDDをそれぞれに個別に適合させる必要があります(モックを使用してレイヤー間を分離します)。


回答:


11

TDDでのデザインの役割に関するボブおじさんの最近のコメントを必ず確認してください。

ドメイン駆動型設計には、アプリケーション層、インフラストラクチャ層、ドメイン層、永続層などの十分に確立された層を定義する多くの技術的パターンが含まれます。

ウディ・ダーハン:「神様、どうやってレイヤーが嫌いなの?」彼はトークCQRSでそれについて議論するのに少し時間を費やしていますが、異なる(18分30秒で開始します)

あなたの文章の綴りは少し異なります。「DDDは、ほとんどのビジネスアプリケーションに共通する多くの懸念があり、それらの懸念に対する解決策の有効期間が異なることを認識しています」

たとえば、ドメインの懸念事項は、原則として、特に特定のビジネス向けにソリューションをカスタマイズする場合に柔軟性が必要です。結局のところ、ドメインは、会社がどのようにビジネスを行っているか、つまり会社がどのように収益を上げ、ビジネス改善を迅速に提供できるかが無料の収益であることに関係しています。

一方、永続性コンポーネントを頻繁に変更する必要はおそらくありません。前回のリリースで機能したデータベースソリューションは、おそらくこのリリースでも機能します。

アプリケーションの懸念事項は中間のどこかにあります。ユーザーはリリースごとに新しいアプリを習得する必要がないように、安定している傾向があります。

また、特定の懸念事項を解決するために複数の実装が存在する場合があります。たとえば、アプリケーションには現在の状態のスナップショットのみが必要な場合があります。ファイルをディスクに保存するだけで十分です。そして、最初の数回の反復では、それもすべてのドメインに必要な場合があります。しかし、最終的には、アドホッククエリのサポートを必要とするストーリーが発生し、リレーショナルデータベースの構成は、ゼロから実装するよりもはるかに簡単になることを認識しています。そして、グラフデータベースでよりよく機能するこの機能が1つあります。

一方、CTOは自分の電話で実行するアプリのバージョンを求めています。CEOが、APIを公開することが大きなことだと聞いたばかりです。

また、営業チームは異なるモデルを使用しているため、異なるモデルで同じアプリを提供してください。ああ、しかし、私たちは頻繁に旅行しているので、オフラインのときにバージョンを動作させ、後で同期する必要があります...

つまり、空のプレースホルダーを実装して後で埋めることを想定するのではなく、から戦術パターンを適用しますが、代わりにストリームを通過するタイミングを認識すること でリファクタリングはまだ完了しています。」


11

テスト駆動開発(TDD)は設計ではありません。これは、設計に影響を与える要件です。スレッドセーフである必要があるかのように、それは設計ではありません。繰り返しますが、これは設計に影響を与える要件です。

他の設計上の懸念事項をすべて喜んで無視し、TDDを忠実に守るなら、コードががらくたになったときにTDDを非難しないでください。それはテスト可能ながらくたですが、それはがらくたになります。

テスト可能ながらくたの良い点の1つは、それがリファクタリング可能ながらくたであるということです。必要なときだけ空想になります。他の人はこれを嫌い、TDDを非難します。いいえ、これはあなたのしていることです。

ドメイン駆動設計(DDD)は、TDDの赤緑のリファクタリングサイクルの前に行うことです。

DDDは、システムの詳細をほとんど知らないドメインエキスパートがシステムの制御方法を理解できるように、コード内にスペースを作成して保存する取り組みです。これは、問題の領域を抽象化してモデリングすることにより、使い慣れた方法で行われます。

DDDシステムには、次のようなアーキテクチャがあります。

ここに画像の説明を入力してください

このDDDアーキテクチャには多くの名前があります: CleanOnionHexagonalなど

多くの人がこの設計を見たときに見られる切断を以下に示します。これは具体的ではありません。私はこの設計に従うことができますが、ここで図に示されているものを書いたことはありません。ユースケースオブジェクトまたはエンティティクラスが必要だと主張する人もいます。これらは、誰とどのように話すことができるかを示すルールのセットです。

それでおしまい。この設計のルールに従うと、あなたの小さな心をTDDできます。TDDはあなたが誰と話しているかを気にしません。ボタンをクリックするだけで、何かを行うすべての機能が動作するかどうかを確認できます。何かが壊れているわけではありません。何が壊れているかを正確に伝えます。

まだ曖昧ですか?見てControler- Use Case Interactor- Presenter右下隅の図。以下は、相互に通信する3つの具体的なものです。確かにこれはDDDですが、ここでTDDをどのように追加しますか?コンクリートの物をモックするだけです。プレゼンターは情報を受信する必要があります。PresenterMockクラスは、あなたがそれを得るために期待したものなってきたことを確認する良い方法だろう。を渡してUse Case Interactor、あたかもあなたがそうであるかのようにPresenterMock運転するUse Case Interactorと、モックはあなたが期待するものを手に入れたかどうかを教えてくれるので、Controllerユニットテストをする良い方法がありますUse Case Interactor

よく見てください。TDDは満足しており、DDDの設計に手を加える必要はありませんでした。どうしてこうなりました?十分に分離された設計から始めました。

TDDを使用して(単なるD開発ではなく)デザインを推進すると、それに費やした労力を反映したデザインが得られます。それでいいなら。しかし、それはTDDが意図したものではありませんでした。これが最終的に欠けることは、確かにTDDのせいではありません。

TDDは設計に関するものではありません。TDDを使用するために設計を変更する必要がある場合、テストよりも大きな問題があります。


TDDはデザインだとは言いませんでしたが、デザインに関するものです。
Mik378

1
ボブおじさんがデザインするように言っていた。彼はあなたに「残りのことを気にするテスト作業ならね」と言っていませんでした。
candied_orange

1
すでに述べたように、あなたは誰と話をすることができるかというルールに従ってください。クリーンアーキテクチャは、BDUFの議論をするものではありません。自分がどの部分にいるかを特定し、誰とどのようにコミュニケーションをとるべきかを考えてください。思っているよりも機敏です。その後、TDDでテスト可能かどうかを尋ねます。そうでない場合は、何か間違ったことをしました。良いデザインは単なるテスト可能なものではないので、それがあなたの注意を払っていることを願っています。
candied_orange

6
うーん...私は本当に「テスト駆動設計」という誤った呼び名に耐えられません。テストを書くかどうかに関係なく、キーボードを激しく叩き始める前に、まだ少し設計する必要があります。
ラバーダック

1
この正確な点でボブおじさんを引用するには「期間を設計する必要があります」。そこをクリックして、もしあなたがそれらの単語を検索するために全部を読むのが短すぎるなら。マーティン氏は、TDDが魔法の弾丸ではなく、非常に脆弱なコードベースに住みたくない場合は、コードだけでなくテストも設計する必要があることを強く確信しています。
candied_orange

4

TDDは、開発に並行して記述されたすべての必要なテストケースをコードに保証します。これは、高レベルの設計には影響しません。トレンチ作業でもっと考えてください。

DDDは、高レベルの設計、ドメインの専門家とエンジニア間の言語、コンテキストマッピングなどがすべてです。これは、アプリケーションの高レベルの設計の推進力となるはずです。

これらは、2つの強力なプログラミング方法論の浅い説明です。しかし、結局のところ、彼らは本当に2つの非常に異なることを達成します。

DDD言語とコンテキストマッピングから始めて、最終的にコードを記述しようとすると、TDDの練習が始まります。しかし、TDDの実践は高レベルの設計に影響を与えるべきではありませんが、物事をテストできるようにする必要があります。ここには少し注意点があります。

注意することが重要だと思います:アプリケーションが十分に複雑な場合にのみDDDを練習する必要があります。


1
TDDはテストではなく、設計に関するものです。
Mik378

ボブおじさんが説明したように、私はすべてをTDDの3つのルールに基づいています。
マットオアハカ

GOOSの著者であるSteve Freemanは次のように述べています。TDDサイクルを開始する前に、レイヤーやインフラストラクチャを指定しないでください。
-Mik378

私はその本に不慣れですが、私は反対しなければなりません。TDDでDIグラフとクラスグラフを整形したくありません。
マットオアハカ

3
@ Mik378:TDDはテストに関するものではありませんが、主に設計に関するものでもありません。TDDによって誘発される設計は、単体テスト用の設計だけです。デザインの他のすべての部分は、どこか別の場所からのものでなければなりません。私はTDDをより実装技術と考えています。
ドックブラウン

3

DDDはソフトウェア設計に関するものです。
TDDはコード設計に関するものです。

DDDでは、「モデル」はドメインの抽象化、ドメイン専門家からのすべての知識を表します。

コード初期ソフトウェア設計モデルにTDDを使用できます。ドメインには、記述されたテスト(最初)が緑色である必要があるビジネスルールとドメインモデルがあります。

実際には、ドメイン駆動モデルを設計した後、テストをコーディングできます。
この本「テストに導かれたオブジェクト指向ソフトウェアの成長」 link-for-buy
このアプローチを、スケルトン六角形アーキテクチャ、TDDを使って進めください。

ソース:DDD迅速-InfoQ


1
私にとってもソフトウェアとコードは同じことです
Konrad

1
それも同じかもしれません。私が言ってみました:ソフトウェアを「ソリューション」、「システム」、「ハイレベル」としてコード「実装」として、「低レベル」、「詳細」。
-JonyLoscal

重要なことは、「最初にテストするが、テストを開始する最小限のスケルトンが必要」だと思います。あなたは?
-JonyLoscal

1

テストからデザインを厳密に出現させるべきか

いいえ。(ドメイン駆動型)定義による設計は、ドメイン要件から生まれるべきです。これは、テストスイート、データベーススキーマ、または...(続き)

または、これらの空のレイヤー(アプリケーション、エンティティ/ドメインサービス、インフラストラクチャ)を作成し、TDDをそれぞれに個別に適合させる必要があります

(続き)...または、お気に入りのオブジェクト指向言語のクラス/クラス階層の標準的な層(非常に成熟した人気のある言語である場合でも)(「何百万ものハエが間違ってはいけない」ということですか?) 。

DDDに関しては、OOPは人間が読み取れる形式で要件を表現すること、つまり、プログラマーでない人には多かれ少なかれ明確なものであるという要件を満たしていません。厳密に型指定されたFP言語はより良い仕事をします。Scott Wlaschinによる関数型プログラミング「Domain Modeling Made Functional」を使用してDDDに関する本を読むことをお勧めします

https://pragprog.com/book/swdddf/domain-modeling-made-functional

そこからいくつかのアイデアを借用するためにFP言語を使用する必要はありません(残念ながらすべてではありません)が、実際に読んだ場合は、おそらく関数型言語を使用することをお勧めします。

また、TDDがDDD画像にどのように適合するかについての質問にも答えます。要するに、要件が機能的なスタイルでコーディングされている場合、無効な状態とシナリオのほとんどをコンパイルできない/不可能にするため、膨大な量の単体テストが不要になります。もちろん、FPプロジェクトにはまだ自動化されたテストの場所がありますが、テストによって主要な設計上の決定が行われることは決してありません。

完全な円を作るために、タイトルの質問、すなわち「厳密なTDDとDDDを組み合わせる方法」に戻りましょう。答えは簡単です。結合するものはなく、利益相反もありません。要件に従って設計し、設計に従って開発します(TDDを実行する場合は、最初にテストを作成します)


FP DDDの本と全体的な説明については+1。
ローマンスーシ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.