ReactとReduxを一通り触ってみた

Flutterのアーキテクチャ組むとしたらReduxだよね、みたいな話を聞いたので、Reduxのお勉強がてらReactやってみるかという程度の軽い気持ちではじめてみました。忘れないうちに備忘録としてまとめておきます。

React

最近、というのも憚られるほどjs系のライブラリが枯れてきている今日このごろですが、Reactです。単体ではデータフローなどには全く関与せず、純粋なViewを管理するライブラリです。特徴としては大きく2つあります。

Virtual DOM

名前の通り、ブラウザが実際に保持しているDOMとは別のReact内部の仮想DOMです。

f:id:t-miliya612:20180610201857p:plain
https://www.html5rocks.com/ja/tutorials/internals/howbrowserswork/#The_rendering_engine

何でそんなことをするのかというと、ブラウザレンダリングの高速化のためです(超ざっくり)。下の写真はブラウザがhtmlとcssを解析・描画していく流れを示したものです。 このうち、特に重い処理がLayoutPaintingの2つで、これが行われる回数・範囲を如何に減らしていくか、というのが課題になります。
初回のレンダリングは仕方ないですが、ユーザーのアクションや外部からのpush通知などのイベントに応じて一部を描画しなおしたりする際、変更があった部分だけを再描画してあげれば、先の2つの処理による負荷を小さくすることができます。
VirtualDOMを使って事前に現在のDOMとのdiffを取ってあげることで、これを実現しようというわけです。

JSX

Javascriptを拡張したXMLライクな言語で、これを使って描画するコンポーネントを記述していきます。

<div className='container'>
  <h1 className='title'>Hello</h1>
</div>

htmlとは少し文法が異なりますが、大体読めばわかるかな、という感じです。rubyerbのような、ただパースして処理をしてくれるもの、とはちょっと違う感じです。
また、Reactにおいてjsxの使用は必須ではありません。現に、reactの入門書として有名(?)なオライリーのこの本はjsx無しで書かれてています。
余談ですが、vimでjsxのシンタックスハイライトを行う際、htmlとして認識させるのが手っ取り早いやり方みたいです。なるほど、確かに。

実践

この本をやってみました。

React入門 React・Reduxの導入からサーバサイドレンダリングによるUXの向上まで (NEXT ONE)

React入門 React・Reduxの導入からサーバサイドレンダリングによるUXの向上まで (NEXT ONE)

扱ってるテーマはすごくいい感じで、これに沿って公式ドキュメントを読み進めていくといいと思います。誤字がちょっとあるのと、扱ってるmaterial-uiのv1.0がリリースされてだいぶ変わってしまった点を除けば良書でした。

material-ui.com

この本で実装したYahoo! shoppingAPIを利用したアプリケーションです。特に本以外の面白いことはしてませんが、一応添えておきます。

github.com

Redux

Reduxは、Fluxアーキテクチャを実装した(と言われていたりいなかったりする)フレームワークです。

flux

f:id:t-miliya612:20180610202050p:plain
https://facebook.github.io/flux/docs/in-depth-overview.html#structure-and-data-flow

facebook.github.io

公式のこの図が有名ですね。やりたいことは、データの流れを一方向にしか流れないように制御することです。
このサイトによると、

This structure allows us to reason easily about our application in a way that is reminiscent of functional reactive programming, or more specifically data-flow programming or flow-based programming, where data flows through the application in a single direction — there are no two-way bindings.

データ管理が双方向にならない分、アプリケーションのロジックはシンプルにデータの流れを記述するものになるんですね。reactiveって単語が出てくるのも納得です。

登場人物

  • View
    • Reactのコンポーネントやhtmlなど、ユーザーにデータを表示したり、ユーザーからのイベントを受け付けたりするもの
  • Action
    • Viewで発生したイベントを通知するメッセージそのもの
    • いわゆるSOAPのリクエストのようなもの?
    • ActionCreatorを通じて作成される
    • typeプロパティが必須
  • Dispatcher
    • 全てのデータフローの中心のハブ
    • Actionを受け取り、Storeへと転送する
    • 全てのデータの変更はDispatcherを経由してStoreへと送られる
  • Store
    • State(アプリケーションで保持するデータ/状態)を管理する
    • DispatcherからdispatchされてきたActionを受け取り、stateを変更する

Redux

github.com

Fluxの流れに従いながら、少し登場人物が増えたり原則が増えたりしています。 Reduxには3つの原則があるのですが、先に中身の方からまとめていきます。

Fluxとの違い

公式サイトに言及がありました。

Unlike Flux, Redux does not have the concept of a Dispatcher. This is because it relies on pure functions instead of event emitters, and pure functions are easy to compose and don't need an additional entity managing them.

  • ReduxにはDispatcherという概念がない
    • ReduxにはEventEmitterよりも純粋な関数であるということが重要(超訳)
    • 副作用がないため管理が楽

Another important difference from Flux is that Redux assumes you never mutate your data. You can use plain objects and arrays for your state just fine, but mutating them inside the reducers is strongly discouraged. You should always return a new object, which is easy with the object spread operator proposal, or with a library like Immutable.

  • データを決して変更してはならない
    • 毎回新しいオブジェクトを生成して返す必要がある
      • object spread operatorなどを使おう

これは状態管理という側面もありますが、Stateが変更されたことをObserveする際の都合もあります。Stateの変更は元のデータと最新のデータが異なっている、ことで検知されるため、元のデータを書き換えてしまうとObserveできなくなってしまうんですね。

これを踏まえた上で、ReduxではDispatcherの代わりにReducerを使用します。

3つの原則

  • Single source of truth
    • Stateは1箇所で管理する
    • fluxの場合は数まで言及されていないみたい
  • State is read-only
    • Actionを発行する、以外の方法でStateを書き換えてはならない
    • Viewからいきなりstateにsetterで書き換えとかやっちゃだめ
  • Changes are made with pure functions
    • 先に書いた通り

middlewareの概念

Reduxにはmiddlewareという概念があります。例えば、loggerや非同期処理といったものを実現してくれるもので、ActionCreatorで生成されたActionがReducerに渡る前に処理してくれます。

全体像

これまでの内容を踏まえると、以下の図が読めてくるんじゃないかと思います。

ちょっと脱線

ここまで読むと、「原則としてはきれいだけど、じゃあHTTP通信の処理とかどこでやんのさ」という気持ちが湧いてきますね。ReduxをMVPのView部分だけに押し込めて残りは別でやっていく、というのも考えましたが、何かあまり上手いやり方ではない気もします……。

qiita.com

qiita.com

超簡単に要約すると、redux-sagaというMiddlewareを使ってtaskという概念を作り出し、ActionがReducerにわたる前にやっつけてあげよう、というわけです。詳しくは上の記事や、公式リポジトリをどうぞ。

github.com

おわりに

