SE(たぶん)の雑感記

一応SEやっている筆者の思ったことを書き連ねます。会計学もやってたので、両方を生かした記事を書きたいと考えています。 でもテーマが定まってない感がすごい。

UWP挑戦記 その2 用語とかを解説してみる

前回の記事で、

UWPPrismが無いとマゾい

という内容を書きました。

hiroronn.hatenablog.jp

別に反響とかなかったですけど、現在、記事にも書いた通り、Prismの勉強をしています。
ただ、そう考えると、WPFもやったことがない人にとって、UWPを始めるまでの壁が高いのでは?と、ふと思いました。

というわけで、UWPPrismを使う上で、たぶん前提として知っておいたほうが良い仕組みや、用語について考えてみます。

参考資料は以下の通り。

Download C#、XAML、Windows ランタイム向けの Prism を使った Windows ストア ビジネス アプリの開発 from Official Microsoft Download Center

なお、C#で、UIをXamlで記述する場合を対象にしています。
JavaScript等を利用される場合は、申し訳ありませんがお役に立つ記事ではないと思います…

MVVMパターンについて

元をたどれば、MVCパターンから派生したものです。
フレームワークレベルで採用しているものとしては、Ruby on RailsASP.NET MVCあたりですかね。

UWPでは、Microsoftが出している単体のフレームワークには、アーキテクチャへの言及はありません。*1

ただ、よっぽど単純なシステムでない限り、MVVMパターンに則るべきです。*2

MVVMは、画面をModelViewViewModelに分けて開発する手法だよ!
と言っても仕方ないので…もっとざっくり説明してみます。

f:id:hiroronn:20170518212350p:plain

上の図を説明すると、

  • ViewModelは、ViewとModelを仲介する
  • 表示すべきデータ等は、Modelが持っている(取ってくる)
  • Viewは、ユーザーの入力をViewModelに渡し、また、ViewModelのデータを表示することに専念する
  • ViewModelは、ModelのデータをViewが扱いやすい形式にする
  • 基本的には、片方向への参照しか持たない

といった感じです。

ただ、そもそもなんでこんなに面倒なことをやるのか?と思われる方もいるかもしれません。
特にWindows Formしか経験がない、という方とかは特に。

これは、一言で言うなら、「画面に処理を書いたって、なにもいいことがない」からです。

まずは、画面にロジックを書くと、そのロジックを検証するのに画面を動かすしかないです。
テストが自動化できない。

そして、Viewは画面という、すごくざっくりした説明しかしていませんが、Viewはいわゆる「ユーザーインターフェース層」であり、役割はユーザに情報を表示して、ユーザのコマンドを解釈することです。*3

たとえば、画面で手入力できるデータを

ファイルで読み込みたい!

とか

ファイルに書きたい!

とか、はたまた

他のシステムから連携させたい!

等の処理を作る必要が出た場合、表示データの計算等をすべて画面がやっているとどうなるか…
さて、そうなった画面を、今度はモバイルで使えるようにしてみましょう。*4

DI(Dependency Injection:依存性の注入)

いくつかリンクを貼ります。

依存性の注入 - Wikipedia

qiita.com

個人的には、『C#実践開発手法』の説明が好きです。*5

honto.jp

DIは、要するに「そのクラスが使うものは、外部から渡す」ことを言います。(だから、「注入」という言葉が使われる)

ソースはこんな感じです。
(仮想ケース:項目が追加されたらメールを送る)

//DI未使用
public class BoardNotDI {
    public void Add(Item item){

        //~なにがしかの追加処理

        var mailer = new MailSender();

        mailer.Send(receiverInfo);
    }
}

//DI使用
public class BoardDI {
    //IMailSenderは、インターフェイス
    private IMailSender _mailer;
    
    public BoardDI(IMailSender mailer) {
        _mailer = mailer;
    }

    public void Add(Item item){

        //~なにがしかの追加処理

        _mailer.Send(receiverInfo);
    }
}

C#実践開発手法』では、クラス内で独自にnewインスタンス生成するのを推奨していません。理由は以下のような感じです。

そのクラスに依存するからやめろ
単体テスト(自動テスト)できなくなるからやめろ
ソース見ないと何に依存しているか分からなくなるからやめろ
サービスの依存関係に依存するからやめろ
他のサービスを柔軟に利用できなくなるからやめろ

『レガシーコード改善ガイド』には、依存性に関して、以下の記述があります。この表現大好きです。

メソッドに悪い副作用(データベースの更新、巡航ミサイルの発射など)があり、テストハーネスで実行することが不可能である

「巡行ミサイルの発射 = メールの送信」です。
単にソースコードのテストしたいだけなのに、毎回実際のメールが送られたり、ミサイルが飛んでいったりしたら、たまったものではありません。

インターフェイスを渡すと、それをテスト用の実装に入れ替えることで、そのクラスが単体テスト可能になります。
とまあ、たったこれだけのことです。

DIコンテナ?その説明はまたいずれ…

非同期処理

UWPでは、ファイルアクセス等、時間がかかる可能性がある処理は、ほとんど非同期用のライブラリばかり用意されています。*6

そういうわけで、async, awaitTaskは、当たり前のように出てきます。

これに関しては、以下の記事が秀逸だと思います。見てください。というか、ネットで探すといっぱい出てきます。

qiita.com

qiita.com

TaskWaitはしない、と書かれていました。そうだね。awaitあるもんね。

非同期処理がない言語や、スレッドを直接扱う方法しかない言語を知っている身ですので、本当にありがたい機能です。*7

ちなみに、匿名メソッドにもasyncは書けます。

最後に

まずは最初に、というところでは、上のようなものでしょうか。
思いついたことがあったら、また記事にします。

余談

そもそもUWPの記事を書き始めたときの記事が、ありがたいことに、なぜかアクセスが伸びました。
Googleでキーワード検索したら、なぜか一番上に出てました。なるほど。

偶然です。
今後も、誰かに何か役に立つ記事を書けたらいいな、と思った所存でございます。

今回の記事、長すぎ…

*1:ありませんが、明らかにMVVMパターンを使え、という意図はある

*2:Viewが非常に強力なデータバインド機構を持っているし、描画で複雑なことをやろうとすると、ソースコードよりXAMLデザイナーのほうが簡単に書ける場合が多いため

*3:厳密には、ViewModelもユーザーインターフェース層に属する

*4:無理です

*5:C#って書いてあるけど、C#やってない人でもお勧めの本

*6:確か、マイクロソフトの解説に記述がある。場所思い出したら貼ります

*7:例外処理が難しいように思う。あと、進捗状況を簡単に出せるサンプルとか欲しい