ほげほげ(仮)

仮死状態

2016年に買って良かったもの

Pebble Time Round

つい最近Fitbitに買収されPebbleブランド消滅のお知らせがあって非常に残念です…

本当に気に入っていて、お風呂以外はずっとつけています。歩数や睡眠もそれなりに取れていてかなり便利です。Androidの通知も受け取るようにしてるので、いちいち端末を取り出す必要なく確認できるのも非常に良いです。

来年またPebbleで買おうと思ってたんですけどね…どうしよう…

iPad Pro

iPad Pro - Apple(日本)

前使ってやつがホームボタン効かないし、反応悪いしで買いました。ついでにApplePencilも。

基本的にKindleで本かマンガしか読んでないですけど…

ApplePencilはKindleでマーカみたいなのをつけるときに使ってます。

Withings 体重計

これまでほとんど体重を測っていなかったのですが、歩数とか睡眠は計測し始めたのでついでに体重も計測し始めました。

Android端末と連携させておくだけで、あとは体重計に乗るだけで勝手に記録していきます。IFTTTとも連携できるのも強いです。

MESH Moveタグ

IoTデバイスですね。動きを検知して色々できます。

ぼくはこれを自宅の鍵の監視として使っています。詳しくは前に記事を書いたので、そちらを見てください。

MESHを使って鍵の閉め忘れをなんとかする - ほげほげ(仮)

ネスカフェ ドルチェグスト

12月のCyberMondayで半額くらいになってたので、勢いで買いました。

たまに美味しいコーヒー飲みたくなるので、これは手軽で非常に良いです。勢いで買ったけど、気に入ってます。

PlayStation®VR

PlayStation VR PlayStation Camera同梱版

PlayStation VR PlayStation Camera同梱版

かれこれ1ヶ月以上使ってないですが、良いです。未来を感じます。

友達が遊びに来て、サマーレッスンで一生懸命スカートの中を覗くのを横から眺める体験ができます。

REGZA 43Z700X

43インチの4Kテレビです。PS4Pro買うのにあわせて買いました。

前のが32インチだったので、画面も大きくなって満足度が高いです。

あと、今のテレビってHDDつけると録画してくれるんですね。今までBDレコーダーを使ってたんですけど、起動も動作も遅くて不満だらけでした。でも、今のテレビで録画もするようにしたらサクサク動いて快適です。BD見るのはPS4あるので、BDレコーダーは捨てようと思います。

PlayStaion4 Pro

PlayStation 4 Pro ジェット・ブラック 1TB (CUH-7000BB01)

PlayStation 4 Pro ジェット・ブラック 1TB (CUH-7000BB01)

品切れ続いてるみたいですが、ぼくは予約開始と同時に速攻でポチりましたので発売日に手に入れてます。

旧型と比較して、起動と読み込み速度は少し速くなったような気がします。あとはだいぶ静かになった気がします。

画質に関してはちゃんとPro対応しているソフトを比較してないのですが…

ちなみに今後購入予定のソフトは GRAVITY DAZE2、NieR:Automata、Horizon Zero Dawnです。

PS4まわりについては前回記事を書きましたので、読んでみてください。

PlayStation4 Proと周辺機器の話 - ほげほげ(仮)

まとめ

2016年はだいぶお金を使ってしまいました。特にPS4まわりはお金使いすぎた感じですね…

来年の予定としては、そろそろ家のMacを新調したいなぁ、ErgoDoxほしいなぁ、ってところですかね。

来年は節約したい…

PlayStation4 Proと周辺機器の話

PlayStation4 Proと周辺機器について雑に書きました。何か参考になれば。

PlayStation4 Pro

PlayStation 4 Pro ジェット・ブラック 1TB (CUH-7000BB01)

PlayStation 4 Pro ジェット・ブラック 1TB (CUH-7000BB01)

ぼくは2年くらい旧型を使ってて、予約開始と同時にポチっと購入しました。

今までのPlayStation4と比べて何が違うかは、よくある質問のほうをみると詳しく書いています。