ここ数年reactに苦手意識を持っていたのですが、思っていたよりもシンプルで使いやすそうでした。ほんのちょっとstaticなページを作るのにはやりすぎかな、という感じもしますが、client側でここまでデータの処理ができてるからこそAPIの提供者側はきれいなIFを定義できるんですね。
一方。。。

AndroidかGoかという環境で生きていると、Androidの超リッチなIDEやGoのformatterの恩恵に甘えまくってしまいます。いざjs書こうとなると。。。
今の所Vimeslint入れて書いていますが、formatterは欲しいですね。

@kakakakakku さんに2ヶ月間ブログメンターをしてもらった知見まとめ

唐突に4月頭からブログを書き始めてきました。思えば自己紹介も何もなかったので、改めて。

自己紹介

みぃや、といいます。2017年新卒で通信系の会社に入社し、エンジニアとしてお仕事をしています。普段の業務ではAndroid開発や新規事業系の企画などを行っています。

学生時代は、CSとかけ離れた文学系の学部で文字を書いたり読んだりしてきました。その中で、言葉って、言語って何だっけ?といったところから色んな事があり、気がついたらコードを書き始め、今に至ります。基本情報は受かりましたが、結構断片的な知識で何とかごまかしてきてしまいました。

ブログを始めた経緯

入社して1年、面白そうなイベントにフラフラ遊びに行ったり、技術系の本を読んだりして楽しく過ごしてきました。業務中も会社の人たちから色んな技術系の話題が飛び込んできて、学生時代に夢見た技術にまみれた生活に少しずつ近づけています。
一方、そんな環境の中である程度過ごしてくると、大して何にも身に付いてないのではなんていう恐ろしいことに気づいてきてしまいました。このままじゃあかんということで、とりあえずブログでも始めてみようかと思い立ちましたが、下書きを書いては消し書いては消しを繰り返す日々が続いておりました。
これQiitaにあるなとか、これ本の内容転載してるだけだなとか、最後の公開ボタンがなかなか押せないんですよね。

そんな中、「仕事とブログどっちが大事なの?」などの言葉で知られる@kakakakakkuさんのブログメンティ募集のお知らせを見て、即座に応募してしまいました。これが3月終わりのこと。

kakakakakku.hatenablog.com

やりかた

基本的には自由にブログ記事を書きまくります。はじめにブログ記事数の目標を設定し、記事にできそうなネタを大量に洗い出していきます。ぼくは週に2記事を書くことにしました。
それに従って実際に記事を書き、出来たらアドバイスをいただく形です。

学んだこと&よかったこと

業務に使える

会社の人「このライブラリのことちょっと教えてください」
ぼく「あ、それ先週ブログに書いたんでURL送りますね」
みたいなことが実際に起こりました。
コードを書いたりブログを書いたり、学んだことをアウトプットするにも色んな形があります。正直、理想形はコードになるのかなーなんて思っていましたが、他人が読む前提のドキュメントとして残しておく、という点にブログの強みを感じました。自分用のメモも勿論いいのですが、他人に向けた前提で書かれたものとはちょっと異なったものが生まれてきますね。

色んなタイプの本を読むようになった

自分がブログを書くようになってから、他の人のブログを今まで以上に読むようになりました。そうすると、興味のある技術分野以外のものに出くわすチャンスに恵まれました。 あんまり興味がなかった マネジメント系やいわゆるビジネス書まで、エンジニアの目線で紹介された記事に出会うと簡単に手が出て……出費がちょっとつらくなってきます。

情報収集の本気度が変わった

あんまり良いことではないのかもしれませんが、週に2記事書こうとすると何とかしてネタをひねり出そうとしてくるようになります。楽しかった!だけでは記事に出来ないので、本を読んだりイベントに参加したりするときに「これで何書こうかなー」と、常に完成形を考えながら頭に突っ込むようになりました。
これでまでは「何となく楽しい」でやっていた情報収集でしたが、完成形を意識すると一気にそれではやっていけなくなります。コーディングや技術の世界を憧れ駆動で目指してきてしまったがために、技術系の話題に触れているだけで幸せになってしまい……。冒頭に書いたような、結局何にも残らない収集の原因はこの辺にあったんですね。

反省

書き出すのが遅かった

記事を1本1本逐次的に書いていってしまった結果、週2記事の目標がかなりつらくなった時期がありました。特に先週は土日で2記事書き上げるといったハードなペースになってしまいました……焦った……。
一気に仕上げるのではなく、普段から断片的なメモを残していくスタイルを作っていこうと思います。

ブログに引っ張られすぎた

テーマ選びであれもこれもとやると、ブログのために今週あれやりたかったけど我慢しなくちゃ……と、テーマが縛られてしまうことがありました。あれ、何のために書いてるんだっけ?
個人的に、ブログを書くもともとの目的はインプットを残すこと、副次的な目的として他の人に読んでもらったりとか何かの機会で使えたら、といったものがありました。あまりにブログベースでやりすぎると、特にシリーズものの記事なんて書いてしまうと大変つらいことになります。
ブログは大事だけど、それだけを目的にしちゃいけないなぁと。

今後について

エンジニアとして

自分のキャリアとして、今の所Android楽しいのでAndroid開発を続けていきたいと思っています。一方、最近CSの知識のなさをつくづく実感することが多くなってきました。。。記事を書くにあたって、調べなきゃいけないことだとか何かふわふわしてることだとかが顕著に現れてきました。
そのため、もうちょっと基本的なところについてもやっていきを図っています。今更ながら、アルゴリズム系や低いレイヤーの部分を眺めていきたいと思います。

ブログとして

新しい技術を学ぶ時間、基本的な知識を身につける時間をちゃんとそれぞれ確保していくため、ブログは新しい技術をアウトプットするものとし、更新を最低週1にしようと思います。
一方、CSの知識の勉強の場も何か作っておきたいところです。こっちのテーマをブログにしなかったのは、日付単位で区切りをつけたくなかったためです。テーマごとに、ちょくちょく気づいたことは追加していける形式でやっていけたらいいなと思います。
Githubのtilリポジトリでもやってみるかなぁ。ちょっとこのあたりは模索しつつやっていきたいです。目標はコミット数レベルで切ることになるんでしょうか。

GitHub で使われる慣習的なリポジトリについてまとめてみた

おわりに

とりあえず2ヶ月間続けてみることで、意外と書けるもんだな、という自信が生まれました。正直なところ、今の自分の業務が今やりたいことにとってベストなのかどうかは分かりません。ですが、常に自分がやりたいことをやるってのも現実味のない話ですし、とりあえずやっていける環境作りをする、という意味でもブログチャレンジ(?)は非常に有意義だと思います。

改めまして、筆の遅い僕の尻を根気強く叩いてくれたkakakakakkuさん、ありがとうございました!
今後も募集があるようでしたら、日常に何かもやもやしている人はぜひ門を叩いてみてください。

Android Things事始め

先日、DroidKaigi Codelabs Tourにお邪魔したところ、Android ThingsのStarter Kitをお借りして試すことができました。

f:id:t-miliya612:20180527005402j:plain

やってみたのはこれです。

