YSNHatenaBlog

主にアプリやWebサービス開発について

irMagician + Raspberry Pi + HomeKitで家電を遠隔&音声制御する

音声でテレビを操作したい、帰宅前にエアコンをつけたい、といったことは誰でも考えたことがあると思います。 今持っている普通の家電でこれを実現したいと思ったときに、

  • 音声認識して家電操作コマンドに変換して赤外線を飛ばすようなソフトとハードを作る。
  • 家に近づいたことを検知するためのアプリを作る。
  • 宅外から宅内のネットワークにある機器を操作するためのシステムを用意する。

など、いざ実現しようとすると意外と難易度が高いことに気づきます。

しかし今回、HomeKitを使った機器連携でこれらが簡単に実現することができました。 今回の記事では、その方法についてまとめたいと思います。

HomeKit

iOS10からホームアプリが追加され、HomeKit対応デバイスをこのアプリから管理できるようになりました。

f:id:yosuke403:20170107185438p:plain

ホームアプリにHomeKIt対応デバイスが登録されるとiOSから操作が可能になるのですが、 単純な操作だけでなく、次のようなことが可能になります。

1. iOSのコントロールセンターから操作できる。

f:id:yosuke403:20170107211712p:plain

2. Siriから操作できる。
3. Apple Watchから操作できる。

f:id:yosuke403:20170107211254p:plain

4. 家族のIDを登録すれば、家族が自分のiOSバイスから操作できる。
5. Apple TVを持っていれば、宅外から操作したり、位置情報やタイマーをトリガーに操作できる。

f:id:yosuke403:20170107211549p:plain f:id:yosuke403:20170107211627p:plain

便利ですね!

つまりHomeKItに対応したデバイスは、音声操作したり宅外操作したりできるわけです。

HomeKit APIをエミュレートするhomebridge

homebridgeはHomeKit APIをエミュレートするNodeJSサーバです。 起動すると、HomeKit対応デバイスとして、そのサーバをホームアプリに登録できるようになります。

nfarina/homebridge: HomeKit support for the impatient

ホームアプリから操作した際の動作は、homebridgeプラグインによってカスタマイズできます。 homebridge-cmdプラグインを使用すると ホームアプリの操作に対応して、任意のコマンドを実行できます。

「irMagician + Raspberry Pi + homebridge」で家電を遠隔操作

irMagicianは大宮技研さんが販売している赤外線リモコンシステムです。 低価格かつ軽量でコマンドラインからでも制御できるのが特徴です。

irMagician – 高機能/低価格赤外線リモコン | 大宮技研 合同会社

irMagicianとRaspberry Piの組み合わせは、HomeKit経由で赤外線リモコンを操作するためのミニマム構成です。 先に説明したhomebridge-cmdでirMagicianを操作して赤外線を自由に発射できます。 フレキシブル延長ケーブルを使うと、向けたい方向にirMagicianを固定できて便利です。

Amazon | エスエスエーサービス [ USB A(オス) - USB A(メス) ] フレキシブル延長ケーブル SU2-AA03FB | エスエスエーサービス | USBケーブル通販

f:id:yosuke403:20170103230320j:plain

見ての通り、irMagicianを使うと全体の構成はコンパクトで済み、かつ低価格なのでオススメです。

全体構成

今回の、宅外からApple TVを介して宅内の機器を操作する際の構成図です。

f:id:yosuke403:20170103224200p:plain

iOSバイスが宅内のWi-Fiに繋がっている場合は、iOSバイスが直接Raspberry Piにアクセスすることになります。

設定方法

irMagician + Raspberry Pi + homebridgeの設定についてはこちらの記事が参考になりました。

iOS10「ホーム」アプリと「Raspberry Pi + irMagician」でお手軽家電操作。 - Qiita

この記事ではSiriについてや、その他ハマったところを書きたいと思います。

Siriで操作するには?

ホームアプリにRaspberry Piを登録するときに名前をつける(例えば「暖房」など)と、その名前で反応するようになります。 Siriを起動し、「暖房の電源を入れて。」と命令すれば電源が入ります。

