Shoeisha Technology Media

CodeZine(コードジン)

特集ページ一覧

実践WPF業務アプリケーションのアーキテクチャ【概要編】 ~ マイクロソフト公式サンプルデータベースAdventureWorksを題材に

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2018/04/10 14:00

目次

コンポーネントモデル

 本節では、本システムで実装するソフトウェアのコンポーネント分割設計と、本システムの構築にあたり利用するコンポーネントを決定します。

 本システムに登場するコンポーネントは次のとおりです。どのコンポーネントが、これまで説明したどのレイヤーに該当するのか、あわせて記載しています。

コンポーネントモデル
コンポーネントモデル

 それぞれのコンポーネントの役割を以下に記載します。

コンポーネント 役割
SystemManager 本システム内で横断的に利用される共有リソースを含みます。
具体的には従業員を表す値オブジェクトなどが含まれます。
SystemManager.Presentation Presentation層のViewおよびViewModelを含みます。
SystemManager.Services WCFサービスのインターフェースを含みます。
インターフェースの引数や戻り値に登場するクラスなどは、SystemManagerコンポーネントに含むため、インターフェースのみが含まれます。
SystemManager.WindowsService ServiceHost層のコンポーネントです。WCFサービスのロジックはSystemManager.Services.Impleコンポーネントで実装されるため、それをWindowsサービスとしてホストするための実装のみを含みます。
SystemManager.Services.Imple WCFサービスの実装コンポーネントです。
Servicesコンポーネントで定義されたインターフェースの実装クラスを含みます。
SystemManager.DatabaseAccess データベースに対するCRUDの実装するData Access Object(Dao)と、テーブルやViewと対になる値オブジェクトであるEntityクラスを含みます。
データベースへの問い合わせにはDapper及びDapper.FastCRUDを利用して行います。
Prism.Wpf MVVMパターンのサポートライブラリであるPrismのWPF用実装コンポーネントです。ICommandの実装クラスや画面ナビゲーションの仕組み、Dependency Injection Container(以降DIコンテナ)のサポートなど、多数のベストプラクティスに基づく実装をサポートします。
Prism.Autofac Pris.WPFにおいて、DIコンテナとしてAutofacを利用するための拡張ライブラリです。
Autofac 本システムのWPFサプリケーションで利用するDIコンテナの実装クラスです。
ReactiveProperty リアクティブ プログラミングをMVVMパターン上で、簡便に利用するためのライブラリです。
PropertyChanged.Fody INotifyPropertyChangedインターフェースの実装を静的コード生成するためのライブラリです。
MahApps.Metro WPFアプリケーションでMetroライクなモダンなユーザーインターフェースを手軽に実現するためのライブラリです。フラットなボタンやスイッチなどの基本的なコントロールも提供しています。
AutoMapper 類似しているが異なるクラスにたいして、値をコピーする用途で利用します。
Database Access層では、データベースへ値を設定する際や、逆に値を取得する際、一旦System.DatabaseAccessコンポーネントで定義されているEntityクラスに保持します。
WCFサービスの引数や戻り値では、SystemManagerコンポーネントで定義された値クラスを利用します。
これら非常に類似したプロパティを保持しており、値の詰め替えが頻繁に必要となるため、本コンポーネントを利用して自動的に詰め替えを実行します。
またSystemManagerコンポーネントで定義された値クラスと、ViewModelの詰め替えにも一部利用します。
Catsle.Core WCFサービスでAspect Oriented Programing(AOP)を行うために利用します。トランザクション制御や、認証処理を、サービスのメソッド群に横断的に適用するためにAOPを利用します。
SimpleInjector WCFサービスで利用するDIコンテナの実装です。
Dapper データベース操作を行うためのMicro ORMライブラリです。
Dapper.FastCRUD Dapperのみでは提供されないCRUD操作をサポートする拡張ライブラリです。

各レイヤー別にコンポーネントを分割する理由について

 各レイヤー間はすべて一方通行の依存関係にあります。

 .NET Frameworkにはnamespaceによるアクセススコープは提供されておらず、代わりにアセンブリ別のアクセススコープ(internal)が提供されています。このため、複数のレイヤーのオブジェクトを同一のアセンブリに配置した場合、依存関係が双方向になることを防ぐことができません。

 レイヤー間の依存関係が、一方通行となるように開発環境で担保するために、レイヤー別にアセンブリを分割することとしました。

ViewとViewModelを同一アセンブリした理由について

 各レイヤーを異なるアセンブリに分割したのであれば、同様にViewとViewModelも分割するべきなのかも知れませんが、今回はSystemManager.Presentationアセンブリに一緒に格納しています。

 最大の理由は、Prismの提供するVisual Studioエクステンションの機能を最大限に活用するためです。Viewを生成すると自動的に対となるViewModelを作成し、ViewとViewModelの紐づけが行われます。

 このため、ViewとViewModelを別のアセンブリに分割することは妥協しました。

 もちろん、その厳密性を優先するためにアセンブリを分割するという方針も、間違っていないと考えています。私自身、開発チームのメンバー構成や規模によっては分割することも多いです。

Prismの選定理由について

 本システムではMVVMのサポートフレームワークとして、Prism for WPFを採用しました。Prismを採用した理由はいくつかあります。

  1. 現在も積極的に開発が継続されていること
  2. 日本語の情報が比較的充実していること
  3. 多数のベストプラクティスが含まれており、自然とそれらを適用できること

 Prismはフルスペックに近いMVVMサポートフレームワークであり、テスト容易性や保守性を担保するためのガイダンスやベストプラクティスが多数含まれています。その点がPrismを選択した最大の理由です。

 私自身、Prismのその方針に共感しており、ささやかではありますがPrismにContributeしています。

 ただし逆に言うと、お仕着せ感の強いフレームワークでもあります。みなさんが各自で蓄積したノウハウがあり、そのためのライブラリやフレームワークをお持ちなのであれば、必ずしもPrismを選ぶ必要はないでしょう。

 個人的にはMVVMに馴染みが薄いようであれば、まずはPrismを使ってみて、一通り理解した上で取捨選択することをお勧めいたします。


  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • 中村 充志(ナカムラ アツシ)

     Microsoft MVP for Visual Studio and Development Technologies  東京在住のSI企業 金融事業部所属。  エンタープライズ領域での業務システム開発におけるアプリケーション アーキテクト・プログラマおよび中間管理職。  業務ではWPFお...

バックナンバー

連載:現役エンジニア直伝! 「現場」で使えるコンポーネント活用術(SPREAD)

もっと読む

All contents copyright © 2005-2018 Shoeisha Co., Ltd. All rights reserved. ver.1.5