PlayStation®4 Pro:よくある質問 | PlayStation®.Blog

で、Proは買ったほうがいいのか?

個人的には今まで持ってなくて新しく買う人はProを買ったほうが今後は良いと思います。スリム版の1Tと比べて、1万円ほど高いですが、機能的な差は1万円以上だと思います。

4KテレビじゃないとProのほうがパフォーマンスが落ちるソフトもあるようなので、4Kテレビ持ってない人は微妙かもしれないですが…

現状で持っている人は悩むところだと思います。特に1年以内とかに買った人は。

ぼく個人の考えだと、4KテレビかPSVRを持っていない場合は特に買い替えてもそこまで恩恵はないかなと考えます。

もし、4Kテレビを買おうと考えてる人は先に買っておくのは全然アリだと思います。

テレビ

ぼくはProにあわせてテレビ新調しました。そのとき出て来る用語とかをざっくり書き出しておきます。あと注意点とか。結構ややこしい感じです。

4K/HDR

Proのほうは4K/HDRに対応しています。なのでテレビもそれに合わせたものを買うのが良いと思います。

ここで注意としては、4K = HDRではない ことです。もしProを買ってテレビやモニターを買おうと考えてる人は気をつけてください。4Kには対応してるけど、HDRには対応していないものあります。

おそらく現状でPCモニターでHDRに対応しているものはないと思います。安いからPCモニターの4KにするとHDRの恩恵は受けられません。よく考えたほうが良いポイントです。

テレビが4K/HDRに対応してるかはPS4の設定から確認できます。Youtubeのほうで確認方法を見ておくと良いです。


"PlayStation 4 Pro" 映像設定チュートリアルビデオ

HDR

HDRHigh Dynamic Rangeの略で、輝度の幅を拡大するものです。映像を現実世界の明るさに近づける技術です。

ぼくも全然詳しくはないのでうまく説明ができないですが、HDRの有り無しで光の表現が全然違ってきます。

4Kはもう時代遅れ? テレビの新しい高画質「HDR」とは何なのか - 日経トレンディネット

HDMI

さらにややこしい仕様のHDMIについてです。これは先程4K/HDRに関わる部分なので結構重要です。

まず、HDMIってケーブルの名前ではなく通信インターフェース規格です。あのケーブルはこの規格に則っとたものになります。

HDMIのバージョンとかあるのですが、あまり詳しくないので、Wikipediaとかを見てもらったほうが早いです。

HDMI - Wikipedia

で、何が言いたいかというと、このHDMIがちゃんとしてないとPlayStation4 Proの恩恵を受けられないので注意が必要です。

HDMIケーブル

よくある質問のほうにも書いてあるのですが、プレミアム ハイスピードHDMIケーブルを使うことで、4K出力と60フレームに対応できます。

1本は同梱されてるのでそれを使えば良いと思いますが、もし長さ足りないなどの理由で買い換える場合は、プレミアム ハイスピードHDMIケーブルの認証を受けたものを買うようにしましょう。

4K対応「Premium HDMIケーブル」の認証プログラムがスタート - AV Watch

HDMIバージョン

最新バージョンはHDMI2.0ですが、最近のテレビはほぼ対応しているので問題はないかと思います。

ただ、HDR対応しているものは2.0aになると思います。

HDMI 2.0a発表。HDR映像伝送に対応 - AV Watch

HDCP

テレビの仕様とかでみかけるHDCPですが、これは著作権保護の技術になります。

最新のバージョンはHDCP 2.2で、4K放送をみるために必要なものになります。

最近のテレビは対応されてると思うので、特に気にする必要はないかと思います。

4K TVで4K放送を見るために必要な「HDCP 2.2」とは? 各社対応まとめ - AV Watch

テレビはどれがおすすめ?

ぼくが買ったものですが、REGZA 43Z700X になります。

本当はREGZA Z20Xが良かったのですが、50インチからになるので、さすがに部屋に入らないです。