Android Things Image Classifier

TensorFlowLite使った画像認識!……ですが、既に学習済みのモデルを用意してくれていました。今回は、学習させる部分ではなく、認識させる部分のみを実装します。
ちなみに、全体で75分かかることになっていますが、ハードウェアの実装で40分ほど確保されています。そんなに時間をガッツリ確保できなくても進められます。

まずはサンプルの犬の画像を認識してもらいます。Portuguese Water Dogという犬がいるんですね。ただのビショビショの犬じゃなかった。

f:id:t-miliya612:20180527005452j:plain

光って読めませんが、curly-coated retriever, Border collie or English spinnerと認識しています。画像とはちょっと違いますが、学習済みデータの都合とのこと。大体犬です。

次に、カメラに接続して実際に撮影した画像を認識していきます。
Import文にhardware関連が並んでいるのはちょっと新鮮です。

import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.StreamConfigurationMap;

f:id:t-miliya612:20180527005513j:plain

iPod……!惜しい!

Codelabは以上です。お試し用なので認識精度はそんなに高くはありませんが、いつものAndroidStudioを使ってIoT向けに遊べるというのは最高ですね。


……と思いながらブラウザで無心にボタンをクリックしていたところ、不思議なメールが来ました。

f:id:t-miliya612:20180527005610p:plain

そして本日、不思議な箱が到着しました。

f:id:t-miliya612:20180527005920j:plain

台湾からの配送で、税関で別途2080円かかりました。

開けてみた様子です。

f:id:t-miliya612:20180527010020j:plain

中にはこんなものが。

f:id:t-miliya612:20180527010041j:plain

箱の裏側に、中に入っているコンポーネントの説明が書いてあります。さすがgoogle……!

f:id:t-miliya612:20180527010100j:plain

内容物は以下の通りです。

  • メインのボード(NXP i.MX7D)
  • ディスプレイ
  • WiFi用アンテナ
  • カメラ
  • USBケーブル
  • ドライバー
  • Rainbow HAT

Android Things向けに開発された、Raspberry Piに接続して利用する多彩な拡張基板です。温度・タッチセンサ、ブザー、LEDディスプレイなど様々な入出力を試すことができます。

www.switch-science.com

サイトの案内に沿って組み立てていきます。組み立て後のセットアップのために、Androidの端末が1台あると便利です。

androidthings.withgoogle.com

完成品がこちら。

f:id:t-miliya612:20180527010155j:plain

ここで電源を入れるとAndroidが起動する……はずだったのですが、この段階ではまだイメージが焼かれていなかったので作業を続けます。

NXP i.MX7D  |  Android Things  |  Android Developers

まずはここからセットアップツールを落とします。Googleアカウントが必須です。

Android Things Console

落としてきたzipファイルを解凍し、中に入ります。

$ ls
README.md                                android-things-setup-utility-macos       quickstart-temp
android-things-setup-utility-linux       android-things-setup-utility-windows.exe

各OS用にツールが用意されています。今回はmacでやっていきます。

$ ./android-things-setup-utility-macos

...
What do you want to do?
1 - Install Android Things and optionally set up Wi-Fi
2 - Set up Wi-Fi on an existing Android Things device

インストールするのでを選択。

What hardware are you using?
1 - Raspberry Pi 3
2 - NXP Pico i.MX7D

購入したモデルを選びます。今回はを選択。

Setting up required tools…
Fetching additional configuration…
Downloading platform tools…
Unzipping platform tools…
Finished setting up required tools.

ツール群のダウンロードが始まります。

Do you want to use the default image or a custom image?
1 - Default image: Used for development purposes and supported by Android
Things Toolkit, a mobile companion app that can be downloaded at
https://goo.gl/rPWhmv. No access to the Android Things Console features such as
metrics, crash reports, and OTA updates.
2 - Custom image: Upload your custom image for full device development and
management with all Android Things Console features.

インストールするイメージを選択します。クラッシュレポートやOverTheAirでのアップデート配信など、製品化を向けたイメージはカスタムのみの機能です。今回はとりあえず動かすのが目的なのでデフォルトイメージを選びます。

Connect your device to this computer:
The USB cable should plug into your board’s USB-C port. If your computer also
has USB-C ports like the more recent MacBooks, you will need to use a USB hub.
Otherwise the board won’t power on correctly.

Once connected, press [Enter] to install Android Things on the device...

KitをPCに繋ぎます。type-cにはハブが必要、とまで丁寧にメッセージが出てきます。接続したらEnter。

Looking for devices… This can take up to 3 minutes.
found device
Unzipping image…
Flashing Android Things. This will take a few minutes…
*Do not disconnect or interrupt!*

バイスが見つかると実際に焼き始めます。いじらずに待ちます。 この辺からLEDが光り始めます。結構眩しいので注意してください。

finished. total time: 124.358s

Successfully flashed your imx7d.
Successfully flashed Android Things…
Would you like to set up Wi-Fi on this device? (y/n)

f:id:t-miliya612:20180527010754p:plain

いずれ終わります。その後Wi-Fiの設定に入りますが、今回はAndroidのアプリを使って行うのでnを選択します。
そして、AndroidスマホAndroid Things Toolkitを起動します。

f:id:t-miliya612:20180527010600p:plain

f:id:t-miliya612:20180527010615p:plain

Kit側に4文字のコードが表示されるので、画面の指示に従って入力します。
その後、WiFiの設定も行います。

f:id:t-miliya612:20180527010631p:plain

ここでKitの動作確認ができます。僕の場合、カメラモジュールが動きませんでした。 つらいので秋葉原で探してきます。

f:id:t-miliya612:20180527010715p:plain
f:id:t-miliya612:20180527010739p:plain

テストの結果にかかわらず、一通り設定が完了です。
Android Thingsのバージョンが、1.0になっていることを確認しましょう(2018/05/27現在)。このバージョンが低いと、codelabのアプリが動きません。 具体的には、rainbow HATのボタンをinitializeするところでコケるみたいです。

あとは自由にアプリを開発するだけです。最後に、参考になりそうなリンクをいくつか貼っておきます。

Healthtech Meetup vol.1に参加したらネイティブアプリの未来がちょっと見えた話

Healthtech Meetup vol.1に参加してきました。
ヘルスケア系のサービスに取り組むスタートアップのエンジニアが集まるイベントで、システム開発の知見だけではなく幅広いテーマでの発表を聞いてくる事ができました。

connpass.com

Main Session

「継続を支える」ライフログの利用と技術 in FiNCアプリ」

株式会社FiNC 森久太郎さん @qsona

行動変容ステージモデルが特に勉強になりました。使うことで便利になる、といった性質ではないアプリにおいて、どうやってユーザーに寄り添っていくかって難しいです。また、WIPとのことだったので省いたものもありますが、機械学習を使った施策も面白かったです。

AI×創薬の最近の事情