f:id:yosuke403:20170107220003p:plain

ただし、「エアコン」という名前にして「エアコンの電源を入れて。」と命令しても「エアコンは見つかりませんでした」と返されてしまいます。 おそらく、Siriではアクセサリのカテゴリ(「照明」や「エアコン」など)を指定するだけで、 そのカテゴリに対応するアクセサリが登録されていれば、そのデバイスを操作しようとするのだと思います。

この辺りにリストアップされているのが、カテゴリの名前になると思われます。 www.apple.com Accessory Category Types - HomeKit | Apple Developer Documentation

その他ハマったところ

homebridgeが見つからない

usernameを変更してみてください。 MACアドレスのように見えますが、Raspberry PiMACアドレスと合わせる必要はないようです。

{
    "bridge": {
        "name": "YourBridgeName",
        "username": "CC:22:3D:E3:CE:50", # <- ここを変更
        "port": 51826,
        "pin": "031-45-403"
    },
    # 省略
}
ログインしたのにApple TVと連携されない

f:id:yosuke403:20170104233550j:plain

Apple TVにログインしたのですが、iPhoneを4G回線に切り替えても最初は宅内の機器が見えませんでした。 いろいろ調べて、設定確認したり、ログインし直したり、再起動したりしてみたのですが結局ダメで、 一旦あきらめて次の日おもむろに起動したところ成功しました!

設定の同期タイミングの問題だったのでしょうか...。

動作の様子

実際の動作の様子です。

前半は宅外から操作するデモ(4G回線でつなげています)、後半はSiriで操作するデモになっています。

www.youtube.com

※ 使用しているエアコンはPanasonicのCS-264CF2です。 http://panasonic.jp/aircon/housing/p-db/CS-364CF2S.html

さいごに

HomeKit、思った以上に便利でした。Raspberry PiとirMagicianも使うことで夢が広がります。

一方、公式にHomeKit対応しているデバイスは少ない状況のようです。

HomeKit - すべてのアクセサリ - Apple(日本)

早くいろんな家電に対応してもらいたいですね。

おうちハックに挑戦してコンテストまで参加できた話

今回、IoT的なことに挑戦してみたので、ブログに書いておこうと思います。

生活デザインコンテスト出品

今回、大阪で行われた「生活デザインコンテスト」に応募し、出品させていただくことができました。

生活デザインコンテスト#3 – 生活デザインプロジェクト

作品名は『家族の「ただいま」を教えてくれるキーホルダー』というものです。

家族の「ただいま」を教えてくれるキーホルダー | ナレッジコネクター + Idea.LinkData

youtu.be

これはQUALY社のSparrow Keyringという鳥の巣箱型キーホルダーを使ったもので、鍵を巣箱に戻すと「ただいま」、巣箱から出すと「行ってきます」を家族のスマートフォンに通知するというデモになっています。

いろいろ課題があって実際の運用まではできていないのですが、なんとかコンセプトを伝えられるところまで実装できました。

作品出品までの道のり

おうちハック発表会のLTに挑戦

コンテスト応募のきっかけは「おうちハック発表会」での発表でした。

このイベントを開催しているおうちハック同好会には、知り合いが多く参加しており、自分も発表したいと思い今回の作品を作りました。

自分はアプリ開発ならできるのですが組み込みは初心者で、とにかくRasbperry PiやArduino、それらに関する書籍を買って、何ができるのか、どうやったらできるのかをとにかく調べました。

最初のネタとして、Netatmoを使った、屋外の気温を朝通知してくれるアプリを作りました。Netatmoは組み込み知識が不要ですが、簡単にIoTを体感できる面白いデバイスです。しかしこの気温アプリ、妻に全然使ってもらえませんでした。朝携帯を全く見ない妻には、このアプリは意味がなかったようです。その代わりのネタを探したところ、先に述べたキーホルダーが面白そうだったので、鍵の検知をする方法を知り合いに聞いたりして作ってみました。

