modest violet

読者です 読者をやめる 読者になる 読者になる

modest violet

開発者としてのあれこれや、日々の雑記など

your future hasn't written yet. no one's has.
by Emmett Lathrop "Doc" Brown

AutoMapper6でのプロファイル設定とユニットテスト

Dev Dev-C# Dev-技術メモ

AutoMapperという自動マッピングライブラリーが便利なのです。ただ、少しばかり使い方を誤っていたようで、下記のサイトを参考に再勉強させて頂きました。

iyemon018.hatenablog.com

この記事のお陰で、今までの自分があまりにも恩恵を受けない無駄な記載をいっぱいしていたという事に気づきました。例えば、逆マッピングもわざわざ定義を書いていたとか、同じ名前のオブジェクトもわざわざ定義書いていたりだとか・・・。

いざ自分でも定義をプロファイル単位にしようと試していたのですが、どうも仕様が違っている様子・・・。
最新のAutoMapperは6.0.2になっており、プロファイルのオーバーライド辺りが変更になっていたようです。ですので、自分の備忘録も兼ねて手順を記載します。

マッピングの定義

以前のAutoMapperでは、Configure()メソッドをオーバーライドして定義を書いていましたが、バージョン6以降は互換がなくなったようで、コンストラクターに定義を記載する事になります。

public class HogeProfile : Profile
{
    // コンストラクターでマッピング定義を記載します
    public HogeProfile()
    {
        CreateMap<SourceClass, DestinationClass>()
            .ForMember(d => d.XXXXXXXXXX, o => o.MapFrom(s => s.YYYYYYYYYY))
            .ReverseMap()
            .ForMember(s => s.XXXXXXXXXX, o => o.MapFrom(d => d.YYYYYYYYYY))
            ;
    }
}


上記のように、必要な定義ごとにクラスを分ける方が管理しやすくて良いと思います。以前一つのクラスの中に定義をまとめて書いていたのですが、数が多くなると判りにくくて仕方が無いという経験からの意見です。

作成したプロファイル設定は、ASP.NET MVCであればGlobal.asaxなどに呼び出しの記述を行います。

Mapper.Initialize(config =>
    {
        config.AddProfile<HogeProfile >();
        config.AddProfile<HogeHogeProfile>();
    });

// マッピング設定の検証
Mapper.AssertConfigurationIsValid();

マッピングユニットテスト

基本的にそのまま値の受け渡しが行われるので、ユニットテストは不要という考えもできます。
但し、型が違うことによりAutoMapperで変換をかけたり、固定値を入れたりなど絶対不要か、といえばそうでも無いと思います。ユニットテストを書く癖をつけるためにも書いてみました。

簡単ですが、MSTestで書いたテストクラスはこんな感じです。

[TestClass()]
public class HogeProfileTests
{
    [ClassInitialize]
    public static void ClassInit(TestContext context)
    {
        Mapper.Initialize(config =>
        {
            // Global.asaxの呼び出し代わりにClassInitializeでプロファイルを呼び出しておく
            config.AddProfile<HogeProfile>(); 
        }); 
    }

    [TestMethod()]
    public void マッピング設定の検証()
    {
        // マッピングエラーならException
        Mapper.AssertConfigurationIsValid();
    }

    [TestMethod()]
    public void コピー元からコピー先へのマッピング検証()
    {
        var srcModel = new SourceClass()
        {
            // コピー元の値を適当に設定
        };

        var destModel = Mapper.Map<DestinationClass>(srcModel);

        // コピー元とコピー先で値が同じか
        Assert.AreEqual(destModel.xxxxxx, srcModel.xxxxxx); 

    //以下・・・省略
    
    }


    [TestMethod()]
    public void コピー先からコピー元への逆マッピング検証()
    {
        var destModel = new DestinationClass()
        {
            // コピー先の値を適当に設定
        };

        var srcModel = Mapper.Map<SourceClass>(destModel);

        // コピー元とコピー先で値が同じか
        Assert.AreEqual(srcModel.CategoryId, destModel.CategoryId);

        //以下・・・省略

    }
}


