C#でドメイン駆動開発

C#でドメイン駆動開発 アーキテクチャーの実装とテスト駆動での書き方を解説5

前回はドメイン駆動開発で採用するアーキテクチャーについて解説しました。今回はそれを実際に実装していきます。全体をユーザーインターフェース、インフラストラクチャー、ドメイン層に分け,さらにユニットテスト用にテストプロジェクトを作成します。その後テスト駆動開発でテストコードを書いていく方法を順番に解説していきます。

実装

プロジェクトの追加

それではプロジェクトの作成をしましょう。最初にWinFormを選びソリューション名を「DDD」プロジェクト名を「DDD.WinForm」にしましょう。次にクラスライブラリを選び「DDD.Domain」を追加します。同じく「DDD.Infrastructure」を追加します。最後にテストフレームワークを選び「DDDTest.Tests」という名前で登録します。「DDD.Tests」としないのはテストプロジェクトが必ず一番下に来るように並べたいからです。好みの問題です。

参照関係はDomainは参照なし。最上位です。InfrastructureはDomainを参照します。WinFormはDomainとInfrastructureを参照します。TestsはDomain,Infrastructure,WinFormを参照します。

TestsにはNugetで「Moq」と「Chaining Assertion」をインストールします。最初の実装さてそれでは最初の実装をしましょう。多くのプログラムはデータを取って画面に表示する。または画面の値をどこかに保存する。というシナリオがほとんどかと思います。データを取って画面に表示するまでに何かしら加工したり,判定したりはするでしょうが,大きく分けるとその2つがエンタープライズアプリケーションとしては王道かと思います。

ゲームアプリとかなら違いがあるかもしれませんが。最初のシナリオはシンプルにデータを取って表示しましょう。ドメイン駆動開発なのでドメイン部分を作りますが,ドメインをテスト駆動で作成するので,まずはテストコードを書きます。

「Tests」にファイル追加でテストを追加します。名前は「MeasureViewModelTest」とします。基本的にはViewModelに対してテストを書いていきます。決まりではありませんが,クラス一つ一つをテストしていくより,シーケンスをつかさどるViewModelをテストするのが一番効果的です。

多くの分岐があるようなドメインロジッククラスがあればそれのみ個別でテストコードを書きます。目的はViewModelとドメイン層に対して,できるだけカバレッジを上げることです。カバレッジとはテストコードが通った割合。分岐などがある場合は全ての分岐を通るようにテストを書きます。

ただ,絶対に通らない本番コード用のコンストラクタなどもあるので90%以上が目安です。カバレッジはNugetでOpenCoverを取得し,拡張機能のOpenCoverUIで計測できます。

MeasureViewModelTestを作ったら「計測_シナリオ」というテストを作ります。そこにいきなり「var viewModel = new MeasureViewModel()」と書きます。MeasureViewModelクラスはまだないのでコンパイルエラーになります。テスト駆動なのでクラスを作る前にテストを書きます。基本的に命名はテストコードでします。

インテリセンスが出てこなくて書きにくいと思うかもしれませんが勘違いです
ここで命名しているのです

命名するときにインテリセンスなんて今までも出てきてないですよね?それと同じことです。

ともかく,MeasureViewModelを作ります。場所は「WinForm」に「ViewModels」というフォルダを作成しそこに作成します。クラスをPublicに変更し,ViewModelBaseを継承します。ViewModelBaseはデータバインドを可能にするための記述を共通化するために実装しています。

ファイルはViewModelsフォルダに配置し,中身は次のようにします。

MeasureViewModelTestに戻るとMeasureViewModelのコンパイルエラー部分でコントロールを押しながらドットを押下してEnterすることでUsingが追加され,コンパイルエラーが消えると思います。

一度テストを実行しましょう。成功すると思います。

次に

と書きます。

これは,MeasureViewModelが生成されたときのMeasureValueの初期値が“–”ということを示しています。画面を起動したときの初期値になります。

