C#でドメイン駆動開発

C#でドメイン駆動開発 ViewModelの中に明細項目があるときの実装⑪

Udemyで公開しているC#のコースを1つ無料でプレゼントしています。こちらから確認してください。

C#でドメイン駆動開発。今回はViewModelの中に

明細項目がる場合の実装を見ていきます。

画面の実装では一覧リストなどViewModelの中に

リスト項目を保持するケースはよくあると思いますので

そのあたりの解説をしていきます。

リスト表示

これまでは1行分のデータを扱ってきましたが,

今回は複数行のデータを扱うシナリオを考えてみましょう。

Testsプロジェクトに「MeasureListViewModelTest」を追加します。

ViewModelsフォルダにMeasureListViewModelクラスを新規で作成します。

MeasureListViewModelTestに戻り,

usingを追加してコンパイルエラーをなくします。

 

次にテストを書いていきます。

今回のシナリオは,

「計測リスト画面が表示したら,計測データが一覧に表示される」

というシナリオです。

テストでは2件表示されることにして次のように書きます。

 

コンパイルが通らないのでMeasureListViewModelに次のように書きます。

BindingList<T>はWinFormでのバインドに使うコレクションです。

WPFであればObservableCollection<T> を使用します。

MeasureListViewModelMeasureという型はこれから作成する

一覧用のViewModelです。

MeasureListViewModelの中でMeasuresを表現するために

使用するViewModelなのでこう言った名前にしています。

MeasureListMeasureViewModelという名前にしてもよいとわ思いますが,

親となるViewModel「MeasureListViewModel」が

ソリューションエクスプローラー上一番上にくるほうがわかりやすいので

私はこのような命名にしています。

 

命名に関してはチームでコードレビューをして決定するのがよいでしょう。

ただマイクロソフトの定めた命名方法があり

.NETのクラスライブラリ設計 開発チーム直伝の設計原則,コーディング標準,パターン

に記載されていますので,ここにあるものはこれに倣ったほうがよいでしょう。

そのほうがマイクロソフトのフレームワークとの実装にも合いますし,

他のチームとの共存もしやすくなるでしょう。

 

それでは「MeasureListViewModelMeasure」を作成します。

場所は「ViewModes」フォルダに作成します。

 

実装はまだ何もありません。

ここで一度テストしましょう。

MeasureListViewModelの「Measures」が0件のためテストが通りません。

画面起動時に計測データを取得するシナリオのため,次ように実装します。

 

IMeasureRepositoryに「GetData」を追加し,

MeasureEntityのリストで返却されるように定義します。

IMeasureRepositoryがコンパイルエラーになるためGetDataメソッドを追加します。

中身は未実装の例外「NotImplementedException」のままにしておきます。

テストコードがコンパイルエラーになるため

Mockを使用してコンストラクタの引数に設定します。

これでテストをすると成功します。

ただこれではCountが2件あるというだけで,

計測リストに何が表示されているかがテストされていません。

 

そこで表示したい値をテストファーストで作成していきます。

計測リストに表示されるのは「計測日時」と「計測値」としましょう。

テストコードに次のコードを追加します。

「MeasureDate」と「MeasureVaule」はコンパイルエラーになるのでMeasureListViewModelMeasureに追加します。

 

「MeasureDate」と「MeasureVaule」の値は

引数で受け取ったMeasureEntityのVOのDisplayValueを表示するようにしています。

EntityにVOを乗せることで,

いろんな場所で統一した書式で表示することが可能になっています。

 

MeasureListViewModelではMeasureEntityを渡すように変更します。

今回はMeasureEntityをカプセル化して_entityを保持していますが,

コンストラクタの引数で値を取得して次のようにしてもよいです。

 

この場合は呼び出し元でVOのDisplayValueを投げます。

このように本当に表示するだけであれば,

ドメインオブジェクト(MeasureEntity)を保持していなくてもよいでしょう。

DisplayValue以外にもドメイン要素が必要であれば

EntityまたはVOをカプセル化して,

プロパティでDisplayValueなどを選択するというコーディングになります。

 

また,Entityの項目が50項目くらいあるけど3項目しか使わない,

などという場合はEnityでカプセル化せず,

VOを3つカプセル化したほうが,メモリの節約になるでしょう。

 

これでテストを実行すると成功します。UIとインフラを作成しましょう。

まず,ViewsにMeasureListViewというフォームを追加します。

DataGridViewを張り付けDockをFillにしてNameを「MeasureDataGrid」にします。

画面のコードを表示し次のようにします。

ViewModelの生成でコンパイルエラーが出ているので

MeasureListViewModelに次のコンストラクタを追加します。

MenuViewにボタンを追加し「List」と表示します。クリックイベントで

「MeasureListView」が表示されるように記述します。

 

実行してMenuViewのListボタンを押下してみましょう。

MeasureFakeのGetDataメソッドが未実装の例外を出しますね。

 

こうしておけば未実装部分を後回しにしていてもすぐに気づくことができるので,

この例を利用することをお勧めします。

 

ではMeasureFakeを実装しましょう。

_entitiesはstaticなリストでprivateでカプセル化しています。

アプリケーション全体で1つのリストを共有し,

MeasureFakeでしか変更できないようにしています。

 

こうすることで外部データをシミュレートしています。

staticなコンストラクタはMeasureFakeに何かがアクセスしたときに

一度だけ動作するため,最初に一回_entitiesが生成され,

初期値が2件作られます。GetDataではこの_entitiesを返却します。

 

ちなみに戻り値をIReadOnlyListとすることで外部から変更ができなくなり,

可読性,保守性が高まります。

 

List<T>はprivateで使用することを心掛け,

外部に公開するリストはReadOnlyにしてください。

 

それではF5で実行してみましょう。

Listボタンを押すと2件の計測データが表示されます。

 

VOを使用したことで「計測日時」「計測値」が,直近値画面や計測画面と同じ概念で動作しています。

Udemyで公開しているC#のコースを1つ無料でプレゼントしています。こちらから確認してください。