2016年8月30日火曜日

[UWP]Winアプリストア用のロゴ画像を作成する

Androidよりもたくさん画像を用意しないといけないので、マクロで作成したい所です。
そんな人用に画像スケーリング一覧を作成しました。

サイズ制限もあるので注意しないとダメなんですが、とりあえず3種類に分けて
ロゴ、スプラッシュスクリーン、ワイドロゴの3つ作っておく必要があるようです。
あとはスクリプトで大量生産すれば完了です。


[logo]
1240x1240
620x620
600x600
465x465
388x388
310x310
300x300
284x284
256x256
225x225
200x200
188x188
176x176
150x150
142x142
107x107
100x100
96x96
89x89
88x88
75x75
71x71
66x66
63x63
55x55
50x50
48x48
44x44
36x36
30x30
24x24
16x16


[Splash screen]
2480x1200
1240x600
930x450
775x375
620x300


[wide logo]
1240x600
620x300
310x150
465x225
388x188

2016年8月24日水曜日

[C#]Async/Awaitの使い方

.NET Framework 4.5から実装されてライブラリの機能に組み込まれた async/await の使い方について書いていきたいと思います。

実装しているときに、今まで見てこなかったConnectAsync()、 PostAsync()、、~~Async()メソッド、最近ちょくちょく出てきているかと思います。

非同期処理なんだなという事は分かっても、いざ使うと同期処理と同じように使うと失敗してしまう、そんな存在です。


同期処理と非同期処理

 C#のTaskを絡めて説明すると、

  同期処理 ・・・関数の始めから最後まで実行して結果を返す処理
  非同期処理・・・関数呼ばれた段階で実行オブジェクト(Task)を返す処理
 
という感じになります、
実装例をかくと

同期処理
void Foo() {
 var result = Bar();
}

非同期処理
async Task Bar() {
 var result = await BarAsync();
}

このような差が出てきます。
また、awaitを使った場合、関数名の隣に async と関数名にAsyncを付けるルールがあります。

個人的には非同期処理を使うとき開発環境がawait付いてないぞ!ってエラーしてくれるので関数名にAsyncはいらないんじゃないかなって思っていますが、右へ倣えではないですが合わせて付けておく事が良いです。

ここまでは他サイトで詳しい説明が書かれています。

この通り使えばできそうに思えるのですが、UI画面操作が加わってくるとそうも言えない状況であるのが現状です。

なので、ここから具体的な使い方について触れていきます。


async/awaitのハマりどころ


まず理解しておかないといけないのがスレッド。
アプリケーションにはMain処理があってそこからプログラムが始まります。
その始まった時にいるスレッドをメインスレッドと命名しておきます。
このメインスレッドはUIを直接操作してもエラーになりません。

その他にThreadやTaskで実行するスレッドがあります。
このスレッドはUIを直接操作するとエラーになります。

スレッドでよく痛い目に遭うのがこのスレッド間の違いで、
始まりはメインスレッド、プログラムのバックグラウンドで別スレッドを動かし
変化を画面に通知するのでInvokeが必要になる、、、という部分で結構トラブルが発生します。

Threadだと処理内部で指示された側(関数内)で明示的にInvokeしてあげないといけなかった部分が
Taskになると、関数の呼び出し側で明示的にawaitするので解決できるようになります。

しかしここにハマりポイントがあって、

 タイマースレッドなどの別スレッド上でUIが更新できるか?

という問題があります。
もちろん、この答えは更新できません。

メインスレッド上でawaitするのは問題ないです。


まとめると、
 ・可能な限り、メインスレッド上でawaitするようにする
 ・バックグラウンドにはメインスレッドで動くDispatchTimerを使ってawaitする


Taskの始まりは必ずメインスレッドになるように実装すると間違いないです。

[C#]Disposeの使い方

IDisposableインターフェイスの正しい使い方について取り上げたいと思います。

IDisposableインターフェイスはクラスに解放処理にあたるDispose処理を追加する事が目的である。
ライブラリを使っていると、Disposeがあるとusingで使えるから便利で使う人もいると思いますが、そこからもう少し深い理由を知ると使い方の意識が変わります。

このDisposeというのは、ネイティブなリソースにアクセスして解放漏れ(メモリーリーク)を防ぐ機構です。

.net frameworkではハードウェアリソースにアクセスするもの全てにライブラリが存在していて、ユーザーは用意されたものを利用するだけで良いようになっています。

意識しなければ利用するライブラリにDisposeがある/なしでしか判断つきませんが、

 リソース開放を意識的に行わなければいけないものがそこには存在している

という視点で見ると使い方がガラッと変わってきます。

クラス実装しているときに利用するライブラリにDisposeがあれば、それを利用したライブラリにもDisposeが必要という連鎖が生まれてきます。
もしDisposeの連鎖が無かったら、Disposeリソース開放が行われなくなるのでメモリーリークが発生します。

なんとなく使っているDisposeですが、Disposeがあるから呼び出している/使っている程度ではなく
しっかりとDisposeの意味を知る事で、使い方の適材適所を身に付けるとより強固な実装が行えるようになると思います。

2016年8月23日火曜日

[C#]イベントの使い方

 日常プログラミングしていると必ず目にするイベント、View画面とかならボタンクリックなどを当たり前のように使っているイベントについてテーマをあげます。


イベントとは何か
 オブジェクト自身の変化を不特定多数に通知する1:Nの繋がりです。
相手に処理を要求するAPIような使い方で1:1の繋がりではないです。
この部分をしっかり覚えておかないとイベント処理を扱いで曖昧さが出てきます。


イベントの作り方
 対象オブジェクトにおける変化を個別に分けてイベント化する方法があります。
このイベント化する上で気おつけなくてはいけない事は、

 「変化したら通知する」

だけにとどめて置くことです。


内部で変化があったから

 「通知前後に他の処理を動かす」

というような使い方は
イベントと内部処理の依存関係が発生して外部のイベント処理にまで
影響が波及する恐れがあるので、必ず

 「変化したら通知する」

だけにとどめておくと良いです。
この時処理は一切含まれません。


余談ですが、ReactiveExtentions(Rx,Push型)はイベント処理のLinq化というものです。
実処理とは無縁の「変化したら通知する」だけのイベントをこねくり回して
新たに合成したイベントを作るという事も可能になりますね。

2016年8月21日日曜日

よりよい要件定義やソフトウェア設計をするには

よりよい要件定義やソフトウェア設計をするには

 今回はこのテーマでは設計思想やアーキテクチャ、仕様の落とし込み、
戦略や実装テクニック・デザインパターンなどといったそういった話ではなく、
アプローチの仕方について書いていきたいと思います。


要件定義とは
 顧客から世にない新しいアイデアを実現したいと要望が来たとき、
既存技術に精通している人がヒアリングして実現可能なモデルに落とし込んで文書化、そこから設計・実装へとプロセスが変化してしていくのですが
最初の仕様を落とし込む段階でホント人様々なアプローチがあって製品の良し悪しに決定的な差が出てきます。
なぜ解釈の違いが生まれるのか、同じアイデアなのに差が出るのかについて触れていきます。


それはなぜなのかを一言でいうと

 顧客は技術について詳しくない

という事に尽きると思います。


ではどういった事をしたらよいのかというと

・ゴールを決める

・ヒアリングした内容をそのまま文書化してアイデアをまとめる事で、顧客が思い描いているアイデアと実装のミスマッチを防ぐ。

・アイデアと既存技術のマッチングを行い、システムの全貌を描き概算する。


この3点をしっかり網羅しているかが重要であり、実装よりの話は出さない事。
実装よりの話を出してしまうと、それが足かせ(依存関係)が発生してどんどんこじれていくこと間違いなしです。
ということでまずはざっくり、実績ある技術の組み合わせ、次にやったことのないチャレンジ課題に分けて技術に値段をつけていきます。
ここを失敗すると、アイデアというものはナマモノなので時間が経つにつれて変化していきます。
ゴールを決めた上で課題を洗い出しておくとやりたい事が明確になり、それが目的となって簡単には仕様変更は発生しなくなります。


・目的と手段
 よくあるのが手段が目的化してしまう事です。
Aという課題を解決するのにBを使う。

これが、BをしないとAという課題が解決しない。

という具合になる事です。

より具体的な例を出すと、

画像解析で猫を認識したいので、ディープラーニングを使う。

これが、ディープラーニングを使わないと画像解析で猫が認識できない。

というような感じです。


「画像解析で猫を認識する」という事を解決するにはいろんな手段があります。

そのいろんな手段がある中でディープラーニングを選択するのは良いことです。

ですが、最初からディープラーニングを使う前提で「画像解析で猫を認識する」というのは

手段が目的化してしまったと言えます。

解決策はより簡単でシンプルなものを選べばいいところを茨の道を進んでしまったことで

結果的に失敗する可能性もでてきますので。

このケースをモデル化(言い換えれば)これも1:Nの関係といえますね。目的は1つのみ(ゴール)で、そこに様々な手段がN個ぶら下がっている状態です。

つまり目的を達成するには、沢山の手段を知っておかなくてはいけないということです。


もっと概念的な他の例でいえば

 年々国の借金は膨らんでいく問題があって、解決手段として

 「借金を減らす」ために「消費税を上げる」

これは目的と手段。


しかし手段が目的になると

 「消費税を上げる」が目的になってしまいますので、

「消費税を上げる」ために「国の借金を増やす」という手段も起こりえます。

いやはや、手段が目的化するというのは恐ろしいですね。


目的と手段の適正に使われない事がどのくらい恐ろしいことか

この事を書きたいと思い、今回はこのテーマを掲げてみました。

2016年8月20日土曜日

[C#]動的にイベントハンドラーを追加/削除する

イベントハンドラをReflectionを用いて動的に追加・削除する方法を紹介します。

いきなりソースコード。↓↓↓

---

public class test1
{
    public test1()
    {
        var m3 = typeof(test1).GetEvents()[0];
        var z3 = typeof(test1).GetMethod(nameof(func1), BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
        var x3 = z3.CreateDelegate(typeof(EventHandler), this);

        m3.AddEventHandler(this, x3);
        Notification("foo");

        m3.RemoveEventHandler(this, x3);
        Notification("bar");
    }
    public event EventHandler Event1;
    void Notification(string s) => Event1?.Invoke(this, s);
    void func1(object o, string s) => Console.WriteLine(s);
}

---

イベントハンドラは身近なところでいうと、WinFormでいうとボタンイベントなどに
使われていて、おおむね1:1の関係で使用されていますが1:Nとして使用することもできます。

1:Nができると何がいいかというと、1つのイベントをN箇所に通知する事ができるのでObserverパターン的な使い方が可能になるということです。

プログラムデザインでいえばList型のような1:Nの関係性がある時、変化を全体に通知したい場合などに使用するととても効果的です。


2016年8月12日金曜日

[C#][UWP]ViewModelを別スレッドから更新する方法(2)

前回の記事はネット上調べて見つけた方法を利用したやり方だったのだが、
よくよく考えてみると、
 モデルクラス自身が変化を通知する時、
  ・UIスレッド上ならOK
  ・別スレッド上だとNG

という事をどう解決するかでTaskのAsync/Await問題にも波及するわずわらしい問題になっている。

どうやって切り分けたら良いかを考えたら、オブザーバーパターンが有効だという事に気が付いた。

モデルクラスは別スレッドで動いていて、モデルクラスの変化を一定周期で監視するクラスをUIスレッド上で動かしておく。
こうすることでモデルクラスは手を加えずにUIスレッド上で通知する事が可能になる。

色々モデリングして動作チェックして一番シンプルなのがこの方法だったので
同じく困っている人がいたらこの方法を採用してみてください。

---

    public interface IRaisePropertyChanged
    {
        void RaiseNotify(PropertyChangedEventArgs args);
    }

    public class PropertyWatcher
    {
        public PropertyChangedEventArgs args { get; }
        Func getValue { get; }
        object self { get; }
        object value { get; set; }

        public PropertyWatcher(object self, PropertyInfo pinfo)
        {
            this.self = self;
            args = new PropertyChangedEventArgs(pinfo.Name);
            getValue = pinfo.GetValue;
        }

        public bool Check()
        {
            var newValue = getValue(self);
            if (newValue != value)
            {
                value = newValue;
                return true;
            }
            return false;
        }
    }

    public class ModelWatcher
    {
        public IRaisePropertyChanged self { get; }
        public PropertyWatcher[] props { get; }

        public ModelWatcher(IRaisePropertyChanged instance)
        {
            self = instance;
            props = instance
                .GetType()
                .GetProperties(BindingFlags.Instance | BindingFlags.Public)
                .Select(_ => new PropertyWatcher(instance, _))
                .ToArray();
        }

        public void Polling()
        {
            foreach (var prop in props)
            {
                if (prop.Check())
                {
                    self.RaiseNotify(prop.args);
                }
            }
        }
    }

    public static class ViewModelUpdater
    {
        static CoreDispatcher Dispatcher { get; set; }
        static int uiThreadId { get; set; }
        static DispatcherTimer timer { get; } = new DispatcherTimer();
        static List models { get; } = new List();

        public static void Add(ModelWatcher model)
        {
            lock (models)
            {
                models.Add(model);
            }
        }

        public static void Remove(ModelWatcher model)
        {
            lock (models)
            {
                if (models.Contains(model))
                {
                    models.Remove(model);
                }
            }
        }

        public static void Initialize()
        {
            Dispatcher = Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher;
            uiThreadId = Environment.CurrentManagedThreadId;
            timer.Interval = TimeSpan.FromMilliseconds(20);
            timer.Tick += (s, e) =>
            {
                lock (models)
                {
                    foreach(var model in models)
                    {
                        model.Polling();
                    }
                }
            };
            timer.Start();
        }

        public static async void UIInvoke(Task action)
        {
            if (uiThreadId == Environment.CurrentManagedThreadId)
            {
                await action;
            }
            else
            {
                await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, new DispatchedHandler(() => { action.Wait(); }));
            }
        }

        public static async void UIInvoke(Action action)
        {
            if (uiThreadId == Environment.CurrentManagedThreadId)
            {
                action();
            }
            else
            {
                await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, new DispatchedHandler(action));
            }
        }
    }



  //テスト用モデルクラス

    public class testmodel : INotifyPropertyChanged, IRaisePropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public void RaiseNotify(PropertyChangedEventArgs args)
        {
            Debug.WriteLine($"Update:{Environment.CurrentManagedThreadId}");
            PropertyChanged?.Invoke(this, args);
        }

        public int value1 { get; set; }
    }

---

使い方

ViewModelUpdater.Initialize();

初期化して

ViewModelUpdater.Add(new ModelWatcher(testmodel));

対象モデルクラスをModelWatcherクラスに渡してViewModelUpdaterに追加する。

監視対象から外す場合はRemoveを使う。








2016年8月10日水曜日

[C#][UWP]ViewModelを別スレッドから更新する方法

ViewModelをINotifyChangedインターフェイス経由で更新しようとすると
PropertyChangedイベントをRaiseした所でエラーになったりフリーズしたりすることがある。
UIに関する事はすべてUIスレッド内で処理しないとエラーになってしまう事など
実装するときのハマりポイントは難なくクリアしたいので、
処理コストを取っても楽するやり方を見つけたのでメモを残しておく。

方法は、UIスレッドに関する部分をUIHelperクラスに記述しておいて
ViewModel内でプロパティ更新するときにUIHelperに更新を依頼するという流れである。


----
    public static class UIHelper
    {
        static CoreDispatcher uiDispatcher;
        static int uiThreadId;
        public static void Initialize(CoreDispatcher uiDispatcher, int uiThreadId)
        {
            UIHelper.uiDispatcher = uiDispatcher;
            UIHelper.uiThreadId = uiThreadId;
        }

        public static bool IsUIThread => uiThreadId == Environment.CurrentManagedThreadId;

        public static async void Dispatch(Action action)
        {
            if (IsUIThread)
            {
                action();
            }
            else
            {
                await uiDispatcher.RunAsync(CoreDispatcherPriority.Normal, new DispatchedHandler(action));
            }
        }
    }
----

上記クラスを初期化するInitializeメソッドは
Appクラスの頭あたりで実行しておくのが良い。

UIHelper.Initialize(Dispatcher, Environment.CurrentManagedThreadId);



ViewModelの実装サンプル

----
    public class viewmodel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        bool SetField(ref T field, T value, [CallerMemberName] string propertyName = null)
        {
            if (EqualityComparer.Default.Equals(field, value)) return false;
            field = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            return true;
        }

        int _value1;
        public int value1
        {
            get { return _value1; }
            set { UIHelper.Dispatch(() => { SetField(ref _value1, value); }); }
        }
    }
----

SetFieldの処理の上にActionでくるんでDispatchに放り投げてしまう。
値1つ変更するのになんでこんなコストを払わないといけないんだろうって思ってしまうけど
安定してシンプルになるならコストを払おう。

IEnumerableとIObservableの違いについて


先に結論いいますと、

 ポーリングとコールバックの違い

です。

---ここから説明---

IEnumerableはポーリングでプログラムから任意のタイミングで状態確認しに行きます。

例えると、
 監視役Aさんが定期的に作業者Bを状態確認します。

プログラム的にいうと
 IEnumerator(Overver)がIEnumerable(Observable)の状態確認します。



IObservableはコールバックでイベント発信者が任意のタイミングで伝言ゲームのように通知します。

例えると、
 センサーAの変化イベントを全体に通知します。

プログラム的に言うと、
 IObservableがイベントのSubscribeしたユーザーに通知します。



Reactive(Rx)はイベント関数の中で全てのイベント条件をLinqで書き記すというやり方です。
従来通りのやり方だと、メインループがいて、定期的にイベントがあれば処理していくやり方です。

見えないところで処理するスレッドが「イベント発信者」、「メインループ」の違いがあるのですが、
Async/Awaitはこの点うまくできていてイベント関数を「async void」した時は別スレッドで実行させ、コールバックを待たずに投機的な実行をします。

なので、チャタリングなどが起きた場合は投機的なタスクが膨大に膨れ上がる事が予想されるので、注意ポイントになりそうです。

方向性が逆なのでどちらを主体にするかでシステム構造に合わせて実装するのが良いです。

フロントエンドはRx方式にしてバックエンドはメインループ方式というやり方もありますが、
学習コストと時間を見合うかのコスパ計算が必要です。

2016年8月6日土曜日

[UWP]async/awaitでデッドロック(deadlock/freeze)を回避する方法

今までデスクトップアプリを使っていた時は非同期処理は経験則で培った非同期処理を行っていたが、UWP世代になると非同期処理はasync/awaitでやれと言わんばかりにフレームワークの一部として実装されいれるため強要される。

どうやったら上手に向き合って解決していくかノウハウが溜まった所で記事にしておく。

いきなり使い方
 デッドロックをして困った場面など色々書きたい事はありますが、最初からやり方を知っていれば遭遇刷ることは無いのでいきなり使い方から説明します。

・Asyncと付くAPIは最終的にTask.Runで括って実行すること。
 →これがデッドロックの回避策。

・Task.Runは最後の呼び出し以外で使用しないこと。
 →途中で使ってもよいがパフォーマンスが落ちる。

・メソッドで async voidの時はTask.Runで括るは不要。
 →完了を待たない投機的な実行なのでデッドロックしない。

・戻り値がIAsyncActionWithProgressなどとなっているメソッドはその場でAsTaskすること。
 →画面上にくるくる回るウェイト画面を実装したりする場面ではAsTaskしなくてよいが、
  バックグラウンドな処理で一連のシーケンスを同期処理を書きたい場合に有効。

もちろん上記以外の方法でうまく付き合っていける方法があったら、また更新したいと思います。



エラー箇所の調べ方
 ここからはデッドロックにハマって悩んでしまった方用の処方箋。

呼び出すメソッドが
 async Task DosomethingAsync()
  {
    await Task.Delay(1);
  }

となっている場合、
呼び出し側の処理でOK/NGパターンを見るとこうなります。

-----
 void CallerMethod()
 {
   DosomethingAsync().Wait();  //deadlock
 }
-----
async void CallerMethod()
 {
   await DosomethingAsync();  //deadlock
 }
-----
void CallerMethod()
 {
   Task.Run(DosomethingAsync).Wait();  //OK!
 }


-----
async void CallerMethod()
 {
   await Task.Run(DosomethingAsync);  //OK!
 }


-----

ほんとに困ったときはその場でTask.Runで括ってすべて同期処理にして
最後にTask.Runしてタスク分けする方法もありと思います。

UWPで開発する上でどうしても向き合わなければ進まない問題なので、がんばりましょう。

2016年8月3日水曜日

MVVM式コーディング作法

プログラムには似たような用語が沢山ある。

service, task, worker, process, sequence, job,,,etc

OSやシステムによって用法が異なったりするので煩雑な部分である。
今回はそのあたりの情報整理しつつ、MVVMフレームワークでどうマッチングさせていけば良いかについて書きたいと思います。


まずシステム全体を見ると
システムの外部と内部、ユーザが触れる、触れないに分けられます。
上記用語がどの枠に属するか分類してみます。

①外部・触れる :View{ユーザ向け}
②外部・触れない :Service{公開API}
③内部・触れる :View{保守メンテ用}
④内部・触れない :Task{内部処理} = worker, process, sequence, job

こんな具合になると思います。
次にデータの流れに着目してみます。
大体はViewからデータの塊(コンテキスト)がなげられてそれをシステムが処理する流れになります。

つまり、

 job = View()

の関係が成り立ちます。

その事を踏まえて情報の流れを考えると

 ①→④
 ②→④
 ③→④

不思議な事に④に集約される関係ができあがっています。

④の部分を掘り下げていきます。

キーワードとして4つ
 worker, process, sequence, job

ありますが、Jobは外部からの入力なので引数です。

ここからコンピュータサイエンス的に表現すると、
Jobが投げられ、バッチ処理を実行して、結果が出てきます。
これを
 y=f(x)
と定義した場合、それぞれの用語に当てはめて考えると

 result = task(job)
 result = worker(job)
 result = process(job)
 result = sequence(job)

一律、同じ意味で言い回しが違うという事が分かりました。
それぞれ使う場面によって意味合いを分けてるのかもしれませんが、
汎化してTaskという用語に集約しちゃいます。


ここで情報の整理すると、
jobを作る・処理する側の2択の関係が見えてきました。

jobを作る側
 ①外部・触れる :View{ユーザ向け}
 ②外部・触れない :Service{公開API}
 ③内部・触れる :View{保守メンテ用}

jobを処理する側
 ④内部・触れない :Task{内部処理}


式に表すと
 job = ①
 job = ②
 job = ③
 result = ④(job)


システム用語で煩雑な部分が上記式で表す事ができました。

次にMVVMパターンに当てはめていきます。


viewは画面なので
viewmodelはjobになります。
jobが決まったら処理を実行する工程になります。
それが目的のtaskに対してjobを入れて実行し、
async/awaitなどで完了結果を待つということです。



task内部の作り方は以前に書いた記事もあるのですが、
見つからないので次回新たに書きたいと思います。

Androider