株式会社ディー・エヌ・エー 望月正弘さん

  • AI創薬
    • AIを用いた新薬の開発を行う
      • 論文を読ませる
      • 薬剤投与時の遺伝子発現データを用いる
      • 化合物の構造を学習する
  • Fingerprintを使った機械学習
    • 90年代に発見
    • 化合物の特徴を表現したベクトル
    • IT創薬コンテストで、DeepLearningを用いた学習にも対抗できた

唯一のアカデミックな話でした。内容もさることながら、機械学習に明るくない僕でも引き込まれるような分かりやすい構成でした。バズワードとなったDeepLearningを使ったから結果が出るわけではない、耳が痛い話です。。。

新規サービスでGo, GAEを使ってみた話とその振り返り

DeSCヘルスケア株式会社 鶴田拓也さん@o_tyazuke

speakerdeck.com

  • 採用理由
    • サクッと作ってサクッと潰したい
    • 社内の知見を増やす
    • GAEのStandardEnvironmentでRails使えない
  • 開発の流れ
    • Github
    • CircleCI
      • QAブランチごとにGAEのバージョンを作ってデプロイできるように
    • GAE
  • アナリティクス
    • GAE
    • Datastore
    • BigQuery
    • Data Studio
  • 失敗したこと
    • 歩数は最新のものが届くとは限らない
      • iOSのヘルスケアへの書き込みにラグがあるのが原因
      • 対策: 書き込みを待つ、書き込みイベントを発火させる(ヘルスケアを開く)
    • Goのアンチパターンを踏んだ
      • structにcontextを詰めていた

みんな大好きGo言語の話。GAEの導入に際した生の知見です。業務だと既にAWSの環境が整っているため導入は難しいのですが、聞けば聞くほど惹かれていく。。。
また、構成の話も面白かったです。アナリティクスの話は、稼働しているサービスだからこそ得られる経験ですね。

某サービスのリニューアルでECSを導入したよもやま話

株式会社エス・エム・エス 光宗朋宏さん(@t_mitz)https://twitter.com/t_mitz

speakerdeck.com

  • リファクタリングに合わせて既存サービスにECSを導入
  • 理由
  • 他サービスとの比較
    • Google Kubernetes Engine
      • 当時のIAMの仕様とセキュリティ要件がマッチしなかった
      • AWSのナレッジを蓄積させたかった
    • Kubernetes on AWS
      • 学習コストが高い
      • フルマネージドに寄せて簡単に環境構築したい
  • 構成
    • CircleCI
      • 今はテストの実行のみ
      • docker imageのbuild&pushは時間の関係でやめた
    • CodePipeline
      • Githubのブランチを監視して更新があるとデプロイ
    • Logging
      • awslogs driverでCloudWatch Logsに収集
      • 特に困ってない
      • 本番環境にするときはKibanaにするかも
    • ECS
      • 1サービス1タスク定義
      • 1タスクに3つのコンテナ
        • h2o(httpサーバー)
        • rails
        • shoryuken(gem)

打って変わってAWSの話です。普段CircleCIはAndroidのバイナリを生成してくれるサービスという認識だったので、サーバーサイドの話の中で登場するとちょっと新鮮でした。他サービスとの比較検討も、ヘルスケアといったテーマで括る勉強会ならではのものですね。


LT

m3.comを支える巨神の話

エムスリー株式会社 池田貴世志さん(@progrhyme)https://twitter.com/progrhyme

speakerdeck.com

  • 歴史あるサービスを改善し続けている話
  • 問題点
    • 複雑なサービス間通信
    • ビュー要素を再利用できず、各サイトで再実装している
    • API Aggregatorを活用できていない
  • 対策
    • Atlasの導入
      • フロントエンドのHTML生成を担当
      • サービス間連携の標準化を推進
    • DBを直参照していたものをAPI

大量のユーザーを抱えたサービスの設計と戦い続ける話です。m3.comは名前は知っていたのですが、お恥ずかしながらこんな大規模なサービスだとは知りませんでした……。
抽象度の高い設計思想の話ではなく、1システムをこうしたおかげで改善されたという具体的な話は、なかなか調べただけじゃ引っかからないので来て良かったです。

過去の負債と戦う(テクニック編)

株式会社エス・エム・エス 岡田数馬さん(@okazu_dm)https://twitter.com/okazu_dm

speakerdeck.com

  • 改善すべき点(負債)の改善には普段の備えが重要
  • 負債は普段はぼんやりしているもの
    • 特定する必要がある
  • 改善活動を支えるツール
    • New Relic
      • アプリケーションをリアルタイムで監視してくれるサービス
      • 重いEndPointや大量のQueryを探し出してくれる
      • クエリ発行数を60%に
    • Cloud Forecast
      • JVMの負荷も見られる
      • キャパシティプランニング、インフラコストを1-2割減

まさに「推測するな、計測せよ」に則った話です。ネイティブのアプリだと、端末の内部処理をここまで細かく特定している話ってあんまり聞かないような……?
また、ツール群を使って見つけたボトルネックの解消にいたるまでのフローも聞いてみたいです。

iOSでのバックグラウンド歩数同期

株式会社DeNAライフサイエンス 馬場南実さん

  • やりたいこと
    • バックグラウンドで歩数を計測したい
  • バックグラウンド処理
    • androidだと簡単だが、iOSだと制限が厳しい
    • 音楽の再生
      • 再生し続ければ処理を続けられる(無音を再生し続ける!)
    • 位置情報更新を受け取る
      • 地図アプリは閉じてても案内してくれる
    • 電池消耗の課題
  • background fetch
    • iOSの任意のタイミングで呼ばれるタイマー
    • 呼ばれたタイミングで必要な処理を行う
      • 歩数取得
      • ゴールに到達したか
      • push通知表示
    • 呼ばれる頻度は不定
  • サーバーからのpush通知
    • background fetchの補助
    • 通知を受信したタイミングでバックグラウンド処理
    • ユーザーへの表示はされない サイレントプッシュ

ネイティブアプリの話ということもあってか、1番実感しながら聞けたセッションでした。iOSつらいという話は聞いてはいたのですが、まさかここまでAPIが塞がれているとは。。。無論敵わない点はありますが、Androidの豊富なAPIを当たり前に思ってはいけないですね。
また、バックグラウンド処理をめぐる血の滲むような努力は涙無しには聞けません。無音で音楽流しっぱなしはだいぶ賭けに出たやり方ですね……。

メディカルノート開発/インフラのあゆみ

株式会社メディカルノート 河本穣さん(@k12u)https://twitter.com/k12u

