ドメイン駆動開発_フォルダー構成編_#07_WinFormのフォルダー構成

当サイトではアフィリエイト広告を利用しています。

NDDD

前回はInfrastructureのフォルダー構成を解説しました。今回はWinFormのフォルダー構成を解説していきます。今回はWindowsフォームを使用するため,WinFormプロジェクトにしていますが,WPFやUWPなどになる可能性があります。それらをまとめて,ユーザーインタフェース層と呼びます。

時代の変化と共に変化する部分

ユーザーインタフェースとは,簡単に言えば画面等のユーザーが実際に触れる部分です。この部分というのも,時代と共に変わっていきますよね。昔は真っ黒のコンソールでしたが,Windowsフォームが出てきて,WPFがあり,UWPがあります。あとはWEBサイトなどもユーザーインタフェースですね。こういった部分は時代とともに進化します。だから,いまWPFで作成していても,数年後にはもっとおしゃれなユーザーインタフェースに切り替えたくなる可能性があります。なので,そういった部分も切り離して実装することで,ユーザーインタフェース部分だけの変更で時代についていくことができます。

ビジネスロジックとの分離

ユーザーインタフェース部分を切り離すことで,ドメイン層には純粋なビジネスロジック,インフラストラクチャーには外部接触部分,ユーザーインタフェース層には画面関連のみを集中することで,今後WindowsフォームをWPFに変更させる場合は,Domain層とInfrastructure層はそのままで,WPFプロジェクトの追加し,Windowsフォームに実装していたものを,WPFプロジェクトに移行するという作業だけで,WPFの実装が可能になります。なので,ユーザーインタフェース層には,ビジネスロジックが入り込んではいけません。純粋な,画面表示などの,ユーザーインタフェースを制御するためのロジックのみを集中させます。ドメイン層やインフラストラクチャー層の機能を選ぶのが仕事です。

合言葉は「WinFormからWPFにするときに,変更しないといけない物だけを入れる!」です。

MVVMパターンの適応

テスト駆動開発を行う上で,WinFormだろうと,WPFだとうと,UWPだろうと,MVVMパターンを採用することがもっともいい選択です。MVVMパターンとは,View,ViewModel,Modelという3つに分けて実装するパターンです。このうちModelはDomain層とInfrastructureが担っているので,ここでは画面をViewと呼び,Viewのコントロールに連動してデータバインドさせる画面制御ロジッククラスをViewModelとします。昔は,Formプログラムにすべての実装をしていましたが,それでは,テストコードからテストができません。なので,Formには最低限の記述だけをして,画面と1対1でデータバインドさせるViewModelに,画面制御のロジック部分のみを移行させます。これにより,多くのユーザーインタフェースのコードをテストコードで検証できるようになります。

フォルダー構成

以上の事を踏まえて,ユーザーインタフェース層ではViewを入れるフォルダーとViewModelを入れるフォルダーの2つに分けます。フォルダー名はそれぞれ,「Views」と「ViewModels」とします。

タイマーイベントはどこに入れる?

ユーザーインタフェース層ではイベントが発生します。私の考えでは,イベントはユーザーインタフェース層でのみ発生させるべきという結論に至っています。例えば「ボタンを押したとき」や「クリックしたとき」などのイベントは当然ユーザーインタフェース層に入ることが理解できると思います。しかし,定期的に発行されるタイマーイベントのようなバックグラウンドイベントはどこに書くべきでしょうか?私の結論はユーザーインタフェース層です。理由は,保守性を高めるためです。保守性の高いコードとは,「修正時に追いやすいコード」です。インフラストラクチャー層からでも,ユーザーインタフェース層からでも,不具合が発生したときや,改造したいときに,簡単に影響範囲が理解できるのが良いコードであり,保守性の高いコードであるといえます。例えばドメイン層に「アプリ起動後に,1秒に1回計測データを作成するタイマー処理」が動作していた場合,数年後にプログラムコードを初めて見た人は,どのようにしてそれに気づくことができるでしょうか?プログラムコードをすべて読まないと,それに気づくことができません。だって,そういうコードがあるという事は,

ほかにも,「勝手に動いているもの」があるかもしれません。

そんなものがあると知らされたら,すべてひっくり返して読まないと,どう動いているかわからないアプリケーションになってしまいます。

だから,私は,「イベントは1か所にまとめるべきだ」という結論に至りました。

「ユーザーインタフェース以外からイベントは発動していない!」とルール付けをすることで,容易にコードは追えるようになります。だって,イベントは画面のクリック等と,バックグラウンドで動作するタイマー的なものだけをWinFormプロジェクトで理解しておけば,アプリケーションがどう動いているかが理解できます。

Domain層とInfrastructure層は,ユーザーインタフェース層で呼ばれない限り,決して動いてはいけないのです。