名前や型が同じプロパティー部分は比較検証しなくてもいいかな、というのが率直な感想です。
AutoMapperで何かしらのマッピング定義を施した箇所を中心にテストを作成するのが合理的だと思います。

20年以上使っていてはじめて知ったWindowsの機能

Windows

2017年4月11日をもって、Windows Vistaの延長サポート期間が終了しました。
私自身もよくよく考えると、Windows利用歴が20年以上なんですよね・・・。文字にすると恐ろしいな・・・、20年かぁ・・・。

さて、それだけ長年Windowsに触れてきた訳ですが、まだまだ知らないこともたくさんあります。

つい最近も、偶然に知ったWindowsの機能に驚愕していたところです。本当に奥が深いよ、Windows

メッセージボックスに隠された機能

f:id:shin21sk:20170412190524p:plain

よくあるメッセージボックスです。これは、何かを書きかけている最中に閉じるボタンを押すと表示される「よく見かける」メッセージです。

この一見、何の変哲も無いメッセージボックス。

タイトル欄辺りをクリックして、メッセージボックスが選択されている状態にします。

そのまま、Ctrl + C キーを押してクリップボードにコピーします。

そして、適当なメモ帳などを新規で開いて、貼り付けを行うと・・・

[Window Title]
メモ帳

[Main Instruction]
無題 への変更内容を保存しますか?

[保存する(S)] [保存しない(N)] [キャンセル]


テキストとして、コピペができたんです!!


知っていました?かなり衝撃的だったんですけど・・・。

メッセージボックスでエラー内容とかいちいち見ながら打ち込んでたあの日は一体なんだったんだ!?と。


余談ですが、Excelのメッセージボックスではできませんでした・・・。パターンがあるのかな。

【Azure】Microsoft Cognitive ServicesのFace APIを検証したキロク

Azure Dev

2017.03.28 大幅加筆しました。

f:id:shin21sk:20170327183607p:plain

Microsoft AzureにはCognitive Services(コグニティブサービス)といって、視覚や聴覚などAI技術を利用して認識を行う超絶便利なサービスがあります。

今回はその中で顔認識「Face API」を利用し、公式ドキュメントの曖昧な部分を検証しました。

Face APIに関しての詳細は、マイクロソフトの公式ドキュメント(英語)をご確認ください。

Microsoft Cognitive Services - Documentation

この通りに実装すれば、いとも簡単に顔認証ができます。本当に、Azureはヤバいです。

FaceAPI Freeプラン

FaceAPIにはFreeプランが存在します。ちょっとした評価や簡単な実装であれば問題ないのですが、少し本格的なサービスを実装しようとするとFreeプランのままでは制約が多いと感じました。
特に最初に判らないのは「トランザクション」の概念かと思います。

レベル 機能 料金
Face API - Free 1 分あたり 20 トランザクションまで 30,000 無料トランザクション / 月
Face API - Standard 最大 10 トランザクション/秒
0 - 1,000,000 トランザクション \153/1,000 トランザクション
1,000,001 - 5,000,000 トランザクション \112.20/1,000 トランザクション
5,000,001 - 20,000,000 トランザクション \66.30/1,000 トランザクション
フェイス ストレージ フェイス ストレージ - 各画像のサイズ上限は 4 MB 画像 1,000 枚あたり月額 - \51

出典
価格 - Face API | Microsoft Azure

ここで挙げられている「トランザクション」とは、何かしらの命令をFaceAPIに送る度にカウントされます。
例えば公式サンプルの記載では、顔認証完了までに最低3トランザクションが必要となっています。

using (Stream s = File.OpenRead(testImageFile))
{
    // 画像ファイルの認証 ->これで1トランザクション
    var faces = await faceServiceClient.DetectAsync(s);
    var faceIds = faces.Select(face => face.FaceId).ToArray();

  // 顔の認証 -> これで2トランザクション
    var results = await faceServiceClient.IdentifyAsync(personGroupId, faceIds);
    foreach (var identifyResult in results)
    {
        if (identifyResult.Candidates.Length == 0)
        {
            Console.WriteLine("No one identified");
        }
        else
        {
            var candidateId = identifyResult.Candidates[0].PersonId;

      // Person情報の呼び出し -> Loop毎にトランザクション数加算
            var person = await faceServiceClient.GetPersonAsync(personGroupId, candidateId);
        }
    }
}