迷ったのがREGZA M500Xです。こちらも4K/HDRに対応してますし、Z700Xより安価なタイプになります。こちらも悪くないとは思います。

だいたいゲームでのおすすめテレビをググるREGZAは必ずあがってきます。理由は遅延時間が少なくゲームに適しているからです。REGZA自体もそれを売りにしている感じですね。

あとはSonyということでBRAVIA候補にあがってきます。

結構忘れがちなのがHDR対応かどうかです。HDRのON/OFFで映像の明るさが変わってきます。好みの問題ではありますが、可能であれば対応したものを選ぶようにしたほうが良いと思います。

困ったら電気屋さんとかで聞いてみたり、見比べたりすると良いと思います。

注意

テレビによっては相性が悪いものがあるみたいなので、事前に調べておいたほうが良いと思います。

ソニーPS4 Proに不具合 TVメーカーと「責任のなすり合い」状態に | Forbes JAPAN(フォーブス ジャパン)

REGZAの注意

REGZAはそのままだと4K/HDRに対応してない状態になっているので設定の変更が必要です。

以下のブログに設定変更の方法がまとめられています。

東芝のREGZA Z700XとPS4®Proを接続してHDRの4K対応させた - 初老のボケ防止日記

PlayStation VRの注意

PSVRを使ってる人はひとつ注意があって、PSVRのプロセッサユニットはHDRをパススルーしません。なのでHDR対応したゲームをプレイする場合はPSVRから外して、テレビへ直接つなぐ必要があります。

HDMIセレクタ

HDMIセレクターとかで切り替えしている場合も注意が必要で、4K/HDRに対応しているか確認したほうが良いです。

試してないはないですが、このセレクターは対応してる感じします。未検証なので購入する方はしっかり検討してください。

SSD

次にSSDです。ぼくが観測した感じだと結構SSDに交換した人が多いように感じました。

ぼくは旧型でもSSDに交換して使ってたのですが、ProもSSDに交換しました。

ProではSATA3に対応したので(旧型はSATA2)、SSDに交換することの効果が高いと考えられています。交換自体も簡単です。

実際に交換後は体感的にだいぶ速くなってる感じです。

少しでもロードを速くしたい人は交換したほうが良いと思います。HDDのままでも旧型よりは速くなったような比較もあるので、普通に遊ぶには問題ないと思います。

今後Proに対応したゲームとかだと更にロードが遅くなる気もしてるのでSSDの効果に期待しています。

ヘッドセット

今使ってるのは、ソニーがだしているPS4用のヘッドセットです。基本これで問題ないと思います。

バーチャル7.1chなので音がどの方向からしたのかわかります。特にFPSプレイヤーにとっては必須な機能だと思います。

ボイスチャットも特に問題ない感じです。

ワイヤレスですが遅延を感じたことはないです。

ワイヤレスサラウンドヘッドセット

ワイヤレスサラウンドヘッドセット

来年それの後継機にあたるのかな、新しいヘッドセットが発売される予定です。3Dオーディオに対応してるので、PSVRでも使えると思われます。これはどうするか悩み中です。

まとめ

お金使いすぎた

やさしいDagger2

Androidその2 Advent Calendar 2016 - Qiita 2日目の記事です。

Dagger2は最初のハードルが高くてなかなか導入できなかったり、メリットがよく分からなかったりします。そういう方が雰囲気だけでも掴めれるように、簡単なサンプルを実装しながら確認できるようなのを書きました。

だいぶ長くなってしまった感じですが、あまり複雑なことはやっていないつもりです。

セットアップ

build.gradle に依存関係を追加します

compile 'com.google.dagger:dagger:2.7'
annotationProcessor 'com.google.dagger:dagger-compiler:2.7'

Hello Dagger2

すごくシンプルなサンプルです。

依存解決されるクラス

まずは依存解決されるクラスを作ります。Dogクラスとします。

public class Dog {
    public String getName() {
        return "ぽち";
    }
}

インスタンスを提供するクラス

依存を解決させるためにインスタンスを提供する必要があります。その設定をしていきます。