おうちハック発表会では、このときの経験した「家族に使ってもらうって難しい!」という題材で発表しました。やはり家族に自分の作品を使ってもらっている人は少なく、共感を得ることができたかなと思いました。またスライドで課題を共有したところ、会の後に解決策をいろんな方に考えていただきました。

www.slideshare.net

生活デザインコンテストへの応募

おうちハック発表会で、ある程度動くものとして作り上げられたことと、見た目の可愛さを評価していただき、生活コンテストへの出品を提案していただきました。

ポスターや作品資料など、いろいろ作成する必要があるのですが、これが結構大変でした。とりあえずデモとして動けばいいとガチャガチャ作っていたこともあり、作品資料とするにはもう一度自分のやったことを整理する必要がありました。特にプログラムやAWSなどについては、別件で持っていた有物を使って動かしていたところを解きほぐして、無駄な処理や構成を省いて精錬していきました。

資料はこちらに上がっています。一応初心者でも再現できるよう、頑張って書いています。

インターネットアカデミーでの発表会

開催後には、インターネットアカデミーにて発表させていただく機会をいただきました。

おうちでできるIoTを体験しよう!『生活デザインコンテスト 優秀作品発表会』8/27開催 - インターネット・アカデミー

実は生活デザインコンテストでは、ネットワークがなかったこともあり動くものを展示できなかったので、今回初めての人前でのデモになります。そこで、課題だった感圧センサーの低い認識率を、おうちハック発表会でいただいたRFIDのアイデアで解決してみたところ、デモとしてちゃんと動かすことができました。もう少し改良したらまた発表したいです。

発表した結果

おうちハック発表会での発表をきっかけに、いろんな経験ができ、またいろんな方と繋がることができました。 発表会で会った方が開催する、別のIoTの勉強会に呼んでいただき、そこでまたいろんな人の話を聞くことができました。 またインターネットアカデミーの発表会でも、コンテストに参加した方の素晴らしい作品を体験したり、また作者の人の話を聞くことができました。

さらに、「キーホルダーの人ですか!」「あのスライドみました!」と言ってもらえたのがすごい嬉しかったです。自分がIoTの世界に一歩踏み込めた気がしました。

まだまだこの作品は改良の余地があるので、引き続き取り組んでいこうと思います。

IoT縛りの勉強会! IoTLT vol.13に参加してきました

IoTLT初参加

遅くなりましたが、3/16(水)にIoTLTに参加してました。 印象に残った発表のみピックアップして感想を書きまっした。

発表

Node.js x IoT

@yosuke_furukawaさん。Node.jsユーザグループの代表。

IoT周りのNodeの話でした。

Nodeはビルド済みのバイナリが配布されており、ビルドする必要がないのが特徴。ARM用のバイナリ(Node and ARM)も配布しているそうです。

IoT関係のライブラリとして「Johnny-Five」が紹介されていました。 rwaldron/johnny-five: JavaScript Robotics and IoT programming framework, developed at Bocoup.

Javascript Robotics programming framework。Arduino, Tessel 2, BeagleBone, Intel Edison, Particle Photonなどいろんなボードに使えるみたいです。 例えばこんなコードでLチカできます。ArduinoC/C++ベースのプログラミングだった気がするのですが、JSで書けるのはWeb系のエンジニアにはとても嬉しいですね。

var five = require("johnny-five");
var board = new five.Board();

board.on("ready", function() {
  var led = new five.Led(13);
  led.blink(500);
});

(もう一つあったけどメモしそびれました...)

このJohnny-Fiveについて、チュートリアル形式で学べる「nodebot-workshop」と言うnpmがあります。

チュートリアルをnpmで配るっていうのがすごいですね。ただしCLIで行うため結構つらいとのこと。

また、V8に変わる実行エンジンとしてMicrosoftのchakracore-node が登場しているとのこと。Windows上で動作する省エネ重視のエンジンらしいです。 nodejs/node-chakracore: Node.js on ChakraCore https://github.com/nodejs/node-chakracore

IoTで家庭の問題を解決したい話

