web-dev-qa-db-ja.com

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

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

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

DDDプロジェクトのコーディング部分をゼロから開始するには、どのように動作しますか?
DDDのテクニカルパターンに合わせるために、テストから設計を厳密に明らかにする必要がありますか?つまり、懸念の分離(レイヤーなし)とリファクタリングを行わないでください。

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

15
Mik378

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

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

ウディ・ダーハン:「神様、私は重ね着が嫌いです。」彼は彼の講演でそれを議論するのにしばらく時間を費やします CQRS-しかし異なる (レイヤーは18分30秒から始まります)

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

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

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

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

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

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

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

言い換えると、空のプレースホルダーを実装して後で埋められると想定することではなく、 ddd からの戦術パターンを適用しますが、代わりにストリームを横断するときを認識することによって「ねえ、私のドメインモデルの永続化コードです。まだリファクタリングを行ってはいけません。」

12
VoiceOfUnreason

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

他のすべての設計上の懸念を喜んで無視し、信心深くTDDルールを守る場合は、コードががらくたになったときにTDDを責めないでください。テスト可能ながらくたになりますが、がらくたになります。

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

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

DDDは、システムの詳細にほとんど気づいていないドメインの専門家がシステムの制御方法を理解できるコード内のスペースを作成して保存する取り組みです。これは、おなじみの方法で問題ドメインを抽象化およびモデル化することによって行われます。

DDDシステムは、次のようなアーキテクチャを持つことができます。

enter image description here

このDDDアーキテクチャは多くの名前で使用されます: CleanOnionHexagonal など

多くの人がこのデザインを見るときに感じる切断は、次のとおりです。これは具体的ではありません。私はこのデザインをたどることができ、ここに図解されているようなものを書いたことがありません。ユースケースオブジェクトまたはエンティティークラスが必要だと他の人が主張しているのを目にします。これらとは、誰とどのように会話できるかを示す一連のルールです。

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

まだあいまいですか?右下隅のControler-Use Case Interactor-Presenterダイアグラムを見てください。ここでは、互いに通信する3つの具体的なものを示します。確かにこれはDDDですが、ここにTDDをどのように追加しますか?具体的なものをあざけるだけ。プレゼンターは情報を受信して​​いる必要があります。 PresenterMockクラスは、期待どおりの結果が得られていることを確認するための良い方法です。 Use Case InteractorPresenterMockを渡してUse Case Interactorを運転し、まるでControllerであるかのようにしてください。モックが期待どおりの結果が得られたかどうかをモックが通知するので、Use Case Interactorを単体テストするための素晴らしい方法があります。取得する。

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

TDDを使用してデザインを推進する場合(単純に[〜#〜] d [〜#〜]evelopmentではない)、あなたの努力を反映したデザインが得られますそれに入れます。それでいいのなら。しかし、それがTDDの目的ではありませんでした。これが最終的に欠けているのは、確かにTDDのせいではありません。

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

11
candied_orange

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

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

これらはどちらも、2つの強力なプログラミング手法の浅い説明です。しかし結局のところ、彼らは2つの非常に異なることを実際に達成しています。

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

注意することが重要かもしれないと思う:アプリケーションが十分に複雑である場合にのみDDDを練習するべきです。

4
Matt Oaxaca

[〜#〜] ddd [〜#〜]はソフトウェア設計に関するものです。
[〜#〜] tdd [〜#〜]はコード設計に関するものです。

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

コードの初期ソフトウェア設計モデルにTDDを使用できます。ドメインにはビジネスルールとドメインモデルがあり、テストの記述(初回)はグリーンでなければなりません。

実際、ドメイン駆動モデルを設計した後、テストをコーディングできます。
この本「成長するオブジェクト指向ソフトウェア、ガイド付きテスト」link-for-buy
walking skeletonhexagonal architecture およびTDDを使用して、このアプローチを取ります。

出典: DDD迅速-InfoQ

3
JonyLoscal

設計をテストから厳密に明らかにするべきか

いいえ。(ドメイン主導)定義による設計は、ドメイン要件から生まれるべきです。これは、テストスイート、データベーススキーマ、または...(続行)のいずれであっても、設計を推進するために他のことをさせることは悪い考えです。

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

(続き)...または、非常に成熟した人気のある言語であっても、選択したお気に入りのOO言語のクラス/クラス階層の標準的なレイヤー(すべての「何百万ものハエは間違っています」.

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

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

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

また、TDDがDDD画像にどのように適合するかについての質問にも答えます。簡単に言えば、要件が機能的なスタイルでコード化されている場合、無効な状態やシナリオのほとんどを表現不可能/コンパイル不可能にするため、大量のユニットテストの必要性がなくなります。もちろん、FPプロジェクトには自動テストの場所がまだありますが、テストが主要な設計上の決定を下すことは決してありません。

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

1
KolA