クラスには@Moduleをつけて、インスタンスを提供するメソッドには@Providesをつけます。

@Providesの戻り値は注入したい依存の型になります。今回はDogクラスを注入したいのでDogが戻り値になっています。

@Module
public class SampleModule {
    @Provides
    Dog provideDog() {
        return new Dog();
    }
}

依存解決のためのinterface

依存解決をしたいところと、どのモジュールを使うかを定義します。

@Componentの引数には使用するModuleクラスを設定します。

injectメソッドを定義して、引数には依存解決を実行するクラスを設定します。今回はMainActivityで依存解決を行います。

ビルドするとDaggerSampleComponentクラスが自動生成されます。これを次に使ってきます。

@Component(modules = SampleModule.class)
public interface SampleComponent {
    void inject(MainActivity activity);
}

実際に依存解決してみる

MainActivityを次のようなコードにします。よくあるサンプルではApplicationクラスでやってますが、とりあえずシンプルにAcitivtyで直接行います。

やってることはコードのほうにコメントしていますが、基本的にはインスタンスを注入してほしいものに@Injectをつけて、Componentを作って注入を実行する感じです。

今回はSampleModuleで設定したDogクラスを戻り値に設定したものが注入されます。

public class MainActivity extends AppCompatActivity {

    // インスタンスが注入されるフィールド
    @Inject
    Dog dog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // SampleComponentからDaggerSampleComponentが自動生成されるので、それを使ってSampleComponentを作ります。
        SampleComponent component = DaggerSampleComponent.builder()
                // 使用するModuleのインスタンスを指定します。
                // (ここでdeprecatedになることがありますが、一旦すべてコードを書いてビルドすると消えると思います)
                .sampleModule(new SampleModule())
                .build();

        // 依存の注入を実行します
        component.inject(this);

        String name = dog.getName();

        Log.d("MainActivity", name);

    }
}

確認

ここまで実装して、実行するとログが出力されと思います。

これだけでは何のためにあるのかよくわからないと思いますが、とりあえずここでは、依存を解決するために、ModuleとComponentが必要だということを抑えておけば良いです。

Field InjectionとConstructor Injection

さきほどは少し違う依存解決方法を簡単にやります。

前回やったのは、クラスのフィールドに@Injectをつけてそこに注入したので、Field Injectionになります。

もう一つが、Constructor Injectionになります。コンストラクタのパラメータとして依存を注入します。

コンストラクタに注入されるクラス

新しくOwnerというクラスを作ります。

コンストラクタに先程のDogクラスをパラメータとして受け取るようになっています。さらに@Injectをつけています。

public class Owner {

    private Dog dog;

    @Inject
    public Owner(Dog dog) {
        this.dog = dog;
    }

    public String getPetName() {
        return dog.getName();
    }
}

MainActivityを修正

次のように修正します。

変更点はフィールドがDogからOwnerに変わりました。

OwnerについてはModuleに設定したりしてませんが、Dagger2が勝手にコンストラクタに注入してOwnerインスタンスを作ってくれています。

public class MainActivity extends AppCompatActivity {

    @Inject
    Owner owner;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        SampleComponent component = DaggerSampleComponent.builder()
                .sampleModule(new SampleModule())
                .build();

        component.inject(this);

        Log.d("MainActivity", owner.getPetName());

    }
}

確認

ここまで出来たら、実行して確認します。結果は先程変わっていませんが、Ownerの処理からDogの処理を呼ぶようになりました。

Constructor Injectionを使うとDagger2がModuleに設定されたものを使って、インスタンスを作ってくれます。

ぼくはこれがかなり便利だなぁって思っています。ContextとかをModuleに設定しておいて使いたいクラスのコンストラクタでパラメータにすることをよくやります。

interfaceを使う

これまでの使ったのは実装クラスでしたが、次はinterfaceを使うように変更します。

新しいinterfaceをつくる

新しくPetというinterfaceを作ります。

public interface Pet {

    String getName();

}

そして、Dogがそれを実装する形に修正します。

public class Dog implements Pet {