これ以外にも、削除処理でも1件に付き1トランザクションとなりますので、不要なデータを削除したい場合でも注意が必要です。 

Freeプランでは、「1分間に20トランザクションまで」という制約がありますので、ちょっとしたサービスを構築するだけでもスグに上限値には達しそうです。

FaceAPIの階層構成

FaceAPIで写真を登録する場合、実際は3階層に分かれているのですが、サンプル通りに実装すると2階層までしか意識しなくても良い書き方となっています。お手軽に作成する分には何も問題はないのですが、原理を知りたいとか構成を知りたいとか行った場合には気になる所です。後述しますが、FaceAPIは「登録上限数」があるので、階層でどれくらい登録できるのか?は押さえておいて損はないと思います。
具体的には、「PersonGroup」「Person」「PersonFace」の3階層となっています。

f:id:shin21sk:20170328115410p:plain

1.PersonGroup階層

人物のグループを登録する為の階層です。認識の際は、このグループ内で合致する顔があるかどうかで検索が行われます。

最大1,000個のPersonGroupを作成する事が可能です。

PersonGroupには一意のpersonGroupIdが必要で、任意の文字列で登録することが出来ます。但し、使用出来る文字には制約があり数字、英字(小文字)、'-','_'が使用出来ます。特にこだわりがないのであれば、GUIDを作成しその値で作成すると良いと思います。

詳しくは、下記APIリファレンスを参照ください。
Microsoft Cognitive Services

2.Person階層

人単位のグループです。例えば、山田太郎さんの顔写真(複数)を管理する階層です。
新規登録時、PersonIdがGUIDで作成されます。同じ人物に画像を追加する場合はこのGUIDを保持しておく必要があります。

Person情報は、PersonGroup階層下に1,000ユーザー分作成可能です。1,000件を超えるとエラーとなる為、別グループへ登録する等の考慮が必要です。

3.PersonFace階層

人物の顔情報データです。(1画像毎に作成される)

一人の人物に対して、複数枚の画像を登録出来ます。理由としては、同じ人物に複数の顔写真を登録する事により、顔認証の精度が向上する事が可能な為です。
可能であれば、正面を向いた顔・側面・眼鏡の有無などの写真を登録すれば、より精度を高めることが出来ます。

但し、登録に際しては制約条件が数点あります。

  • 登録可能な数は1ユーザー毎に248件
  • 画像の種類は、JPEGPNG、GIF(最初のフレーム)、およびBMPがサポート
  • イメージファイルのサイズは、1KB以上4MB以下
  • 検出可能な顔のサイズは、36×36〜4096×4096ピクセル


特に写真で撮った画像をそのまま認証させたい場合など、画像サイズに注意が必要です。

削除時は下位層を考慮する

FaceServiceClientには各Deleteメソッドが準備されています。

例えば、PersonGroupを削除する場合は「DeletePersonGroupAsync」といった具合です。

但し、上位のPersonGroupを削除したとしても、下位層の「Person」「PersistedFace」は残ったままとなります。

よって、上位を削除する際には、下位層のデータを削除してから消すといった一手間が要りそうです。


削除も1件=1トランザクションで課金の対象となる為、敢えて残すという選択肢もあるとは思います。

値の無いデータは全てNotFoundでExceptionがスローされる

GetPersonGroupAsync等で指定した値に該当するデータが無い場合、nullでは無くExceptionがスローされます。

この辺りは善し悪しなのですが、個人的にはnullで返ってきてもらった方が慣れているので、一手間を加えて使用しています。

まとめ

もう何点か検証中項目がある為、随時更新していきます。

一つ言えるのは、Azure楽しい♪という事です。

一瞬…!! だけど… 閃光のように…!!!

雑記

学生時代は勤勉でもなんでもなく、どちらかというとノートを写させて貰う事のほうが多い、怠惰な学生だったと思います。
社会人になった後も、仕事の忙しさにかまけて自己啓発は無駄だと考えていた時期もありました。