@yamacho1111 イノベーター・ジャパン

speakerdeck.com

SONYのMESHを使って、鍵の開閉を記録してみた話でした。 MESH:遊び心を形にできる、アプリとつなげるブロック形状の電子タグ|ソニー

目的は奥様に家の鍵を閉めさせることだそうです(笑)。MESHで鍵の開閉を検知して、IFTTT経由でGoogle Docsに記録していく仕組みです。

鍵が閉まっていなかったらHueで知らせるようにしたところ効果があったとのこと。家の中で携帯を見させるというのは難しいので、他の手段で気づかせるという仕掛けは重要な気がしています。 [IoTで家庭内の問題を解決したい話

MESHはそこそこ値段はするようですが、機能ごとにバラ売りしています。何か解決したい課題にはまりそうなら購入してみたいですね。

IoTをインターネット越しに見る

@tnohoさん

www.slideshare.net

個人的にいちばん共感した話。IoTで機器をリモートコントロールする話はよくありますが、実際ちゃんと動いたか、何か問題は発生していないか(特に火事とか)を見られるように現場の映像も必要になるだろうという話。この映像転送のためにWebRTCはどうかという提案です。

動画配信サービスを自分で作るのは、たとえAWSのようなサービスを利用しても結構大変だと思いますが、WebRTCを使うと簡単に実現できます。P2Pで通信することも可能なので、バックエンドの運用コストも少なくて済むはず。何か使いやすいキットがあれば流行りそうですね。

終わりに

IoT関係の勉強会は初参加でしたが、白愛話がいろいろ聞けてよかったです!

スピード勝負の記事を書くのは大変

たまたまある日早起きしたら「Kitura」のニュースを発見したので、ちょっと試してみようと思ったので、セットアップしてみました。 その時にメモした内容をちょっと整理してQiitaに投稿したら、そこそこストックが付きました。

qiita.com

ストックがついたのは嬉しいのですが、結構大変だなと思いました。

特に、内容に誤りがないか?というのは、時間が許す限り(出社する時間まで)確認しました。 それでも不安でしたが。

また、読み返してみると初期設定のガイドを追っているだけなので内容が薄い。 こんな記事でもいいんだっけ?と気になりました。

ただ、ニュースを広めるという役割の記事だと思えばそれもいいのかなと。 またこういった機会があれば、スピード勝負記事を書いてみようかなと思います。 大変ですけどね。

Developers.IO 2016に行ってきました

勉強会ネタばかりですが、今度はDevelopers.IOに行ってきました。

f:id:yosuke403:20160221091328j:plain

SORACOM Airだけは会場で買いましたが、他はいただきました。嬉しい。

参加したセッションの感想を書きたいと思います。

頑張らないクラウド最適化 〜クラウドネイティブだけでないAWS活用〜

頑張らないクラウド最適化 〜クラウドネイティブだけでないAWS活用〜 | Developers.IO 2016 - クラスメソッド株式会社

アプリは頑張らないでインフラ側で頑張るという話でした。 「AWSに責任を押し付ける」ことでセキュリティを上げるというのは重要な考え方ですね。 「AWS Well-Architected Framework」は知らなかったので、今度読んでみようと思いました。 AWSは目的を達成するための手段はいっぱいあるので、適切な選択肢を取るための知識習得が求められますね。

AWS Mobile Maniacs

www.slideshare.net

Mobile Hubの話は以前AWSのイベントで聞いたかな。 LambdaがVPC中のRDSを直接叩けるようになったので、活用が進みそうです。 API Gatewayからlambdaを呼ぶ時はAsyncで呼べないので、間にInvoke-Asyncする軽いLambdaを噛ませるとか、CloudFrontをとりあえず挟むといいとか、Tips的な情報が聞けてよかったです。

実務で使うAWS Lambda

speakerdeck.com

Lambdaの実用事例ってあんまり聞かないような気がしていましたが、「EC2はオンプレミスの延長だったがLambdaはそうではないため使う際の心理障壁がある」というので納得しました。 LambdaのTipsは参考になりました。メモリやサイズ、同時実行数に注意する必要があるとのこと。また、Lambdaは大丈夫だがバックエンドが並列に耐えられない可能性もあるので、間に何か噛ませるかしてコントロールする必要があるとのことです。

IoTのビジネスをデバイス・ゲートウェイから見てみる ~この1年でどんなアップデートがあったのか?~

IoTのビジネスをデバイス・ゲートウェイから見てみる ~この1年でどんなアップデートがあったのか?~ | Developers.IO 2016 - クラスメソッド株式会社

情報通信白書によるとIoTデバイスは2020年に530億個になると出ている一方で、ハイプ・サイクルによるとIoTは幻滅期に入っています。 確かにインフラ側は整いつつある中で、キラーとなるデバイスがなかなか出ない印象があります。

サブギガの話は面白かったですね。 障害物にも強いというのは嬉しい。 前にトイレの空き状況を通知する話があった気がしますが、これが使えそうだと感じました。

IoTの問題として大量デバイスの管理や、盗難の問題があります。 SORACOM AirのカスタムDNSを使って、名前解決できたらアクションを起こすような例を紹介されていました。 こんな風に使えるとは、なるほど。

IoT WARS - The Force Awakens -

懇親会中のデモ。 手でドローン操作したりする、フォース感のあるデモでした。 BB8めっちゃ欲しいです。

全体感想

いろんな話が聞けて面白かったですが、別の勉強会で聞いた話と重複することも多かったので、別セッションも見てみたかったですね。 これからスライド上がってくると思うのでチェックしておきたいと思います。

Swiftで何か作る勉強会 #4(UI・UX編)に参加してきました

今度は茅場町で行われた「Swiftで何か作る勉強会」に参加してきました。

iPhoneアプリ開発勉強会@茅場町 | Doorkeeper

他のSwift勉強会と違って、コードの内容より作るにはどうしたらいいかにフォーカスしているそうです。 @tikidunponさんが司会を務めています。

茅場町って行きやすそうで、JRだと意外と乗り換えが面倒でした。 もういいやと思って東京駅から歩きましたが、結構遠かったです...次は電車で行きます。

人数は7人でした。 最初に@tikidunponさんがLTをしてくれました。 他にもLT募集していましたが、今回はいませんでした。

LT

入力フォームを作るときにいろいろ調べた時の話でした。 発表中のメモを貼っておきます。

入力フォームを作る

まずはiOS Human Interface Guidelinesを読んでから作るべき。

良いUIのサンプルを調査中でこんなサイトがあるらしい。

  • UIサンプル cappitivate.co - アニメーション付き。サンプルをDLできる。

capptivate.co

  • iOS Cookies - 良いUIをキュレーションしている。

www.ioscookies.com

  • awesome-ios-ui - キュレーションしているが玉石混交感あり。アニメーション付き。

github.com

作成中にやること

pod try

でCocoapodsのExampleを試せる。

モック

  • Prott
  • POP

デザイナーがいればProttでいいが、手書きでいい場合はPOPで。

おすすめ

  • SwiftCop - フォームのバリデーションライブラリ
  • Eureka - Swiftのフォームライブラリ

改善の為に

何を目標値とするかを決める。

  • お申し込みを1割増やしたフォーム改善の話

www.slideshare.net

qiita.com

GAのABテスト機能。使われてる方の出す割合をさらに増やすことで、試験機会を逃さないようにするとのこと。

失敗談

  • Express審査の時の話。ジョブズ使ったらNGにされた。急いで申請するときはハードルが上がる可能性が高いと思われる。

感想

GAでABテストできるの知りませんでした。ちょっと調べてみたいです。

もくもく

雑談しながら各自プログラミング。

いろいろな話が聞けて面白かったです。 CoreDataよりRealmを勧められたので、現在移行できるか調査中です。 まだ全然調べられてないのでなんともですが、ちょっとチュートリアル読んだ感じは使いやすそうです。

タイムアップ

時間になったら終了です。 社外もくもく会は初参加でしたが面白かったですね。また行ってみようかな。

Kyobashi.swift #1 に参加してきました

f:id:yosuke403:20160214091621j:plain

京橋でSwiftの勉強会が開催されたので行ってきました。 株式会社リクルートマーケティングパートナーズさんがスポンサーです。 会場は広くていい雰囲気。料理や飲み物がいっぱいだったのに無料でした。すごい! 人数は40人ぐらいでしょうか。結構多かった印象でした。

LTを行った後懇親会の流れでした。 LTのお題はこんな感じです。

発表者 タイトル
yutu About Kyobashi.swift#1 + Swift Refactoring Tips
akatsuki174 既存プロジェクトにSwiftLintを導入した話
ktsukago ExtraViewの使い方
mpon Unidirectional Data Flow in ReSwift
yousan OSSから学ぶSwift実践テクニック
kazu0620 Nearby Messages API
naoty FriendlyErrorType
gomi_ningen Dependency Injection in Swift 2.x

自分もLTしてきました。

About Kyobashi.swift

\@yutu 平井祐樹

今回Kyobashi.swiftは1回目なので、このイベントの説明。 yutuさんは転職されたばかりで、kyobashi.dexを受けてSwift版を開催することにしたそうです。

おまけで次について発表されていました。

Refactoring Swift Source

Objective-Cでは使えたXcodeのRename機能ですが、Swiftでは使えません。そこでRefactorator Swift Pluginというのがあり、Alcatrazなどで入れられるそうです。

Xcode本体に早く入れて欲しい。

既存プロジェクトにSwiftLintを導入した話

sssslide.com

\@akatsuki174

SwiftLintをプロジェクトに導入したときの話。いきなり導入するとワーニングがえらいことになるので、徐々にいれていこうっっていう話ですね。

SwiftLintはGitHubのコーディング規約がベースになっていて、そこからパラメータをカスタマイズしていくそうです。

ルールは.swiftlint.ymlに記述。RunScriptにLintを実行するよう追記。

導入ステップ 1. チームの合意を得る 2. 採用するルールを決める(line_lengthはチームで議論) 3. 全てのルールをdisabledにする 4. 1つずつルールを適用 5. 数値系ルールの値の調整 6. ユニットテストを回して確認

$ swiftlint autocorrect

を使うこともできるそうです。

ExtraViewの使い方

www.slideshare.net

\@ktsukago

ExtraViewの使い方についてご紹介(Swiftは関係ないと最初に宣言されていました笑)

Storyboardの外側にViewを持たせることができるという話です。発表にもありましたがSectionHeaderの定義に使うと便利そうです。

Viewをここに挿入できることは知っていたのですが、Storyboard Editorに表示されてましたっけ??Storyboardと一緒に編集できて便利ですね。

Unidirectional Data Flow in ReSwift

sssslide.com

\@_mpon

ReSwiftについての説明。

ReSwiftはReduxのSwift実装で、ReduxはFluxを進化させたもので、FluxとはFacebookが提唱しているクライアントアプリケーションの設計モデルのこと。

ヘビーなフレームワークって導入コストも大きそうだけど、どうやって導入していってるんでしょう。聞いてみたかった。

OSSから学ぶSwift実践テクニック

ここは自分の発表をさせていただきました。 こちらに置いてあります。

www.slideshare.net

Qiitaにも投稿してあるので、手早く読みたい人はこちらをどうぞ。

Alamofireから学ぶSwift実践テクニック - Qiita

Nearby Messages API

\@kazu0620

自己紹介されてましたが、個人アプリのDL数ハンパない。

Sansanさんの名刺交換アプリを作った際の話。名刺交換を様々なデバイスで行うことを考えた時に、こちらのGoogleAPIを使うことを思いついたそうです。

Nearby Messages API Overview | Nearby Messages API | Google Developers

仕組みとしては、 1. 送信側がGoogleAPIにアクセスして、渡す情報と一次的なペアリングコードを生成する。 2. 送信側はペアリングコードをBT, BLE, WiFi, 「超音波」などの方法で送信する。 3. 受信側はペアリングコードを受信する。 4. Googleでペアリングコードを確認し、紐付いた情報を取ってくる。

という流れの模様です。超音波が使えることで、BLEを持っていないAndroidとも情報交換できます。

注意として、100KBまで、常に送信し続けないようにする、Googleの許諾画面が出るといった項目があるそうです。

FriendlyErrorType

www.slideshare.net

\@naoty

従来のNSErrorからErrorTypeへ移行したときの工夫についてです。

ErrorTypeにはuserInfoのような詳細なエラー情報がないため、それを格納するプロパティを持った、ErrorType適合型を実装するとよいそうです。

さらに、Alamofireを使用したりすると、NSErrorがまだ使用されているのでErrorTypeとの共存を考える必要があるとのこと。NSErrorにextensionでFriendlyErrorTypeに適合させれば、NSErrorをFriendlyErrorTypeと同じように扱えるそうです。

Dependency Injection in Swift 2.x

niconare.nicovideo.jp

\@gomi_ningen

複雑なDI(Dependency Injection)を解決するための話です。当日は理解まで追いつけなかったので、復習。

そもそもDIとは?

オブジェクトが他のオブジェクトを利用するコードを「依存性」と捉え、これらの依存性をもったコードを実行時に注入するため、依存性注入と呼ばれる。

http://e-words.jp/w/DI.html

例えばHTTPクライアントオブジェクトを内部プロパティに持ち、それを使ってリクエストを送信するオブジェクトをテストしたいとします。テスト用に応答を固定したいので、固定の応答を返すダミークライアントに変えたいのですが、Swiftで内部プロパティを直接書き換えられないので困ります。そういう時は、コンストラクタからHTTPクライアントを渡せるようにします。これがDIです。このケースは特に、Constructor Injectionというそうです。

オブジェクトが他のオブジェクトを利用するコードを「依存」していると呼び、上の例であれば「テストしたいオブジェクトは、HTTPクライアントオブジェクトに依存している」と言います。

この発表では、「じゃあAがBに依存していて、BがCに依存している関係があった場合、Aのテストする時、コンストラクタC(B(A()))と、どんどん複雑になってしまう」という話。

動的DI

オブジェクトを生成する前に、依存関係を適宜登録するパターン。

Swinjectというライブラリの紹介。 Swinject/Swinject: Dependency injection framework for Swift

ここで上がってる例を見ると、

let container = Container()
container.register(AnimalType.self) { _ in Cat(name: "Mimi") }
container.register(PersonType.self) { r in
    PetOwner(pet: r.resolve(AnimalType.self)!)
}

つまりPersonType -> PetOwner -> AnimalTypeと依存しており、あらかじめ初期化の流れを記述しておく。このcontainerを使ってインスタンスをこう生成できる。

let person = container.resolve(PersonType.self)!
person.play() // prints "I'm playing with Mimi."

静的DI

型の定義で依存関係をコントロールするケース。

Cake Patternを参考に、Protocol Extensionを使って実現しています。Cake Patternを自分は知らなかったのですが、ScalaのMix機能を使って行うDIパターンのようです。

サンプルコードの方の最後の方を見ると、確かに実装するプロトコルで振る舞いを切り替えられているようです。

class DebugContext: DefaultAComponent, DefaultABComponent {
    static let a: A = DebugContext.createA()
    static let ab: AB = DebugContext.createAB()
}

class ReleaseContext: DefaultAComponent, SimpleABComponent {
    static let a: A = ReleaseContext.createA()
    static let ab: AB = ReleaseContext.createAB()
}

let debugContext = Context(type: DebugContext.self)
debugContext.ab.getAB()

let releaseContext = Context(type: ReleaseContext.self)
releaseContext.ab.getAB()

でも途中までのコードが複雑ですね。ちょっと悩ましい。

難しかったですが勉強になりました。

感想

いろんなレベル感のある発表があって面白かったです。懇親会もいろいろお話聞くことができました。次回もぜひ参加したいです。