    @Override
    public String getName() {
        return "ぽち";
    }
}

interfaceを使うように修正していく

まずはModuleを修正します。

@Module
public class SampleModule {

    @Provides
    Pet providePet() {
        return new Dog();
    }
}

次にOwnerのパラメータを変更します。

public class Owner {

    private Pet pet;

    @Inject
    public Owner(Pet pet) {
        this.pet = pet;
    }

    public String getPetName() {
        return pet.getName();
    }
}

確認

実行して確認します。結果は変わっていません。

ここで確認するポイントはOwnerのクラスになります。

今までDogという実装クラスに依存していましたが、interfaceに変更することでそことの依存がなくなり、interfaceのみに依存する感じになりました。

Build Variantsで動作を変更する

Build Variantsで動作を変更するようにします。Build Variants自体についはドキュメントやググったりしてください。

今回はProductFlavorsで分けるようにします。

build.gradle

build.gradleを下記のようにして、dogcatのProductFlavorを作ります。

android {
    ...
    productFlavors {
        dog {
        }
        cat {
        }
    }
}

フォルダ作成

srcフォルダの下にdog/javaのフォルダを作り、さらにパッケージを作成しておきます。同様にcat/javaも作成しておきます。

たぶん、どちらかのjavaフォルダがソースフォルダとして認識されないと思います。メニューのView → Tool Windows → Build VariantsからBuild Variantを切り替えることで直ると思います。

実行するときもBuild VariantsのWindowから切り替えることになります

f:id:STAR_ZERO:20161105094229p:plain

Catクラス

新しくPetinterfaceを実装したクラスを追加します。これはmainフォルダのソースフォルダに追加します。

public class Cat implements Pet {

    @Override
    public String getName() {
        return "たま";
    }
}

main

mainフォルダ内にあるSampleModuleクラスを削除しておきます。

BuidTypeやProductFlavorでmainフォルダ内に同一クラス名を使うことはできないためです。代わりにdogフォルダとcatフォルダにSampleModuleを追加するようにします。

catのProductFlavor

catのProductFlavor実行時には先程のCatクラスを使うようにします。

catフォルダのソースフォルダに下記を追加します。今まで異なるのはDogクラスのインスタンスを返却するのではなく、Catクラスを返却するようにします。

@Module
public class SampleModule {

    @Provides
    Pet providePet() {
        return new Cat();
    }
}

f:id:STAR_ZERO:20161105094307p:plain

dogのProductFlavor

dogのProductFlavorの場合は今までのDogクラスを使います。

dogフォルダのソースフォルダに下記を追加します。

@Module
public class SampleModule {

    @Provides
    Pet providePet() {
        return new Dog();
    }
}

f:id:STAR_ZERO:20161105094319p:plain

確認

Build VariantsのWindowでcatDebugdogDebugを切り替えて実行してみてください。

それぞれ、違う結果になると思います。

Build Variantsで実装クラスを丸ごと差し替えて、それぞれで違う動作が可能になります。BuildTypeのreleaseとdebugで処理を分けたい場合や、ProductFlavorの有料版と無料版で処理を分けたい場合などに使えます。

テストを書いてみる

Ownerクラスのテストを書いてみます。このサンプルコードだとDagger2なくても問題なくかけると思いますが…

テスト

テストを次のように書いてみます。androidTestのほうではなくて、testのほうです。

Ownerに渡すパラメータは匿名クラスとしてその場で生成しています。

今回の場合はあまりメリットを感じないかもしれないですが、直接Dogインスタンスを渡してません。

例えばDogクラスのgetNameAPI通信している場合にDogクラスに直接依存している状態だとテストを書くのが結構ツライ感じになったと思います。さらに、もしDogクラスのコンストラクタでContextが必要だったりするとかなり厳しい感じだと思います。

今回のようにinterfaceを使ってテスト時は動作を変更することで、Ownerのテストが書きやすくなりました。

public class OwnerTest {