そんな僕ですが、今では勉強をしていないと何か落ち着かない気分になるので、不思議なものです。
とはいっても四六時中勉強なんて出来ませんので、隙間時間を有効活用するようになったという方が的確かもしれません。

色々と勉強に至るキッカケはあったのですが、「転職」が大きなきっかけだったと思います。

会社にとって自分は必須ではない

現役バリバリで自分しか出来ない事をやっていると「自分はこの会社にとって、必要不可欠な人材」「自分の代わりなんて誰もいない」と思いがちです。現に僕もそう思っていた時期もありました。でも、その会社を辞めて、辞めた後の状況を聞いても大抵なんとかなっているんですよね。

自分は必要不可欠と思っていたのは自分だけであり、会社からしてみれば僕は「必須」の存在ではなかった訳です。

『自分は特別ではない』
『自分の代わりは要る』

わりと衝撃的なこの事実。現にリストラが社会問題となった当時は、脱力する方も多かったようです。

この観点が僕自身の勉強しなくては!という意志の開花につながりました。

書面での第一印象

『資格なんて実業務に使えないから取っても意味がない』という意見をよく聞きます。
確かに資格試験、特に情報処理系の資格はほとんど無意味な場合が多いです。

ですが、ある時ふと気付きました。
『未来永劫今の仕事で食べていけるという保証はどこにもない。』
『終身雇用なんてハナから期待していない自分にとって、ある日突然解雇されたら?』

自分には自分のスキルを客観的に評価出来る指標がない事に気付きました。そう、資格試験とはスキルを客観的に評価出来るツールだという事に気付けた訳です。
履歴書に資格欄が空白と記載有りなら印象が違います。年齢が上になればなるほどジワジワと効いてくる箇所です。

書面での第一印象で『客観的』に判断出来る資格試験の勉強へと繋がっていきます。

明日が来る事を当たり前と思わない

流通ジャーナリストで金子哲雄さんという方がおられました。2012年に肺カルチノイドという症例が非常に少ない病の為、41歳という若さでこの世を去られました。

僕自身、この方がテレビによく出演されていた頃はあまりいい印象はなく、軽い内容を面白おかしく吹聴しているな、という認識でしかありませんでした。ですが、僕の認識はお恥ずかしい限りで、金子哲雄さんは努力の塊のような人で、無くなる直前まで仕事を行い、自分のお葬式まで自分で手配・プロデュースしたのです。

この話を聴いた時、今までの認識を改め、尊敬の念を抱かずにはいられませんでした。

この本は、金子哲雄さんの死後に出版された手記です。

『自分が70歳、80歳の頃どうなっているかを前は想像していたのに、想像する事が出来なくなった』というニュアンスが非常に胸に刺さりました。

明日が来ることが当たり前に感じていますが、それはとても特別な事なんだという思いがひしひしと伝わってきます。

こんなに生を渇望している人がいる傍ら、僕自身は毎日を無駄に浪費しているのではないだろうか・・・。

いつの頃からか、そう感じるようにもなりました。

「あの時こうしていれば」「この時こうだったら」と現在テレビで「東京タラレバ娘」というドラマをしているそうですが、「たられば」ばっかり言っていても仕方が無い訳です。
この世の中には生きたくても叶わず亡くなられた方が大勢いる。そんな人達に失礼のないように一生懸命生きなければ!というのが僕が出した結論でした。

一瞬…!! だけど… 閃光のように…!!!

少年時代はよく漫画を読んでいました。今でも昔の漫画は読み返しますが、勇気をくれるフレーズというのがたくさんあります。
大人になってより感銘を受けるセリフも多く、漫画は偉大だなぁと感じます。

そんなセリフの中でも、好きなフレーズです。

f:id:shin21sk:20170219231715j:plain