speakerdeck.com

  • 気をつけているところ
    • なるべくマネージドサービス
    • IAAC(infra as code)
    • SSM parameter store
    • packer + ansible
    • Terraform workspace
  • 進化の軌跡
    1. シングルインスタンス
      • admin作業でサイトが落ちる
    2. adminインスタンスの分離
    3. ELB化
    4. CDNフルキャッシュ化
      • HTMLコンテンツごとキャッシュ
      • 今はサーバーレスで配信
  • Infrastructure as Code
    • AMIプロビジョニング
      • packer/ansible/CI
      • アプリケーションや環境に依存しないもの
      • rootで動かすもの
    • プロジェクト環境構築
      • プロジェクト環境のセットアップ
      • ネットワーク
      • サーバー構成
    • インスタンス起動時/デプロイ時
      • ライブラリインストール
      • 依存性解決
  • チャレンジしやすいプロジェクトでは積極的に
    • 一方、駄目なものは駄目と言えることが大事
  • チーム
    • 設計レビュー
    • 実装後レビュー
    • 毎週のKPT確認
    • 運用と開発のチームが 半歩はみ出す
      • 非効率性は境界部分に発生しがち
  • おまけ
    • サービス名を絵文字で表現できるようにすると楽

チーム運営の話が特に勉強になりました。半歩はみ出そうとすること、そして半歩はみ出されることの両方を良しとする文化形成は壁の多そうな取り組みです。
また、サービス名を絵文字で表現する、というのも当日Twitterで話題になりました。名前はかっこいいけどスペルに気を使わなきゃいけなかったり、もしくは略称ばかりでこれなんだっけシステムが続出したりするような事案が発生しがちなので、ビジュアルで認知できるのは強みですね。


まとめ

先日病院のお世話になったこともあり、個人的に非常に関心の高い分野のミートアップでした。健康に取り組む人々をどう支援していくか、という戦略的な面から具体的なシステムの面まで、よくここまで散らばったなと思うくらい幅広いテーマの発表でした。
また、個人的にはネイティブアプリ開発のモチベーションが上がった会でもありました。普段開発しているアプリは、webブラウザよりも優れた体験を与えることを目的にしたものが多かったです。PWAなどを代表とするWeb技術群も流行ってきて、ネイティブアプリって今後どうなってしまうんだろう、という不安も抱えていました。一方、ライフログという観点で見ると、そこにネイティブアプリの優位性があるのかなと感じました。AndroidにはFitAPIもあるし、さらにFitbitなどAPIを提供してくれている外部デバイスと組み合わせることもできます。
ちょっと感度を上げながら新しいサービスを眺めていってみたいです。

『DNSをはじめよう』を読んで実際にappドメインを買ってみた

先日、google.appドメインの一般登録を開始しました。

japanese.engadget.com

ネイティブアプリ開発をお仕事としていることもあり、不思議な使命感に駆られて契約してました。その際、先日技術書展4で購入した『DNSをはじめよう』が役に立ったのでまとめてみます。

DNSをはじめよう』について

著者はmochikoAsTechさん、技術書展において750冊売り切りを達成した恐るべき本です。その後もboothにて売れ続けていると言われています。

今は電子版のみです。

mochikoastech.booth.pm

この本のゴールとして、以下のものが挙げられていました。

・ドメインを買うときは何に注意してどこで買ったらいいか分かっている
Whois情報に何を登録すべきか分かっている
・ 障害が起きたときに黒い画面(ターミナル)で dig コマンドや whois コマンドを駆使して原因を調査できる
サイト移管時に「DNS 浸透待ちで 8~24 時間くらいは切り替わりません」みたいなことを言わない
・読む前より DNS が好きになっている

4つ目が刺さりますね。。。

目次

  1. ドメインWhois
  2. DNSの仕組み
  3. AWSのネームサーバ(Route53)を使ってみよう
  4. digとwhoisを叩いて学ぶDNS
  5. トラブルシューティング

感想

サービスの創世記に携わったりしない限り、なかなかドメインの管理に携わることって無くてですね。趣味でいじったとしても、1回紐付けたら後はそのままにしてしまうので……。
本書は、ドメインに関する知識を疑問ベースで丁寧に扱っており、著者のドメイン愛とそれを広めたい思いがとんでもない熱量で伝わってきます。途中で挟まっているドリルもすごく「上手いな」と感じました。
個人的に1番役立ったのは、リソースレコードについて扱っている章です。AやらNSやら、よくわかんないけどマニュアルに沿ってやっていればOKくらいの認識しかなかったので、良い復習になりました。
また、digコマンドやwhoisコマンドも勉強になりました。これでいちいちブラウザからwhois情報を調べなくてもいいんですね……!

中身からは離れますが、実際の書籍自体のクオリティも高いです。半透明の遊び紙、これいくらするんだろう……。技術書、ニッチな分野も対応するせいか商業誌だとこういうこだわりになかなか出会えないのでちょっと嬉しくなってしまいました。

f:id:t-miliya612:20180520215831j:plain
遊び紙

appドメインについて

.appドメインは、googleドメイン登録サービスのGoogle Registryが提供するトップレベルドメインです。大きな特徴としては、HTTPS接続が必須であるということ……のようです。どうやってるんだろう。

Registry – Google

また、google.appドメインの紹介文を提供してくれているので添えておきます。この文章使ってね、とのこと。

Apps make the mobile world go ‘round, and now they have their own more secure home on the web: the .app domain, the most relevant TLD for mobile apps. You can use your .app name to showcase a unique and trustworthy destination, as a relevant download link, for deep linking, or for sharing screenshots, release notes, and reviews. Get your .app domain now to start sharing your app with the world.

せっかくなのでGoogle翻訳に頼ります。

アプリでは、モバイル世界が一巡し、現在はウェブ上により安全なホームがあります。.appドメインは、モバイルアプリにとって最も関連性の高いTLDです。 .appの名前を使用すると、一意で信頼性の高い宛先、関連するダウンロードリンク、深いリンク、スクリーンショット、リリースノート、レビューの共有などを表示できます。今あなたの.appドメインを取得して、あなたのアプリを世界と共有しましょう。

deep linking惜しい……!!

公式サイトのAnnouncementを見ると、

  • 2017/12/14: .app.devをopenなTLDとして、2018年の前半に提供することが最終決定
  • 2018/05/01: リリース計画が確定
    • 03/29-05/01: 商標を持っている人のみ登録可能な期間
    • 05/01-05/08: Early Accessとして、追加料金を払うと登録可能(追加料金はだんだん下がっていく)
    • 0508-: 全体向けに登録開始
  • 2018/05/02: Early Access期間の追加料金に関する方針が決定
    • 05/01-05/05にかけて段々追加料金が下がっていく
    • 追加料金はレジストラによって違う

のプランで進んでいったみたいです。TLDの立ち上げの一連の流れを追うのも面白いです。
ちなみに.devもローンチに向けて動いているようです。これ、本のトラブルシューティングで言及があったやつですね!

登録について

今回、miliya.appドメインを取得しました。
僕はHPをよく読まずに焦ってEarlyAccessの期間に登録してしまいました。やたら高いと思ったら追加料金だったのか……

今回の場合、レジストリgoogle registryなので、レジストラかリセラを探せばよい、とのことになります。
が、お馴染みお名前ドットコムやムームードメインは取扱業者のリストには無く。。。

Registry – Google