    @Test
    public void getPetName() throws Exception {
        Owner owner = new Owner(new Pet() {
            @Override
            public String getName() {
                return "ペットの名前";
            }
        });

        assertThat(owner.getPetName(), is("ペットの名前"));
    }
}

確認

テストを実行してみてパスすることを確認します。

Constructor Injectionを使ってたおかげで、テストがだいぶ書きやすくなりそうな感じです。

まとめ

今回のサンプルはあまり実践的ではないかと思いますが、雰囲気を分かってもらえれば嬉しいです。

Dagger2のテストのサンプルとかだと結構UIについてが多かったりしますが、UI以外のテストにもとても有効だと思いますし、導入がしやすいかなぁって思います。

実際に手を動かして確認しないと理解しにくのもあるので、Dagger2を試したことない人は一度やってみたほうが早いかなぁって思います。複雑な部分もありますが、単純な使い方だとそこまで苦労せず使えると思います。(ぼくは単純な使い方しかできないですが…)

ToolbarはFragmentに持たせても良いと思う

Y.A.M の 雑記帳: Fragment に Toolbar を持たせるのはやめなさい を読んで思ったことです。

ぼくはFragmentにToolbarを持たせても良いと思ってます。

もちろんActivityに置くことでFragment側がシンプルになるので、極力そうしたい感じですが、色々と事情があります。

例えばFragmetごとにToolbarに独自のViewを入れたりしたい場合があります。記事では android:actionViewClass を使えば良いと書いていますが、Toolbar使う理由ってレイアウトファイルでToolbar内を簡単にカスタマイズできることだと思っています。Toolbar内をカスタマイズしたほうがコード自体も見通しが良くなる場合もあると思います。もちろんSearchView などの便利なやつは android:actionViewClass で使いますが。

あとはDataBinding絡みで簡単にToolbar内のViewにアクセス可能になります。 android:actionViewClassでもDataBindingUtil.bindを使えばいけるかもしれないですが、わざわざ複雑さを増すようなことはしたくないなぁと個人的には思います。

じゃ、Googleはどうしてるの?ってのを思って調べたら、googlesamplesで実装を見かけました。揚げ足取りみたいな感じでアレですが…

https://github.com/googlesamples/friendlyping/blob/ee8e2bb4084b1326f414903ca0e4b1189489ad5c/android/app/src/main/java/com/google/samples/apps/friendlyping/fragment/FriendlyPingFragment.java#L169

こういうのは難しいところで、正解は無いと考えています。

今回は賛同できませんでしたが、そういう考えで実装を進めることは非常に良いと思います。

すいません、少しモヤモヤしたところあったので書かせてもらいました。

MESHを使って鍵の閉め忘れをなんとかする

MESHとは

MESH:遊び心を形にできる、アプリとつなげるブロック形状の電子タグ|ソニー

さまざまな機能を持ったブロック形状の "MESHタグ" を "MESHアプリ" でつなげることにより、 あなたの「あったらいいな」を実現できる それがMESHです。 難しいプログラミングや電子工作の知識は必要ありません。 IoT(モノ・コトのインターネット化)を活用した仕組みも 簡単に実現します。

とのことです。

去年くらいからあったっぽいのですが、ぼくは全然知らなくて、この前ソニーストア行った時に見て興味が湧いて実際に買ってみました。

iOSアプリを使って、アイコンを繋いでいくだけで様々なことが出来ます。

すごく簡単なので、子供がいらっしゃる方は子供と一緒にやる良いかもしれません。夏休みも残り少ないけど自由研究的なものに。

いろんな人がレシピを公開してるので、これを見るとどんなことが出来るのかイメージしやすいかもしれません。 MESHレシピ

MESHアプリ

iOSアプリで下のような感じでアイコンをつなぐだけで色々できます。下の例だと、動きタグが何か検知したらiPhoneの音が鳴ります。

f:id:STAR_ZERO:20160819141005p:plain:w200

詳しくは下のリンクを参考にしてください

MESHアプリ Creative DIY Toolkit|ソニー

鍵の閉め忘れをなんとかしたい