5つか6つのとき…だったかなぁ…
あるときオレは「死」について考えだした。死んだらどうなるのかどこへ行くのか。考えれば考えるほどこわくなって…夜中におれは泣き出した。親父たちがびっくりして飛び起きた。
『どうしても人は死んじゃうの!? どうしてずっと生きていられないの!?』
わけがわからなくなって おれは泣きわめき続けた。
…そしてら母さんが…母さんがオレを抱きしめてくれてこう言ってくれたんだ。
『人間は誰でもいつかは死ぬ… …………だから』
『だから……みんな一生懸命生きるのよ』……って
『あんたらみてえな雲のうえの連中に比べたら おれたち人間の人生なんてどのみち一瞬だろう?』
『だからこそ、結果がみえてたって もがきぬいてやる!!!』
『一生懸命生き抜いてやる』
『残りの人生が50年だって5分だって 同じことだっ!!!』
『一瞬……!!だけど……閃光のように!!!』
『まぶしく燃えて生き抜いてやるっ!!!』
『それがおれたち人間の生き方だっ!!!』
『よく目に刻み込めよッ!!! このバッカヤローッ!!!』

ダイの大冒険より

振り返れば、僕自身の人生なんて一瞬の出来事です。
それも歴史には何の影響も与えないちっぽけな存在です。
だからといって、なんとなく日々を暮らすのはどうかなと。
ブログを始めたのも、今になって思えばそんな想いがあったからなのかもしれません。

『自分に出来ることを一生懸命やる』

そんな当たり前の事を大事にしていきたいと、金子哲雄さんの本をあらためて手にして感じた気持ちをそのまま書いてみました。

僕がCDコレクターをやめた理由

雑記

f:id:shin21sk:20170208194018p:plain

数年前まで、僕はCDのコレクターでした。

初回生産版をこよなく愛し、持っていない限定版は中古屋を巡ってまで手に入れるほど必死でした。
これは自分の性分なんだと。きっと、一生こんな感じなんだろう。まぁ、それはそれでいいかなとか思うほどに。

でも、ある時を境に一気に熱が冷めました。

それは、あるアーティストの新譜アルバム発売の時です。

・初回限定版A(DVD付き・アナザージャケット)
・初回限定版B(DVD付き・アナザージャケット※Aとは内容が違う)
・初回限定版C(ボーナストラック1曲・アナザージャケット)
・通常版   (ボーナストラック1曲※Cとは内容が違う)

あれ?これって単に搾取されてるだけじゃない?

「ファンなんでしょ?好きなんでしょ?じゃあ全部買うよね当然」的な。

この時点で、シングルCDならばまだ許容出来ていたと思います。
ただ、アルバムでこういう仕打ちはなかなかに酷い。

「応援しているアーティストだから複数枚買う」というファン心理は良くわかっているつもりです。

それは、ファンが自ら同じCDを複数枚買うというのであれば、個人の嗜好なので問題はないと思うのです。

ただ、そういったファン心理につけ込んで、販売する側が「ファンなら全部買うでしょ?」という感じで販売するようになったのが、ただただ悲しい

そう遅咲きながら気づいてしまった事により、僕はコレクターを卒業しました。

初回生産限定販売

今でもこの販売方法が多いのかは判らないのですが、一時期「初回生産販売のみの限定版」というのが流行った時期があります。

それを買いそびれると二度と手に入りませんよ、といった類いの商品です。

これは本当に意味がわかりません。

買いそびれたり、後になってそういった商品があったことを知り、欲しくても手に入らない訳です。

中古屋もしくは転売屋しか儲からない。

有名な所ではBOΦWYの「COMPLETE」という製品です。

定価が2万円に対して、1999年頃には10万円*1というプレミア価格がついていました。

BOOWY COMPLETE ?21st Century 20th Anniversary EDITION?

BOOWY COMPLETE ?21st Century 20th Anniversary EDITION?

後に、COMPLETE 21st REMASTER EDITION が発売となり、またインターネットオークションの台頭でプレミア価格は下落し、今では5,000~10,000円で買えるようです。


かくいう僕も、TMNが1994年終了時に発売した限定BOX「GROOVE GEAR」をプレミア価格で買った思い出があります。

定価が1万円だったのに、確か4万円近くで購入したと思います。

これを買うために必死にアルバイトをした記憶が・・・。

今だと3,000円くらいで買えてしまうようです。

それでも良き思い出として残っているのですから、コレクターは怖いです。