MeasureValueはコンパイルエラーになるのでコントロールボタンを押しながらドットを押し,Enterします。

テストをするとレッドバーになると思います。レッドバーを取り除きましょう。自動生成されたプロパティpublic object MeasureValue{get;set;}は次のように書き換えます。

さらにデータバインドを可能にするために,値が変更された時の通知がされるように書き直します。

SetPropertyは継承元のViewModelBaseに記載しています。中身はMVVMライブラリーのPrismと同じ実装にしています。

これでテストしてみましょう。これでテストが通りましたね。
今のが一連のテスト駆動の手順です。

です。そしてグリンバーが出たら最後にやることがあります。

などなど。

今回は単純なコードのため特に重複コードやドメインコードが散らばっているという状態にはなっていません。このサイクルをぐるぐる回していきます。

これでは先に進みます。今のは非常に単純なケースでしたが,次は少々ややこしくなります。

インターフェースを普段使い慣れていない人は急に難しくなったと感じるかもしれません。テストコードにテストを追加します。

Measure()が存在しないためコンパイルエラーになりますが,いつもの要領でメソッドを生成します。

コンパイルエラーが取れたらテストを実行しましょう。レッドバーになります。

今回は少々厄介です。まず1.23がどこからやってくるのでしょうか?もちろんこれはテスト用の値です。ちなみにこのテストのシナリオは「計測ボタンを押したら計測値が表示される。計測値は小数点2桁で丸められ,単位はm/sで生じされる」ということを表しています。

テスト駆動とはこのように先に欲しい結果をテストコードに書きます。「こういうアクションを起こすとプロパティの値はこう変わっているはず!」という思いを込めてテストコードを書きます。あとはレッドバーをグリーンバーにするだけです。では始めましょう。MeasureViewModelのMeasureメソッドは未実装のExceptionが記述されていると思います。

これを消します。そしてもう一度テストしてみましょう。当然まだレッドバーです。MeasureメソッドにMeasureValue = “1.23m/s”;

と書けばテストはとおりますが,こんなコードは意味がありませんね。それ以外の方法でテストを通しましょう。

ここでドメイン駆動開発の1つの要素を紹介します。

ドメイン駆動開発

C#プログラマーのための正しい3層構造が分かる「C#アーキテクチャー解説動画」をここで公開しています。よかったら見てみてください。

 

参考図書

ドメイン駆動開発

エリック・エヴァンスのドメイン駆動設計

実践ドメイン駆動設計

ドメイン駆動

現場で役立つシステム設計の原則

エンタープライズアプリケーションアーキテクチャパターン

デザインパターン

オブジェクト指向における再利用のためのデザインパターン

オブジェクト指向のこころ

Head Firstデザインパターン ―頭とからだで覚えるデザインパターンの基本

オブジェクト指向

ジャイルソフトウェア開発の奥義 第2版 オブジェクト指向開発の神髄と匠の技
  すばらしい本です。オブジェクト指向が詰まっています。

オブジェクト脳のつくり方―Java・UML・EJBをマスターするための究極の基礎講座
  サンプルコードはjavaですが,最初にオブジェクト指向に目覚めるのに最適な本です。

Head Firstオブジェクト指向分析設計 ―頭とからだで覚えるオブジェクト指向の基本
  マンガみたいな感じで読めて,オブジェクト指向について学べます。  

Clean Code アジャイルソフトウェア達人の技

Clean Architecture 達人に学ぶソフトウェアの構造と設計

Adaptive Code ~ C#実践開発手法

.NETのエンタープライズアプリケーションアーキテクチャ

実装パターン
  廃盤のため異常に高くなりすぎなので,様子を見た方がいい気がします。一万円のボリュームがあるかどうかは微妙です。

オブジェクト指向でなぜつくるのか

レガシーコード改善ガイド

リファクタリング 既存のコードを安全に改善する

C#でオブジェクト指向をする方法

オブジェクト指向の原則1:単一責務の原則