ぼくは鍵を閉めたのかが不安になることが多くて、一度家に戻るとかもよくやります。

今回はMESHの検証ついでにこの課題をなんとかしたいと思います。

鍵の開け閉めを検知する

MESH-100AC 動き(Move)タグ - 動きがきっかけになる新しい感覚 ワイヤレス加速度センサー | ソニー

今回は動きタグのみを使って、鍵の開閉を検知する仕組みを作ります。

これ想像以上に優秀で、振られたら、ひっくり返したら、振動したら、向きが変わったら、を検知できます。

今回はこの向きが変わったらをトリガーにします。

ドアの鍵にこんな感じにくっつけます。見た目がかなり残念な感じですが…

  • 開けた状態

f:id:STAR_ZERO:20160819135325j:plain:w200

  • 閉めた状態

f:id:STAR_ZERO:20160819135333j:plain:w200

鍵が閉められたのを検知

動きタグが表向きに変更されたら、鍵を閉めたと判断します。

キャンバスに動きタグを配置して、タップすると詳細が見れるので、そこで「向きが変わったら」の「表」を選択します。

f:id:STAR_ZERO:20160819141651p:plain:w200

鍵が開けられたのを検知

これも同じような感じで設定します。

「向きが変わったら」の「上」を選択します。

f:id:STAR_ZERO:20160819141905p:plain:w200

これで鍵の開け閉めは検知できるようになりました。

通知する

次は通知です。おそらく現状でMESHの状態(動きタグの例だと今は表を向いてるとか)が簡単に取れないと思うので、通知でログを残す方法で状態を確認できるようにします。

MESHでは、スピーカー鳴らしたり、iPhoneに通知をだしたりできますが、これではログとしてはあとから確認するには不十分です。

MESHは実はIFTTTと連携することができます。これを使ってSlackに投稿させればログとして残るし後から確認できます。

IFTTT設定

ここは省略します。詳しくは公式サイトの手順を参考にしてください。

IFTTT連携の初期設定方法を教えてください – MESHサポート | 遊び心を形にできる、アプリとつなげるブロック形状の電子タグ

IFTTT連携でレシピの作り方を教えてください – MESHサポート | 遊び心を形にできる、アプリとつなげるブロック形状の電子タグ

ぼくはSlack側の設定は下のような感じにしました。

f:id:STAR_ZERO:20160819143056p:plain:w200

Messageのところを{{Text}}にしておくと、MESHアプリからテキスト設定できます。

アプリ設定

アプリの右下にある連携タグからIFTTTを選択して、キャンバスへ配置します。

IFTTTの設定を下のようにイベントIDとテキストを設定します。

f:id:STAR_ZERO:20160819143304p:plain:w200

同じように開けられた時のIFTTTもキャンバスへ配置しておきます。

それを動きタグと繋ぎます。

最終的にキャンバスは次のようになります。上が鍵を閉めた時、下が鍵を開けた時になります。

f:id:STAR_ZERO:20160819143652p:plain:w200

確認

鍵の開け閉めをするとSlackに次のように通知されます。

f:id:STAR_ZERO:20160819144300p:plain:w200

これで、鍵の状態が確認できるようになりました。

完成

コーディングなしで簡単にここまで出来ました。工夫次第ではもっと色々できると思います。

MESHがくっつけられればだいたいの鍵に対応できると思います。オフィスとかで最終退出時間を自動で残すとかにも使えるかも。

まとめ

MESHは他にも色々な使い方が出来ると思うので、時間あるときにまた試そうと思います。またSDKもあるっぽいのでそれも見てみたいと思います。