ドキドキしながらも海外のレジストラの中から、name.comで登録してみることにしました。ほとんど勘ですが、こんな人気ありそうなドメインで運営してるってことは大丈夫じゃろ、くらいの気持ちです。

流れ

そんなに難しいことはありませんでした。

  1. 05/02: 会員登録 f:id:t-miliya612:20180520214906p:plain

  2. 05/02: ドメインの契約(Paypal使えました。) f:id:t-miliya612:20180520214929p:plain

  3. 05/09: 24時間以内にアカウントにドメインが追加されるよ、とのメール f:id:t-miliya612:20180520214953p:plain

  4. 05/09: 登録完了通知。Whois privacyも追加するといいよ!とのメッセージ。 f:id:t-miliya612:20180520215021p:plain

  5. 05/09: Whois privacyを追加(追加料金あり)。1分くらいで反映完了メールが来ました。 f:id:t-miliya612:20180520215051p:plain f:id:t-miliya612:20180520215106p:plain

お値段

  • domain: $14.99/year
  • Whois privacy: $4.98/year

合計で年間$20くらいです。なかなか高いです。。。

実験

実際にdigwhoisを叩いてみましょう。

; <<>> DiG 9.10.6 <<>> miliya.app
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5651
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;miliya.app.            IN  A

;; ANSWER SECTION:
miliya.app.     300 IN  A   91.195.240.82

;; Query time: 112 msec
;; SERVER: 2400:402f:9f1f:1100:225:dcff:fe1e:ee57#53(2400:402f:9f1f:1100:225:dcff:fe1e:ee57)
;; WHEN: Sun May 20 21:08:32 JST 2018
;; MSG SIZE  rcvd: 55
$ whois miliya.app
% IANA WHOIS server
% for more information on IANA, visit http://www.iana.org
% This query returned 1 object

refer:        whois.nic.google

domain:       APP

organisation: Charleston Road Registry Inc.
address:      1600 Amphitheatre Parkway Mountain View, CA 94043
address:      United States

contact:      administrative
name:         Domains Policy and Compliance
organisation: Google Inc.
address:      601 N. 34th Street
address:      Seattle, WA 98103
address:      United States
phone:        1 202 642 2325
fax-no:       1 650 492 5631
e-mail:       iana-contact@google.com

contact:      technical
name:         Richard Roberto
organisation: Google Inc
address:      76 9th Avenue, 4th Floor
address:      New York, NY 10011
address:      United States
phone:        1 212 565 2633
fax-no:       1 650 492 5631
e-mail:       crr-tech@google.com

nserver:      NS-TLD1.CHARLESTONROADREGISTRY.COM 2001:4860:4802:32:0:0:0:69 216.239.32.105
nserver:      NS-TLD2.CHARLESTONROADREGISTRY.COM 2001:4860:4802:34:0:0:0:69 216.239.34.105
nserver:      NS-TLD3.CHARLESTONROADREGISTRY.COM 2001:4860:4802:36:0:0:0:69 216.239.36.105
nserver:      NS-TLD4.CHARLESTONROADREGISTRY.COM 2001:4860:4802:38:0:0:0:69 216.239.38.105
nserver:      NS-TLD5.CHARLESTONROADREGISTRY.COM 2001:4860:4805:0:0:0:0:69 216.239.60.105
ds-rdata:     41971 8 2 858FEEE8930855598DB109C9705955EDF494FA641ED1CDD07A95C13357E9FD19
ds-rdata:     23684 8 2 3a5cc8a31e02c94aba6461912fabb7e9f5e34957bb6114a55a864d96aec31836

whois:        whois.nic.google

status:       ACTIVE
remarks:      Registration information: http://www.registry.google

created:      2015-06-25
changed:      2018-03-20
source:       IANA

Domain Name: miliya.app
Registry Domain ID: 2CB00A0B8-APP
Registrar WHOIS Server: whois.nic.google
Registrar URL: http://www.name.com
Updated Date: 2018-05-09T03:39:40Z
Creation Date: 2018-05-08T16:00:44Z
Registry Expiry Date: 2019-05-08T16:00:44Z
Registrar: Name.com, Inc.
Registrar IANA ID: 625
Registrar Abuse Contact Email: abuse@name.com
Registrar Abuse Contact Phone: +1.7203101849
Domain Status: clientTransferProhibited https://icann.org/epp#clientTransferProhibited
Registrant Organization: Domain Protection Services, Inc.
Registrant State/Province: CO
Registrant Country: US
Name Server: ns1lmy.name.com
Name Server: ns2bkr.name.com
Name Server: ns3cgw.name.com
Name Server: ns4htz.name.com
DNSSEC: unsigned
URL of the ICANN Whois Inaccuracy Complaint Form: https://www.icann.org/wicf/
>>> Last update of WHOIS database: 2018-05-20T12:06:31Z <<<

ちゃんとprivacy設定も反映されてます!

まとめ

DNSをはじめよう』のおかげで安心してドメイン取得できました。本のゴールにもあった、

サイト移管時に「DNS 浸透待ちで 8~24 時間くらいは切り替わりません」みたいなことを言わない

これ、学生の頃そのまんま喋ってました……お恥ずかしい……。
学生の頃はサークルのHPを作る、みたいな用途でよくわからないまま触っていたドメインDNSの仕組みも、一回理解してしまえばえらく安心感を持って弄ることができますね。こういう本が、エンジニアではないような人達に幅広く届く場にあればなぁと切に思います。
また、せっかく取得したドメインを取得したので早く使っていきたいですね。はてぶろに課金するか、ポートフォリオサイト作るか……迷いますね。

#dartlang_jp のFlutterハンズオンで再度Flutterを触ってみた

この前の日曜日にFlutterのハンズオンに参加してきました。

dartisans-jp.connpass.com

  • 講師
    • ntaooさん 読み方は特に決めてないそうですが、「えぬたおさん」でいいとのこと。
  • 資料

docs.google.com

docs.google.com

dart自体から実際のFlutterアプリまで、かなり盛りだくさんな内容でした。

以前に一度公式のtutorialはこなしていたのですが、プラスαで学べる事が多かったのでまとめておきます。

講義

Dart

FlutterからDartを知ったのですが、Dart自体はもともとWeb用の言語だったそうです。2004年頃からWeb以外もターゲットにした汎用プログラミング言語としての道を歩み始めたとのこと。
また、開発時はJIT, リリース時はAOTコンパイルを実行する点、言語レベルで非同期処理を実装している点などが特徴みたいです。
全体的な文法はJavaとJSにそっくりです。言語自体は意図的に面白くなくしており、簡単に習得できるように設計されています。

Flutter

Flutter自体は前回も触れましたが、復習もかねて。

  • 特徴
  • 構造
    • coreとなるEngine部分はC++で書かれている
    • documentもしっかりある
  • パッケージ管理システム
    • Pub package manager
    • https://pub.dartlang.org/
    • ユニバーサルに使えるコアパッケージと各プラットフォーム向けに使えるパッケージがある

参照

ハンズオン

作ったもの

f:id:t-miliya612:20180520220251p:plain