このように、「本当に欲しい人が困って」しまうのが、初回生産限定販売なのです。

出来れば、この形の販売は無くなって欲しい所です。

複数パターン販売

これは、大きく分けて2パターンあります。

1.内容は同じでジャケットなどが違うケース

CDの収録内容は同じで、ジャケットが違うなどのケースは、まだ割り切りが出来ます。

有名なのは安室奈美恵の「SWEET 19 BLUES」が4種類のジャケットで販売し話題になりました。

SWEET 19 BLUES

SWEET 19 BLUES

ただ、収録内容は一緒なので、自分の好きなジャケットを選べば良いだけという考え方も出来ます

どちらかというと僕は、曲をコンプリートしたいというコレクターだったので、ジャケットだけの相違にはあまりこだわりが無かっただけなのかもしれませんが。

とはいいつつ、これもTM NETWORKになりますが、「Major Turn-Round」というアルバムがあります。

Major Turn-Round

Major Turn-Round

恐るべき事に、通販限定かTSUTAYA、新星堂のみでの販売。
しかも、それぞれで特典が異なるという悪行w
さらにさらに、通販版はピクチャーレーベルが4種類でもちろん何が入っているかは判らないといった悪魔のような所行で販売されました。

もちろん、複数枚買いましたけども。

はい、コレクターだったので。

ちなみにこの段階では、まだまだバリバリのコレクターです。
売り方はアレでしたが、かなりの名盤だと今でも思っています。

余談になりますが、思った通り通販で購入した「Major Turn-Round」は同じピクチャーレーベルが何枚もダブりました。当時はYahoo!オークションが黎明期で全体的にまだまだ緩かったので、「交換オークション」という手法で交換したりしてました。

2.収録内容が違う、DVD有無などのケース

これは、冒頭に書いた通り、僕をコレクターから卒業させてくれた販売方式です。

初回版・通常版の2パターンくらいなら、致し方ないとは思えます。

ただ、初回版にAやらBやら複数パターンを設けて、さらに通常版には違うボーナストラックを入れるとか「何か違うんじゃないの?」と思わずにはいられない訳です。

アルバムCDは3,000円近くします。

学生には大金です。それを何種類も買うかとなると買わない、買えないわけです。さらに、初回版は色々ついてきて5,000円を超えるケースも。

音楽CDに5,000円はさすがにやり過ぎな感が否めません。

そりゃあCD売れずに、音楽ダウンロードに走るよなと。

結局の所、必ず買ってくれる人たち。そう、固定ファンの人たちに、買わなくなった人の分まで買ってもらわないといけないので、同じCDを少しバリエーション違いにして販売しているのでしょう。

コレクターだった僕の目を覚ましてくれるくらい酷い状況だと思っています。

f:id:shin21sk:20170208194033p:plain

個人的には握手券付きCDの販売も、同じ部類に入ると思っています。

閉塞する音楽市場

音楽は今でも好きなので、歌謡祭とかのテレビは今でもよく見ます。でも、最近の曲がほとんど無いんですよね。

昔に流行った曲をカバーしたりとかが結構多い。

1990年代後半から音楽シーンが劇的に変わったという印象が全くないんです。

f:id:shin21sk:20170208194058p:plain

1970年代はフォークソング、1980年代はロックや台頭し、90年代初頭はポップな曲が多くありました。

2000年に入る頃にラップが流行り、少し変わったかな~と思った事もありましたが、結局2017年の今、目新しさが無いわけです。

音楽CDの扱いが低くなっているからなのかもしれません。

おわりに

僕の今の人生はたった1枚のシングルCDで変わりました。

これは過言でもなんでもありません。

そんな思いがけないきっかけで、人の人生を変えてしまえるほど音楽というのは素晴らしい物だと思っています。

音楽を手にする事が出来るCDという媒体が「大人の事情」で、若い世代に疎遠になっているのであれば、悲しい事だと思います。

今必要なのは、初回版でも特典でもなく、小学生でも買える価格(つまり日本のCDは高い)にする事だと僕は思います。

*1:COMPLETEには黒番と再販の白番があり、黒番が特にプレミアだった