MESHは単品でも買えるので、お試しで一つだけっていう感じで気軽に試せます(それなり値段はしますが…

暇な人はこれで遊んでみると良いと思います。

MESH Moveタグ

MESH Moveタグ

ワイヤレスファンクショナルタグ Button

ワイヤレスファンクショナルタグ Button

MESH Bundle 7

MESH Bundle 7

CQRSのメモ

CQRSって知らなかったので調べました。かなり雑なメモです。

参考リンクとかではEvent Sourcingについても絡んできますが、ここでは触れてないです。

参考

ここにある記事を読みました。英語のとこはなんとくで読んだので怪しいですが。

ぼくのこのメモを読むより、下記の記事を読んだほうがいいです。

CQS(Command Query Separation)

CQRS(コマンドクエリ責務分離)に入る前に、CQS(コマンドクエリ分離原則)について。

CQSはコマンドとクエリを分けようってことです。

  • クエリ: 結果のみを返し、状態の変更は行わない
  • コマンド: 状態の変更のみを行い、結果は返さない

これをオブジェクトレベルで適用します。メソッドで分ける感じです。

ただ、Javaiteratorのようにnextで結果の取り出しと内部状態の変更をやっているものもあります。こういうイディオムは便利なので原則を破ることもあるようです。

CQRS(Command and Query Responsibility Segregation)

CQSではオブジェクトレベルで適用する感じでしたが、CQRSではもっと広い範囲に適用します。Event Sourcingも含むとアプリケーション全体になるかと思います。

CQRSではCQSと異なり、コマンドとクエリをメソッドで分けるのではなくオブジェクトごと分けます。

例えばこういうオブジェクトがあった場合、

CustomerService
void MakeCustomerPreferred(CustomerId)
Customer GetCustomer(CustomerId)
CustomerSet GetCustomersWithName(Name)
CustomerSet GetPreferredCustomers()
void ChangeCustomerLocale(CustomerId, NewLocale)
void CreateCustomer(Customer)
void EditCustomerDetails(CustomerDetails)

次のように分離します。

CustomerWriteService
void MakeCustomerPreferred(CustomerId)
void ChangeCustomerLocale(CustomerId, NewLocale)
void CreateCustomer(Customer)
void EditCustomerDetails(CustomerDetails)

CustomerReadService
Customer GetCustomer(CustomerId)
CustomerSet GetCustomersWithName(Name)
CustomerSet GetPreferredCustomers()

クエリ側

データを取得するメソッドを持つだけで、各画面にマッチするDTOを生成して返却します。

多くのドメインではクエリ最適化が困難、インピーダンスミスマッチ問題などがあります。

CQRSを適用すれば、クエリ側はドメインを使いません。新しい概念の「Thin Read Layer」でデータベースから直接読み込んでDTOに反映します。

コマンド側

読み込みをドメインから分離すれば、コマンドの処理だけに焦点があたります。

リポジトリではGetByIdを除くとクエリはわずかになります。

クエリを分離したドメインモデルで作業をすれば、概念的なオーバヘッドが減り、コスト削減につながります。

(ここらへん怪しい)CQRSを適用すると、クエリとコマンドで同一データモデルを使うのかという問題がある。ここから先はEvent Sourcingの話っぽい?(ココのP23の下の部分)

まとめ

CQSはすぐにでも適用できそうですが、CQRSになると簡単にはいかなさそうです。

Event Sourcingも絡んでくると、ぼくはお手上げ状態になりそうです。

ここの最後にも書いてあるのですが、CQRSについてはだいぶ慎重になったほうが良さそうです。

XCTestでthrowsをテストする

環境

テスト対象コード

テストの対象となるサンプルコードです。

エラータイプの定義です。

enum SampleError: ErrorType {
    case Invalid
    case Unknown
}

エラーをthrowするコードです。

class Sample {
    static func exec() throws {
        throw SampleError.Invalid
    }
}

テスト

throwされたかをテストする

エラーがthrowされた場合はテストはパスします。もしthrowされなかった場合はテストは失敗します。エラーのタイプなんでもいいです。

XCTAssertThrowsError(try Sample.exec())

throwされたエラーもテストする

Closure内でエラーが期待しているものかをXCTAssertEqualを使ってテストします。もし、違うタイプのエラーの場合はテストは失敗します。

XCTAssertThrowsError(try Sample.exec()) { error in
    XCTAssertEqual(error as? SampleError, SampleError.Invalid)
}