SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

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

2022年版実践WPF業務アプリケーションのアーキテクチャ【設計編/前編】 ~ドメイン駆動設計&Clean Architectureとともに~

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

プロセスビューの設計

 プロセスビューでは、並行性やパフォーマンス要件で、特別な検討が必要と考えられるアーキテクチャを設計します。ほとんどの場合は、.NET(async/awaitなど)やASP.NET Coreなどが担ってくれるため、それらを単純に使うだけなら特別な設計は不要です。

 今回のケースではWPFのプロセスの起動のみを設計の対象とします。というのもWPFアプリケーションをGeneric Host上で利用したいためです。

 Generic HostはASP.NET CoreなどでWebアプリケーションやWeb APIをホスティングするための仕組みです。Generic Hostでは多様な機能が提供されていますが、特に重要なのは .NET公式のDependency Injection(DI)コンテナーが含まれている点にあります。そのためモダンなサードバーティライブラリはGeneric Host前提のものが多数ありますし、今後でてくる魅力的なライブラリもGeneric Hostを対象にリリースされるでしょう。

 WPFの標準的な実装ではGeneric Hostにホストされていませんが、できないわけではありません。

フレームワークの選定

 WPFをGeneric Host上にホストするライブラリは、次の2つがNuGet上に公開されています。

  1. Dapplo.Microsoft.Extensions.Hosting.Wpf
  2. Wpf.Extensions.Hosting

 今回は後者のWpf.Extensions.Hostingを利用します。これはWpf.Extensions.Hostingをベースとしている画面遷移フレームワーク「Kamishibai」を利用したいためです。Kamishibaiは、次のような特徴をもつWPF用の画面遷移フレームワークです。

  • Generic Hostのサポート
  • MVVMパターンを適用したViewModel起点の画面遷移
  • 型安全性の保証された画面遷移時パラメーター
  • 画面遷移にともなう一貫性あるイベント通知
  • nullableを最大限活用するためのサポート

 たとえば画面遷移時に、文字列messageを引数として渡したいとします。その場合、遷移先のViewModelを次のように実装します。

cs
[Navigate]
public class FirstViewModel
{
    public FirstViewModel(string message)
    {
        Message = message;
    }

    public string Message { get; }
}

 すると専用の画面遷移メソッドが自動生成され、次のように呼び出すことができます。

cs
await _presentationService.NavigateToFirstAsync("Hello, KAMISHIBAI!");

 画面遷移でパラメーターの型不一致が発生したり、デフォルトコンストラクターが前提とならないため、null安全な実装ができる非常に強力な、現状もっとも理想的な画面遷移フレームワーク……だと思って私が開発したものです。自画自賛抜きで良くできていると思っているので良かったら使ってみてください。

 日本語のドキュメントも十分に用意しています。

コンテナー初期化とViewの分離

 通常WPFプロジェクトを作成すると、アプリケーションのエントリーポイントとXAMLは同じプロジェクト内に作成されます。しかしこの設計には大きな問題があります。

 アプリケーションのエントリーポイントでは、Generic Hostを初期化してアプリケーションをホストします。このときGeneric Hostで利用するDIコンテナーの初期化を行う必要があります。DIコンテナーの初期化を行うという事は、エントリーポイントからはソリューション内のすべてのプロジェクトを参照できる必要があります。

 そのため、DIコンテナーの初期化とXAMLを同じプロジェクトに配置すると、XAMLから本来は触る必要のないオブジェクトを操作できるようになってしまいます。これを防ぐためには、エントリーポイントとViewのプロジェクトを分離する必要があります。

 また実のところ、Web API側でも同じ問題があります。ASP.NET CoreのDIコンテナーの初期化処理と、VendorRepositoryServiceクラスを同じプロジェクトに配置すると、VendorRepositoryServiceから不要なオブジェクトを参照できてしまいます。そのためWPF・Web APIともに初期化処理を分離しましょう。これは実装ビューで表現します。

実装ビューの更新

 更新した実装ビューは次の通りです。

 WPFとWeb APIの初期化処理を実施するProgramクラスを含む、それぞれAdventureWorks.Purchasing.WpfとAdventureWorks.Purchasing.AspNetCoreというプロジェクトを追加しました。

 またWPFで重要となるAppクラスをViewのプロジェクトに含めることを合わせて明記しました。テーマやスタイルなどを適用するためには、View側にないと不都合が多いためです。

配置ビューの更新

 配置ビューも更新しましょう。

 AdventureWorks.Purchasing.WpfとAdventureWorks.Purchasing.AspNetCoreを追加して依存関係を整理しました。

まとめ

 さて、これでやっとユースケースや非機能要件を設計する準備が整いました。なかなか大変でしたね。ただ、ここまでの設計はシステムに依存しない部分が多いため、次回以降はそのまま流用できる部分が多いです。

 今後、次のような内容で進めて、アーキテクチャ設計を完成に導きたいと思います。

  1. 代表的なユースケースの実現
  2. 非機能要件の実現
  3. 開発者ビューの設計

 ここまでお付き合いありがとうございました。再びお会いしましょう!

関連リンク

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加
現役エンジニア直伝! 「現場」で使えるコンポーネント活用術(SPREAD)連載記事一覧

もっと読む

この記事の著者

中村 充志(リコージャパン株式会社)(ナカムラ アツシ)

 Microsoft MVP for Visual Studio and Development Technologies リコージャパン株式会社 金融事業部 金融ソリューション開発部所属。 エンタープライズ領域での業務システム開発におけるアプリケーション アーキテクト・プログラマおよび中間管理職。 業務ではWPFおよびASP.NETを用いた業務システム開発が中心。 SI案件において、テスト・保守容易性を担保した、アーキテクチャ構築を得意としている。 GitHub:https://github.com/nuitsjp Twitter:@nuits_jp 著書 『Essential Xamarin ネイティブからクロスプラットフォームまで モバイル.NETの世界』(共著) 『Extensive Xamarin ─ひろがるXamarinの世界─』(共著)

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

提供:グレープシティ株式会社

【AD】本記事の内容は記事掲載開始時点のものです 企画・制作 株式会社翔泳社

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/17633 2023/05/25 20:39

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング