LINE DEVELOPER DAY 2016 午後 整理されていないメモ
こちらの午後のメモを整理しよう整理しようと思い、数日経ってしまいました。
もう整理することを諦めて貼り付けてしまいます。
網羅性はないし、タイポなたくさんあって、自分にしか理解できない内容になってしまっています。
それではどうぞ。
LINEが乗り越えてきた困難な問題
2016/3/11に発生したサービスダウンについて
- 1時間40分ダウン
- デマで炎上する。
- 今でもテレビ局の取材がある
発生の経緯
- LINEのきせかえ機能の更新
- クライアントサイドのきせかえ画像の更新
- サーバ負荷増大
データ更新の仕組み
- UEN: ユーザにリクエストしてもらうための通知のサービス
- サーバからクライアントに通知
- 通知を受け取るとクライアントからサーバにリクエスト
- 一斉に通知が飛ばないように全ユーザ通知は時間を分散している
- 今は3時間程
- 通常の更新は認証不要
- ただし、全データ更新の場合は認証必要
- 全データ更新は更新データが2000を超える場合に、通信のオーバーヘッドを減らすための仕組み
- 全データ更新は長期間LINEを使って
データ更新の仕組み
- データ構造の変更が必要
- 着せ替えの数がテストのときと本番のときで違った
- 植えたし
- 2000を超えると全データ更新になる仕組みがあった
- リクエストのオーバーヘッドを彫らすため全データ更新
- 全データ更新の場合は認証が必要
- 全データ更新通知を全ユーザに通知
- 通常は1日10名程度
- 全データ更新は時間分散しない
- 全データは久しぶりに起動したユーザ扱いなので認証必要
- 認証サービスに障害が発生したのでデータ更新が以外のサービスにも影響が出た
復旧対応
- 認証サーバの不可を減らす
- 全データ更新リクエストが飛ばないようにする
- 認証種類がある
- リクエスト制限
- 認証の仕組みを回収
対応
- 全データ更新にも時間分散導入
- UAMの登録上限を儲ける
- 認証にサーキットブレーカーの仕組み導入
- だいたい全箇所(Micoroservices)に再発防止先を入れた
- 総務省への報告義務(音声通話があるため)
- 総務省のHPに議事録報告書がある
- Microservicesが不完全であった
- それぞれのサービスに自衛の仕組みが必要
- リクエストバーストを検知
- 全データ更新のリクエストだと判明
- なぜ全データ更新なのか。着せ替えの更新をやってるらしい。
- で判明。
LINE Login - LINE Platform
LINE Loginとは
- LINE ApplicationからLINE Service(LINE PayやLINE game)を利用する際にLINE Loginが使われる
- LINEユーザの会員情報を利用したログイン
- Web/iOS/Androidで実装可能
- iOS/AndroidにはSDKを提供
- Autoログイン
- LINEアプリからの動線のみAutoログイン
- Web:OAush2.0
- Native SDK: ApptoApp
- チャネルの作成が必要
- 使っている会社
- niconico
- ikyu.com
- Demae-can
- Rilunabi
LINE Loginロードマップ
Security x LINE Platform
LINE Architecture
- ApplicationはLEGYにリクエスト
- LEGYはルーティングと暗号化が主な責務
- TLSv1.2
- ネイティブアプリだとハンドシェイクなどで通信が必要
- TLSv1.3はハンドシェイクの簡略化がされる予定
Messaging E2EE
- iOSとAndroidのチャットのみ
- ユーザの端末でしか復号化できない技術
- Letter Saling Evalution
- Group Chat 対応
- Bの公開鍵、Aの秘密鍵で暗号化してサーバに投げる
- BはサーバにAの公開鍵のリクエスト
- BはAの公開鍵と自分の秘密鍵で受け取ったメッセージを復号化
- グループチャットも仕組みは違うが同じような仕組み
- サーバも平文を見れないようにしている
- VoIP(電話)もE2EE
- ローカルデータも安全に。
- 削除したら本当に削除する。フラグ立てるだけじゃない
Risk Assessment
Reverse Engineering
- Security Measures
- 改ざんされてもサーバでブロックできるように
- 最初の障壁を高くすることは大切
- ゲームのチート
- スピードハック、時間のハック
- 時間取得をフックして偽装するなど
- ネットワーク
- HTTPSでも証明書を入れると通信を覗ける
- 証明書を端末でチェック SSL Piling
- 短波正
- サーバサイドのチェック
- マシンランニングで自動化したいが攻撃側もマシンランニングしているので考えて実装が必要
- ご検知は0.01%以下でないと使えない
- he
Anti-Spam/Fame Abusing
LINE LIVE を支えるアーキテクチャ
- 2014年に追加したLINE LIVE CASTの評判が良かったのでLINE LIVEをうあることに
- 視聴者数をリアルタイム集計している
- HLS
- チャット機能はWebSocket
New stream processing platform with Apache Flink
- DataLabの体制
- Planner
- Developer
- Analist
LINE LIVEの視聴者数の話
- 10秒毎に更新しているリアルタイム集計している
- 求められる機能
- リアルタイム集計
- ユニークユーザ集計
- 耐障害性
- はじめは norikura を採用した
- LINE LIVEの仕様追加(だれでも配信)でスケーラビリティも求められるようになった
- そこで Apache Flink を採用
- ユニークユーザ集計で消費されるメモリ問題以外は Apache Flink で解決できた。
- メモリ問題はHyperLogLogで採用
- HyperLogLogはユニークユーザを推定する
- 誤差1%以内に収まった
- 使用メモリが180Gから80Mになった TODO: 後で数値確認
A True Agile Team - Global LINE News
- 海外に需要があるかわからなかった
- 6wで完了
- 経験無し
- チームも若く、シニアエンジニアがリモートで参加
- 他国にまたがりコミュニケーションが大変
- Agile/Scrum
- 様々な国のチームメンバー
- Scrumは手法でしか無い。CoreValueが大事。
- チームスピリット
- 信頼とコミットメント
- プランナーと開発者の信頼関係
- プランナーは正しい
- コミットメントは守る
- 開発者だけがスケジュールをコミットできる
- マネージャ(Scrum master)はアドバイスする立場。コミットしない。
- Planner -> Why -> What -> Developer -> How -> When -> Plannerのループ
- プランナーはなぜ開発にそれだけ時間がかかるか納得する節用がアアル
- セルフマネジメント
- 信頼とコミットメント
LINEのエンジニアが働く環境と文化
- Github Enterpriceを利用
- リポジトリ数 2016.9: 10660
- エンジニアはJapan, Korea, China, Taiwan, Thailand, Indonesia
- 海外だけのサービスも有る
- 各国独自のカルチャを理解して開発する必要がある
- ローカライズだけではなく、カルチャライズしている
- MicroServicesを採用していることもある1つのプロダクトが1つのオフィスで収まることはほとんどない
- 多言語のコミュニケーションは英語がマストではなく社内コミュニケーションでも通訳を通すこともある
- LINEの翻訳BOTを使ってコミュニケーションもしてる
- 翻訳BOTは社内の需要から出てきたもの
- なんだかんだFaceToFaceが一番良い
- 来年は新宿 MiRAINAに移転予定
開発文化
Take Ownership
- 自分ごととして考える
Take Risk
- 大前提として物事は計画通りに行くとは限らない
- だからといっていつも同じ事をやっていてはいけない
- リスクをどうとるか
Be Open
- コードはエンジニア全員見れる
基本的なマインド
- Trust $ Respect -> Self-directed Work -> Positive Peer Pressure -> Trust & Respcetのループが大事
- Trust $ Respect 信頼と尊重
- Self-directed Work
- PositivePeer Pressure
- 仲良しグループではなくいい意味でのプレッシャー
- 人事評価が大事
- マネージャはコードを読んでいないのではないか
- 同僚からの評価が一番大事
- マネージャは良いサイクルが回っているかサポートする
- 今までLINEは秘密的だった気がする
LINE DEVELOPER DAY 2016 午前 参加レポート
Opening & Introduction
ビジョン:Closing the Distance(距離を縮める)
- コンテンツプラットフォームをライフプラットフォームを連携
- コンテンツプラットフォーム
- ゲーム, ニュースなど
- ライフプラットフォーム
- LINE@, LINE MOBILEなど
- 他社とも連携も必要。そのためにOPENに。
- 長期間BOTを運用してきた。ナレッジが蓄積してきた。
- 他のアプリケーションをチャットに入れられるようにするChat Extention
Tech Focus
- Technology for a Large-Scale Platform
- Augmented/Mixed Reality in Daily Life
- Data Processing & Machine Learning
Keynote : New world by the LINE BOT
LINE Notify
- LINE Notifyにリクエストを送ると、LINE Notifyアカウントでユーザに通知
- OAuth2 / HTTPSで利用可能。
- OAuth2 を使わなくても Personal Access Tokenも使える。
- 管理画面でToken作成
- ヘッダーにToken付与してHTTPリクエスト
- IFTTT/Github/mackerelとも連携
LINE Messaging API
- LINE Botは大企業向け、LINE@は中小企業向けで運営してきた。
- 今までは公式パートナーのみAPI型のBOTを利用可能だった。
- 本日よりAPIを公開。
- 公開に伴い一部仕様変更。マジックナンバーをなくしたり。
- オープンソースのSDKを用意。
- 3機能追加公開
- New Message TypeとReply Push APIはLINE Messaging APIのみで提供
- BOT API Trialは廃止。代わりにDeveloper Trialを開始する。
Rich Menu
- BOTとのコミュニケーションがテキストだけは不十分ではないか。
- ユーザは何を送ってよいかわからない。
- この問題を解決するRichMenu
- BOTを開くと画像などを載せたサジェスト(Rich Menu)を表示
LINE Web Login from the LINE App
Iot Beacon
- LINEのIotの取り組みとしてBeacon
- Beaconを店舗に設置し店舗に来たユーザにクーポンを発行
LINE BOT AWARDS
- 優勝賞金最大1000万円
- 応募受付11月初旬
ユーザはWebのブックマークよりもLINE友達登録の方が気軽にしてくれるでしょ?だからLINE BOT。
歌舞伎座.tech#11「Swiftプログラミング勉強会」を視聴しました。
上記勉強会ををニコ生で視聴させて頂いたので、メモを残しておきます。
クリーンアーキテクチャしたい、クリーンアーキテクチャしたくない?
メモ
- クリーンアーキテクチャ、メリットデメリットあるけど良かったよという話。
合わせて確認したいページ
初めて Phantom Type と遭遇して、闇雲に闘いを挑んでみた話
メモ
- Phantom Typeの紹介。
合わせて確認したいページ
Swift 3.0 と値型
メモ
- Swift3.0 で値型が増えた。NSが取れたものがいくつかある。
- 迷ったら値型使おう。
- パフォーマンスも悪くない。
Good Design Pattern of Networking Programming in Swift
メモ
- Swift3.0 の機能を使ったネットワークライブラリの話。
君の参照は。
メモ
- 循環参照になるパターン、ならないパターンの話。
合わせて確認したいページ
ATSと通信ライブラリの話
メモ
- ATSとそれに対応した通信ライブラリの話。
- 理由を述べたからといってAppleがHTTP通信しているアプリ審査通してくれるはずがない(かもしれない)。
- APIでHTTPアクセスしたければSocket使えばいいじゃんということで、Socket使って簡易に書ける通信ライブラリを作ったそうです。
Minimal Cake Pattern in Swift
www.slideshare.net
メモ
- ドワンゴがDIで採用しているMinimal Cake PatternのSwift実装について紹介。
合わせて確認したいページ
Validation Decoration
- Validation処理をDecoratorパターンを使って実装した話。
The introduction to RxSwift you've been missing
- Rxの話。
「ハッカソンに使うSwift」か「Swift 3.0のGCD」
- ハッカソン参加しよう。こういう点を心がけよう。という話。
その他まとめページ
git の Discard all changes を復元する(取り消す)方法
最近はGitKrakenを使ってgit操作をしています。
GitKrakenにはcommit前の変更を全て取り消す Discard all changes という機能があります。
内部的にはgit checkout
を実行しているのでしょうか。
詳しく調べていませんが、GitKraken以外のGUIアプリでも実装されてるものは多いと思います。
で、たまに(よく)単一ファイルを Discard change しようとした時に、誤って Discard all changes してしまい、全ての変更を取り消してしまうことがあります。
その時の復元方法について紹介します。
1. git reflog でログ確認
$ git reflog 104352f HEAD@{0}: discard: [8d1024be820c042cef4fe17432dc438d59189526] 104352f HEAD@{1}: commit: fix bug. c263df1 HEAD@{2}: Fast forward branch feature/menu to branch develop
discard のログが残っていることを確認します。
2. git reset で復元
$ git reset --hard 8d1024be820c042cef4fe17432dc438d59189526 HEAD is now at 8d1024b saved UNDO information for reset changes and discarded files
これで復元されます。
git reset --hard
の右側の値はgit reflog
で確認した discard の右側の値です。
discard した内容のcommitが出来上がるので必要に応じてcommit logの修正します。
注意点1. git reset --hard HEAD@{0} では復元されない
上記 reglog の状態でgit reset --hard HEAD@{0}
を実行すると、HEAD@{1}の位置にHEADが移動するだけで discard した内容は復元されません。
注意点2. git reset --soft 8d1024 でも commit は作られる
git reset --soft
でもやってみましたが、commitが作られました。
softの場合はcommitに加えて、そのcommitを取り消す変更がある状態になりました。
Androidオールスターズ2に参加しました。
Androidオールスターズ2に参加したので、簡単なレポートとメモを残しておきます。
AndroidのCIを始めよう
レポート
- AndroidのIDEがAndroid Studioになり、Gradleでビルドしている。
- Gradleではビルドスクリプトが用意されている。
- CIにはビルドスクリプトが必要だがAndroidでは既に用意されている。
まとめ
Flux de Relax
発表資料と発表で使ったコード
レポート
なぜFluxか
- Viewの状態管理が難しい
- Fragment問題など
- アプリがスケールした時の状態管理がつらい
Fluxの各役割
- Dispatcher
- ActionとStoreを結ぶ
- シングルトンで作る
- EventBusを使っている
- DispatcherのメンバにEventBusを持っている
- Mockしやすいように作る
- Action
- 外部リソースからデータを取得し揃ったらDispatcherに渡す
- Rxのメリット
- 複数リソースの合成
- リクエストのキャンセル
- Store
- Storeの更新はStore内部で行う
- Storeの状態が変更したらViewへ通知
- DispatherへCallbackを登録する
- ObservableXXからRxへの移行
- ReadOnlyを制御出来ない。Rxなら出来る
- ただしListは難しい
- ObservableListならいい感じにやってくれる
- View
- StoreのStateを合成するケースがあるので、ObservableXXよりもRxが良い
- Flux
まとめ
- AndroidでFluxの発表でした。
- コードも公開されていますので、発表資料と合わせて読むと理解が進むと思います。
aptとKotlinでコードを(なるべく)書かないAndroid開発
発表資料
レポート
- aptについて Androidでaptのライブラリを作るときの高速道路 - Qiita で詳細に紹介されているがその足りない部分について紹介。
まとめ
- 前半apt、後半Kotlinの発表でした。
- aptはコードを自動生成する仕組みです。
- いずれも なるべくコードを書かない という目的のツールとして紹介されていました。
はじめよう Localization - ツール/tips/運用ノウハウなど
発表資料
レポート
- Localization(地域化)とInternationalization(国際化)がある。
- Internationalizationにエンジニア要素がある。
- Localizationにエンジニア要素は少ない。
- Internationalizationに必要なこと
- 多言語リソースの用意
- Formatterを使った日付や数字
- 柔軟性の高いレイアウトの設計
- Internationalizationに必要なことの要素
- Strings
- 画像
- マルチメディア、音声、動画
- レイアウト
- Analyze > Run Inspection by Name でハードコードされているstringを見つけることが出来る
- システムの言語設定を English XA にしてアプリを起動してまともに表示されているとそれがハードコードされているとわかる。
- EnglishXAは特殊な文字列リソースを使い、30%程の文字を追加する特殊な言語
- strings.xml にプレースホルダーを設定できる。
- <string name="buyitems">Buy %1$d %2$s</string>
- 上記のように値を外から設定できる string を定義できる。
- もっと使いやすいプレースホルダー Pharaseというライブラリがある。
- 複数形は plurals を使う
- 日付・時刻
- DateFormat
- API18からは getBestDateTimePatternという便利なメソッドがある
- DateUtilsもある
- getDateとgetDateRnage
- 通過、数値
- NumberFormat
- 電話番号
- PhoneNumberUtils
- API21以前は、英語日本語以外はあてにならない
- 画像
- 文字つきの画像は避ける
- 柔軟性の高いレイアウト
- 英語の30%増しくらいで考える。日本語は文字数少ない。
翻訳管理
- 翻訳に必要なコンテキスト(どういうケースで使われるStringなのか)をXMLのコメントで付与する。
- 翻訳不要なStringをマーク。Androidが用意している。
- 翻訳管理サービス
- 翻訳作業も自動化。
- エンジニアがStringリソースを追加する。
- CIが翻訳管理サービスに投げる。
- アプリに翻訳に協力するボタン用意すると結構協力してくれる。
まとめ
- Internationalization(Localization)に関する発表でした。
- AndroidではInternationalizationのためのフレームワークがたくさん用意されており、知らないこともたくさんあったので非常に勉強になりました。
設計のお話 MVPとDDDで
発表資料
レポート
- 設計:イメージしたものを実現するための見通しを立てる行為
- プログラミングの設計:上の定義に加え、システムには完了が変更への強さも求められる
- VとCの責務を持った、Activity/FragmentからイベントをPresenterとして外出しするためにMVP
- スレッド管理はアプリケーションレイア
まとめ
- AndroidでMVP/DDDの発表でした。
- DDDからはドメインモデルとレイヤードアーキテクチャを採用していました。
- MVPですが、AndroidのDatabindingが便利だということで、ViewModelを用意し、Viewにバインドしていました。
- Android + MVP + DDD の実践的な設計が紹介されていたと思います。
Android初心者を脱するための20のチップス
発表資料
レポート
Javaのチップス
- アクセス修飾子を適切に
- static修飾子
- staticメソッドにしておけばテストコードを書きやすい
- final修飾子
- 変数、クラス、メソッド
- コメント
- アノテーション
- Non-primitive は @Nullable を指定する
- ジェネリクス
Androidのチップス
- 適切なViewを使う
- Viewの階層は浅く
- FrameLayout
- テーブルっぽいレイアウト
- NG: LinearLayout
- OK: GridLayout
- 関係ないView属性を書かない
- ViewもDRY
- <include>
- <merge>
- toolsを使う
- tools:layout_heightで指定してpreviewで確認できる
- tools:contesxtでActivityを指定しThemeを適用する
- tools:layoutでFragmentのレイアウトを指定する
- lintを確認
- proguardをかける
- 依存ライブラリは外部モジュールで
- ディスプレイサイズはResourcesから取得
- TextUtilsを使う
- タスクは積み直せる
- Activityのタスク
- static 生成メソッド
- フォーマットかけよう
- Alt + Command + l
- フォーマット修正diffがあるとレビューつらい
まとめ
- 今日から使えるチップスの発表でした。
全体を通して
Androidに関係する様々なジャンルの話を聞けて、非常に勉強になりました。
Kotlin sealed class パターンマッチの挙動
sealed class を when でパターンマッチした際に、想定外の挙動をしていたのでいろいろ検証してみました。
網羅チェック
網羅チェックが動きそうで動かなかったケース
- ビルドエラーになりません。
sealed class Event { class Insert: Event() class Update: Event() class Delete: Event() } fun hoge(event: Event) { when(event) { is Event.Insert -> { print("Insert") } is Event.Update -> { print("Update") } // is Event.Delete -> { print("Delete") } } }
網羅チェックが動くパターン1
- ビルドエラーになります。
sealed class Event { class Insert: Event() class Update: Event() class Delete: Event() } fun hoge(event: Event) { val x = when(event) { is Event.Insert -> { print("Insert") } is Event.Update -> { print("Update") } // is Event.Delete -> { print("Delete") } } }
網羅チェックが動くパターン2
- ビルドエラーになります。
sealed class Event { class Insert: Event() class Update: Event() class Delete: Event() } fun hoge(event: Event) { when(event) { is Event.Insert -> { print("Insert") } is Event.Update -> { print("Update") } // is Event.Delete -> { print("Delete") } }.let { } }
参考にしたページ
ネストしたクラス
下記のようなページも有ったので検証してみました。
- ビルドエラーになります。
sealed class Event { class Insert: Event() { class Single: Event() class Multiple: Event() } class Update: Event() class Delete: Event() } fun hoge(event: Event) { when(event) { is Event.Insert -> { print("Insert") } is Event.Insert.Multiple -> { print("Multiple Insert") } // is Event.Insert.Single -> { print("Single Insert") } is Event.Update -> { print("Update") } is Event.Delete -> { print("Delete") } }.let { } }
複雑なクラス継承
継承した時の挙動が気になったので検証してみました。
sealed class の inner class を外で継承
- ForceDeleteをwhenの条件に加えなくてもビルドエラーになりません。
- ForceDelete の場合 Delete にマッチします。
sealed class Event { class Insert: Event() class Update: Event() open class Delete: Event() // 継承できるように open を指定する。 } class ForceDelete: Event.Delete() fun hoge(event: Event) { when(event) { is Event.Insert -> { print("Insert") } is Event.Update -> { print("Update") } is Event.Delete -> { print("Delete") } }.let { } } hoge(ForceDelete()) // Delete
sealed class の inner class を sealed class 内で継承
- Deleteをwhenの条件に加えなくてもビルドエラーになりません。
- hoge(ForceDelete()) では Delete が実行されます。
- 1つ前の外で継承したケースと同じ挙動です。
sealed class Event { class Insert: Event() class Update: Event() open class Delete: Event() class ForceDelete: Event.Delete() } fun hoge(event: Event) { when(event) { is Event.Insert -> { print("Insert") } is Event.Update -> { print("Update") } is Event.Delete -> { print("Delete") } }.let { } } hoge(ForceDelete()) // Delete
sealed class の inner class を継承した場合の when の評価を検証
- 次のコードでは Delete は Update にマッチします。
sealed class Event { class Insert: Event() open class Update: Event() class Delete: Event.Update() } fun hoge(event: Event) { when(event) { is Event.Insert -> { print("Insert") } is Event.Update -> { print("Update") } is Event.Delete -> { print("Delete") } }.let { } } hoge(Event.Delete()) // Update
- 次のコードでは Delete は Delete にマッチします。
sealed class Event { class Insert: Event() open class Update: Event() class Delete: Event.Update() } fun hoge(event: Event) { when(event) { is Event.Insert -> { print("Insert") } is Event.Delete -> { print("Delete") } is Event.Update -> { print("Update") } }.let { } } hoge(Event.Delete()) // Delete
この通り、When-isの順番により処理が変わってしまうため、 sealed class の inner class を open にして継承することは避けるべきです。
最後に
いくつか微妙だなと感じる仕様があったので以下の仕様変更があればなと思います。
- whenで評価した値を使わなくてもsealed classの網羅チェックが働くようにする。
- sealed class の inner class は open にできないようにする。
こういうのどこでリクエストすればいいのでしょうか。
Kotlin + DataBinding + RecyclerView のサンプル。
標題のサンプルが見つからなかったので作りました。 github.com
このコードを元に、第3回Kotlin勉強会 @ Sansan - connpassでLTしてきたのですが、
#Kotlin_Sansan enumならviewTypeはordinal で良いんじゃないかなと https://t.co/GXweUTSK7s
— Satoru Fujiwara (@satorufujiwara) 2016年7月1日
このようなフィードバックを頂きましたので、合わせて参考にして頂ければと思います。
またLTで使った資料はこちらです。 speakerdeck.com