hacker news(https://news.ycombinator.com/)のニュースリーダーです。実際に外部APIを叩いています。
f:id:t-miliya612:20180519190553j:plain

ニュースをタップすると、WebViewが開いてページを表示できます。
f:id:t-miliya612:20180519190644j:plain

また、ニュースをお気に入りに登録できます。お気に入りリストも見ることが出来ます。
f:id:t-miliya612:20180519190618j:plain

さらに、Pull(Swipe?)-To-Rrefreshも実装。ネイティブをやっていく自信がなくなってきますね。
f:id:t-miliya612:20180519191216j:plain

ゆっくり調べながらやっていたら当日終わらなくて、後日改めてやり直したコードがこちら。コメント多めです。

github.com

学び

ほんとに何から何までWidgetであること

特にDividerなんて顕著ですが、marginから何から全部がWidgetとして扱われます。HTML書いている時にpaddingにするかmarginにするか悩むことが多かったのですが、Flutterだとその辺何も考えずに決められそうでいい感じです。

ネイティブのUIの充実

アイコンとPullToRefreshで実感しました。今回はボタンなどは使用していないためあんまりMaterial感を体験できていないのですが、ネイティブで書くより互換性を気にせずもりもり書けるのはちょっと爽快感があります。 ちなみに、AndroidminSdkVersionはデフォルトで16に設定されていました。環境によって違うのでしょうか。
また、アイコンですが、Iconsクラス配下に大量に用意されています。以下のサイトに一覧があるのですが、数えてみたら 985個もありました。笑う。

docs.flutter.io

つらかったところ

書いていくうちに、インデントとカッコの対応が崩れた瞬間の絶望感。。他の言語よりも崩れたときの復帰がしんどい印象でした。Android StudioのDartAnalysisを使えばかなりわかりやすくなりますが、これがなかったらと思うと……恐ろしいですね。
f:id:t-miliya612:20180519190824p:plain

正直初めは何やってるのか全く分かりませんでしたが、2回目をやり直したらだいぶ目が慣れてきました。 marginからdividerから何までWidgetであるということを忘れなければ大丈夫だと思います。
また、やっぱりネイティブと比べてしまうと不安定なところはあります。例えば、ListViewを勢い良くスクロールすると……たまに落ちたします。この辺のキャパシティというか、何も考えずに書いてもある程度いい感じにやってくれるのは、もしかするとネイティブの方なのかなぁ、などと。

lintについて

ハンズオンでは参考程度くらいでしか触れられていないのですが、Flutter(Dart)のlintについてです。
デフォルトでは、override時のアノテーション(@override)は添えていなくてもエラーが出ないようになっています。ただ、慣れていないうちにタイポ等もろもろつらかったので、試しに追加してみました。手順は以下の通りです。

  1. projectのrootにanalysis_options.dartを作成する。
    • これ、もとは.analysis_optionsだったみたいなのですが、変更加えるそうなので前者がおすすめだそうです。
  2. 中身をこんな感じに書く。
analyzer:
  strong-mode: true
  errors:
    todo: ignore
  exclude:
    - flutter/**
    - lib/api/*.dart

linter:
  rules:
    - avoid_empty_else
    - cancel_subscriptions
    - close_sinks
    - annotate_overrides

以上です。簡単ですが、忘れず設定しておきたいです。
詳しくは、以下のリンクを参照してください。

www.dartlang.org

Linter for Dart

感想

Flutter公式のtutorialにプラスした部分もあり、かなり実用的なハンズオンでした。このアプリ普通に使えますね……。そして、何故か忘れがちですがこれがAndroidiOS両方で動いているというの、改めて恐ろしいです。
ただ、やっぱりそろそろファイル1枚に書いていくスタイルが厳しくなってくる分量だと思うので、まずはこれを分割していくところが次のステップでしょうか。
また、今後はチャットアプリなど外部のAPIにPOSTしていくようなものも触ってみたいです。次は話題のFirebaseですかね……!
講師のntaooさん、主催の方々、ありがとうございました!


追記

講師のntaooさんよりコメントいただきました!
コーディングの際に、プラグインのおかげで強力なalt+enterの補完が使えるそうです。詳しくは以下のリンクとこの記事のコメント欄を参照してください。

flutter.io

GoogleI/O行ってないけどAndroid Jetpack気になったので調べてみた

先週はGoogle I/Oでしたね。現地にも行かずリアルタイムで見ることもしませんでしたが、TwitterのTLから現地のレポートを見てそわそわしていました。
KeynoteでのAndroid P発表も騒がれましたが、何やらJetpackとやらが話題の様子。Googleがdocumentを揃えてくれているので、読んでみました。

なお、翻訳ではなくメモ程度です

developer.android.com

What’s

公式サイトによると、

Jetpack is a set of libraries, tools and architectural guidance to help make it quick and easy to build great Android apps. 

とのこと。後述する内訳も見ると、これまでGoogleが提供していたArchitectureComponentを含んだコンポーネント群、のような感じでしょうか。

What’s included

4つの区分があるようです。

Foundation

Android開発の全領域に関わるコンポーネントが入っています。AppCompatよく分からんけど使っとくか、みたいな時期がすごく長かったので、個人的にこれがちゃんと分類されたことはすごく嬉しいです。

Architecture

  • Data Binding
  • Lifecycles
  • LiveData
  • Navigation
  • Paging
  • Room

ここがいわゆるArchitecture Componentが入るカテゴリのようですね。データの永続化、データ変更の通知などを行うものから、ライフサイクルのつらみをラッピングしてくれるものまで詰まっています。 正直まだ全部は分かってないので詳しくは書きません。
Navigationのところは、Androidアプリのデザイン自体とも絡んできそうなので、早めに読みたいです。

Behavior

  • Download manager
  • Media & playback
  • Notifications
  • Permissions
  • Sharing
  • Slices

制作しているアプリが、他のアプリやOSなどと上手くやっていくところをお手伝いしてくれるコンポーネント群、という理解です。
特に気になったのはNotificationsとSlicesです。前に業務でウィジェット(ホームスクリーンに出てくる方)を作ることがあったのですが、通知やらUI微妙に作りづらい問題やらで結構苦労しました。この辺がきれいに作れるようになってるといいなぁ……。(まだ見てない)

UI

  • Animation & transitions
  • Auto
  • Emoji
  • Fragment
  • Layout
  • Palette
  • TV
  • Wear OS by Google

当たり前なのですが、UIというだけあって、handset以外のモバイル端末から車までもをサポートするコンポーネントが揃っています。スマホだけがAndroidアプリ開発じゃないんだ。
加えて、おなじみFragmentから絵文字、アニメーションを対象としたコンポーネントが入っています。

How to use

developer.android.com

具体的な使い方は各コンポーネント群をインストールして……となるのです が、Jetpackベースでアプリを作る時のハンズオン?のようなものも用意されていました。

Android Studioの3.2+が必須条件です。まだアイコンが緑色の人(2018/05/12時点)は、公式サイトからPreview版をインストールしましょう。 Stable版とは違う名前でインストールされたのでご安心を。

f:id:t-miliya612:20180513030135p:plain

次に、新しくプロジェクトを作ります。
すると……

f:id:t-miliya612:20180513030156p:plain

新顔がいますね。Activity & Fragment + ViewModelだそうです。

f:id:t-miliya612:20180513030213p:plain

ActivityやFragmentとそれらに紐づくlayout配下のXMLの名前を聞かれます。さらに、ViewModelの名前やFragment package pathを入力する項目がありますね。

とりあえずそのままにしてFinishを押すと……

f:id:t-miliya612:20180513030227p:plain

Activity, Fragment, ViewModelが出来ています。Activity以外はuiパッケージに押し込めてくれています。
ソースはかなりシンプルですが、以下のとおりです。

Activity

...
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main_activity)
        if (savedInstanceState == null) {
            supportFragmentManager.beginTransaction()
                    .replace(R.id.container, MainFragment.newInstance())
                    .commitNow()
        }
    }

}

Fragment

...
class MainFragment : Fragment() {

    companion object {
        fun newInstance() = MainFragment()
    }

    private lateinit var viewModel: MainViewModel

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View {
        return inflater.inflate(R.layout.main_fragment, container, false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
        // TODO: Use the ViewModel
    }

}

ViewModel

import android.arch.lifecycle.ViewModel

class MainViewModel : ViewModel() {
    // TODO: Implement the ViewModel
}

ページ上に進めていくと、ViewModelを実装したりArchitectureComponentのNavigationの香りを感じたりできます。

Guide to App Architecture

Guide to App Architecture  |  Android Developers

ちょっと長いので箇条書きで。

  • アプリのコンポーネントの中にアプリのデータや状態を保持してはいけない
    • 全てのアプリのコンポーネントは、個別に起動されたりいつでも捨てられる可能性があるため
  • コンポーネント間は依存せず独立しているべき
  • 重要な原理は2つ
    • 関心の分離をしよう
      • ActivityやFragmentからUI操作やOSとのやり取り以外のコードを排除する
    • UIを(できれば永続化した)モデルから操作しよう
      • OSによるリソース解放でアプリのプロセスがdestroyされたとしてもユーザーがデータを失わないため
      • ネットワークの状態がよくない時でもアプリを起動しておくため
      • Modelとはアプリ内のデータを扱うコンポーネント

UIを作る時は?

  • ViewModelを使おう
    • 表示するデータを保持しておくため
    • Viewや設定の変更(画面の向きの変更によるactivityの再生成など)とは関係なしにデータを扱える
  • LiveDataを使おう
    • アプリの他のコンポーネントから保持しているデータの変更を検知するため
    • データの変更をobserveしてUIを更新したいときには、propertyをLiveDataで包んだ後、observe()メソッド内で処理を行う

データを取得するときは?

  • REST APIと通信を行うライブラリを使おう
    • Serviceという形でメソッドを準備する
    • 今回はRetrofitを使う
  • ViewModelにデータの取得とオブジェクトへのマッピングの責務を追わせるのはやめよう
    • メンテナンス性向上のため
    • 関心の分離のため
  • Repositoryオブジェクトを作ろう
    • データの操作を担当する
    • データの取得先やデータ更新時に呼ぶAPIを知っている
    • data sourceを抽象化できる
    • (これはコンポーネントというより実装方針?)
  • コンポーネント間の依存性を管理しよう
    • RepositoryAPI通信用のServiceインスタンスが必要
    • 今後Repositoryを使う全クラスでServiceインスタンス生成を行うのは面倒
    • 方法は2つ
      • DIを使って他クラスから実行時にインスタンスを提供(注入)する
      • Service Locatorを使ってregistryを用意する
    • テスタビリティも向上する

ViewModelとRepositoryを接続するときは?

ViewModelからrepositoryのメソッド呼ぶだけです。次!

データをキャッシュしたいときは?

  • Fragmentに戻るたびにAPIをcallするのはやめよう
    • 貴重なネットワークの帯域を浪費することになる
    • ユーザーに通信完了まで待たせることになる
val cached = CacheObject.get(id)
if (cached != nil) {
    return cached
}

// 以降、APIからの取得処理

そっか、インメモリキャッシュってこんなシンプルだったんだと考え直しました。SQLiteやらrealmやらライブラリ先行で技術を追っていると大事なことを忘れてしまいますね。

データを永続化したいときは?

  • Roomを使おう
    • SQLiteのORマッパー
    • コンパイル時にSQLSchemeと合っているかバリデーションしてくれる
    • 使い方
      • local schemeとして、Entityとするクラスに@Entityアノテーションをつける
      • RoomDatabaseを拡張したdatabaseクラスを作成する
      • データ挿入用のDAOを生成する
      • databaseクラス内でDAOへの参照を作る

テストしたいときは?

  • UI & Interaction
    • この時だけEspressoなどを使ってUIの実装のテストをしよう
  • ViewModel
    • JUnitでテストをしよう
    • Repositoryをモックににする必要がある
  • Repository
    • JUnitでテストをしよう
    • ServiceとDAOをモックにする必要がある
    • 以下のことを確かめよう
      • 正しくServiceのメソッドをcallしているか
      • APIの結果を正しくDBに保存しているか
      • データがキャッシュされていて最新のとき、余計なAPIリクエストをしていないか
  • DAO
    • instrumentationテストを行う必要がある
    • JUnitSupportSQLiteOpenHelperを使えばUnitテストができるが、端末とローカルPCとでSQLiteのバージョンに違いがあると困る
  • Service
    • Mock化しよう
    • 外部に依存しないテストにするため、通信が走らないでテストをしよう
    • ライブラリはたくさんあるけど、okhttp/mockwebserverとかおすすめ
  • TestingArtifacts
    • ArchitectureComponentは、バックグラウンドのスレッドを操作するmavenアーティファクトを用意
      • InstantTaskExecutorRule: 全てのバックグラウンドの操作を行う
      • CountingTaskExecutorRule: instrumentationテスト内で、ArchitectureComponentのバックグラウンド処理を待ったりEspressoと接続したりする

TODO

  • 古くなったデータの更新処理
  • ネットワークの状態をユーザーに通知する

Note

  • データの整合性を保つには、data sourceを1つにしよう
    • 同じデータを返す複数のAPIのエンドポイントがあるとき、データの齟齬が発生する
    • 全てのデータ取得を内部のDBなどに統一すれば解決できる

大筋は以上です!!長かった!~後半JetpackというよりはAACの話だけどまあいっか~
実際はコードラボ風味になっているので、手を動かしながら進めていただきたく!

AACの紹介ではなくて、直面した問題ベースでの設計の考え方をベースに進めてくれたので、かなり分かりやすいし研修の教材としてもいい感じなのではないでしょうか。
まだAACで触わりたりないところがあるので、各コンポーネントの内部もしっかり読んでいきたいです。