今回3/2,3/3の2日間に渡ってプレゼンがあったので、3/2をDay1,3/3をDay2としています。
Day1-3というのはDay1の3番目のプレゼンという意味です。
##プレゼン内容の整理
Swift言語だけでなく、iOSアプリ的なもの、開発のプロセスに関わるものなど幅広くプレゼンされていました。トレンドなのは機械学習と、アプリ品質に関わるテスト関係の話のようです。サーバサイドSwiftなどサーバ・クライアントの言語を共通化しようという傾向もありました。
行動・組織論
Day1-5 Pixcels、プロセスと情熱
Day2-6 スタートアップのSwift
Day2-12 チームの生産性を改善するために決断疲れを最小化する
Day2-14 オープンソースコミュニティをスケールさせる
Day2-17 なぜ登るのか
機械学習
Day1-1 Swift開発者が知りたかったけど聞きにくい機械学習のすべて
Day1-12 楽しく便利なSwiftチャットボット
Day1-15 リアルタイム物体検出アプリでよりよいフィードバックを提供する
Day2-13 Client-Side Deep Learning
テスト
Day1-8 クックパッドアプリのテストを味わう
Day2-1 テスト可能なコードを書くということの2つの側面
Day2-11 モックオブジェクトをより便利にする
Day2-15 Swiftでのエラーハンドリングとエラー耐性についての教訓
Swift
Day1-2 誰もが知りたいSequenceとCollectionのすべて
Day1-3 SwiftのPointy Bits
Day1-7 Unsafe Swiftの安全性
サーバサイド
Day1-11 SwiftのWeb APIとアプリをともに構築する
Day2-3 様々な場面でSwiftを使う
Day2-10 サーバサイドSwiftの実例
UI/UX
Day1-16 UXエンジニアという働き方
Day2-9 Swiftで堅牢なカラーシステムを構築する
Day1-10 UIをSwiftyに書く
iOS
Day1-4 アプリを新次元に導く3D Touch
Day2-5 iOSにおけるDocument IndexingとApp Search
Day2-8 忙しい人のためのApp Transport Security
データ層
Day1-9 データレイヤを分離する
Day1-13 Realmを使ってコラボレーションアプリを作る
Reactive Programming
Day1-6 毎日リアクティブ
Day1-14 独自のツールを構築する
Android
Day1-2 Swift on Android
AppleWatch
Day2-16 👾 & ⌚️
VR
Day2-4 VRの革新と新たなユーザー体験
各テーマごとのまとめ(記載中)
テスト
Day1-8:クックパッドアプリのテストを味わう
テストを継続的に行い、それをリファクタリングにつなげている。
UIテストにAppiumを導入し、テスト工数を少なくしている。
画面遷移の8割にUIテストを導入している。
さらに、UIだけでなくイメージ差分やネットワークトラフィック(リクエストカウントなども)もチェックしている。
Appiumを利用する理由はシミュレータのシステム領域のクリア可能で再現性が高いため。
Day 2-1:テスト可能なコードを書くということの二つの側面
テストを行うには入力によって出力が一意に決まる関数(pure function)である必要があるが、
実際は入力や出力には作用するものがあり、条件によって出力が変わる。
そのためテストの際はこの作用を分離する必要がある。
分離方法としてグローバル変数群や動作や値が変化するプロトコルを一つのstructなどにまとめて入力する。
Day 2-11:モックオブジェクトをより便利にする
二つのオブジェクトのインタラクションテストを行うのであれば、プロトコルを利用する。
必要な変数と操作をプロトコルで定義し、プロトコルに準拠したモックを用意してテストする。
UnitTestではアサーションは一つしか定義できないので、
繰り返し呼ばれるのであれば呼び出された数、期待される値と実際の値などを表示する関数をアサーションで呼び出す。
細かくメッセージを出すのはリファクタの参考にするため。
Day 2-15:Swiftでのエラーハンドリングとエラー耐性についての教訓
エラー耐性を高めるときに考えるのは、正常系、Error型、予期せぬ不具合がある。
予期せぬ不具合から復帰して影響を最小限したい、入力に作用するグローバル変数・シングルトンを明示するようにする。
暗黙的なものとして状態がある。状態はある時間で実行されているコードの順番で定義される。
状態を明示するには、コメントや順序指定コンパイルなど。
コンパイラで実行順序はある程度指定されている。
データ移行など以前は存在しないものを利用する場合は型による明示的な依存関係にしていく
Optional型
・正しいか正しくない または、あるかない
・入力で使用すれば任意の値を意味する
・大抵の場合はこの型が正解
・情報量が少なく起こりがちなエラーに
Error型
・異常系で発生率が低く影響範囲が広いエラーで利用する
・スローして対処
・情報量が多く、コンテキスト依存な稀なエラーに
機械学習
Day1-1:Swift開発者が知りたかったけど聞きにくい機械学習のすべて
機械学習では、大量のデータと人間の考えを使って、ものを識別する関数を作る。
補助的なデータ、例えば身長を判定するのに、性別や年齢、体重、靴のサイズなどのパラメータを係数を使って積算していく、というのは線形回帰で求めること。
ニューラルネットワークでは多層のネットワークを用いて、ものを分類する関数を作っていく
様々な層ではぼやっとしているものを認識していく。
機械学習では、学習とその学習データを利用したアプリの段階があり、学習ではPythonとTensorFlowのような学習APIを使って学習データを作成し、アプリではSwiftを使って様々な入力と学習データを利用した認識結果を様々な結果として見せるアプリを作れる。
Day1-12;楽しく便利なSwiftチャットボット
日本語を学ぶために、個人的にカスタマイズしたLINEのようなbotを作った。
まず吹き出しを長押しすると Siriで話せるようにした。
次に入力した文章をGoogle翻訳に通して、翻訳された文章を話すようにした。
写真を送れば、写真内の文字を認識して描かれているものの画像を表示するようにした。
スタンプでbotに指示を出せるようにした。
UIはシンプルにすること。
画像をアップするとDropboxに保存され、URLを返答してくれる。
Day1-15;リアルタイム物体検出アプリでよりよいフィードバックを提供する
Wantedly Peopleというアプリでは、複数の名刺を認識できる。どのようにしているか?
まず名刺を検知する。そして複数の名刺であればトラッキングすることで常に各名刺を見分けているように見せる。検知するものについてAPIを使い分ける(顔だったらUIDetectionとか)
Day2-13;Client-Side Deep Learning
iOS10ではMetal Performance ShaderにCNN(Convolution Neural Network)の計算APIが用意された。GPUを使って計算するのでリアルタイムレベルで結果を出せる。TensorFlowなどで学習したデータを用いてリアルタイム認識可能。
カメラでリアルタイムで認識するアプリの画面を写して見せた。
行動・組織論
Day1-5 Pixcels、プロセスと情熱
結局のところ、ものづくりというのはこれを作りたいと思う人がいて、
それに共感した人が互いに自分のスキルを生かして、共同でものを作っていく流れになる。
そのような中で
- チームやプロジェクトの内外の人にモチベーションを持ってもらい、互いにハッピーになることが大事な課題
- 人脈も大事。自分ができないことは人の助けを借りる必要がある
- コンフォートゾーン(居心地のよい場所)を出て、刺激を受けることが重要
Day2-12 チームの生産性を改善するために決断疲れを最小化する by Derek Leeさん
意志決定をシンプルにして開発効率を上げていく。まずは会社の日常を振りかえって考えてみる。
- 朝食
- 全体朝礼:新しいメンバーやユーザの紹介など会社全体的な話題の整理
- プロジェクトの朝ミーティング:昨日何があって、今日何をするか。メンバー間の共通話題の整理(ここでソースコード管理の話:Xcodeでファイルを探す場合、まず機能によってグループ分けしてファイルを仕分けておくのが重要)
- ペアプログラミング:インデックスカード(開発要求や優先度を書いたもの)、ピンポン(実装とテスト実装を交代で行う)、Driver+Navigation(熟練者がナビしてドライバーがコードを書く)また、エンジニアやデザイナ、PMもペア(Cross Function Pair Programming)になり、また毎日ペアを変えてチーム全体でコードを共有。利点としては、みんな内容を知っているのですぐフィードバックが帰ってくること。
- ランチタイム:他の人のプレゼンや動画を見る
- ペアプログラミングに戻る
- チームディスカッション:計画など話し合う(ここではソースコード管理の話:アノテーションを使ってViewControllerを整理する。Xcodeのスニペットにテンプレートを作成、プロトコルの内容整理)
- 休憩:ペアで卓球してリフレッシュ
- クロスファンクションペアリング:エンジニアやデザインなどでペアを組む(ここではソースコード管理の話:フォント定義、カラー定義、スタイル定義、適用定義)
- レトロスペクティブ:チームメンバーだけで振り返り。KDI(Keep/Discuss/Improve)を集めてアクションアイテムを出して取り組むことで問題が大きくなる前に解決する
XPの中でKentBeckが言ってたこと
・真実や好き嫌いを話す勇気が、コミュニケーションと信頼を育てる。
常にチームの間でコミュニケーションと信頼を育てることでチーム内での意思決定の場面が少なくなっていく。その結果、チームのリソースを、より重要な意思決定に向けられる。
Day2-14 オープンソースコミュニティをスケールさせる by Felix Krauseさん
OSSの発展段階としては
- ソースコードを公開
- 開発者があなたのプロジェクトを利用するようになる(PullRequestが来る)
- その分野のソリューションとなっていく(Twitterで推奨されたり、カンファレンスで発表される)
- 大きなプロジェクトとなる
人間的な要因として、どうインパクトを与えるか、どうサポートするかを考える必要が出て来る
- モメンタムを維持する(初期のイノベーションができなくなる。機能変更や設定値を変えられなくなる)
- サポートの扱い(実装よりもユーザサポートの時間が長くなる)
- 機能要求の受付(GitHub issues、issuesをクローズできなければ別サイト用意)
- 不要な要求を断るときの理由をしっかりさせる
- 外部PRのレビュー、issueをレビューすることはコードを書くのと同じくらい重要
- 情報の不均衡 ある一つのissueはユーザにとっては重要なissue
どのようにOSSプロジェクトをスケールさせるか
- エラーメッセージの改善 文字色を赤にしてStackOverFLowへのリンクと再現するコマンドを表示
- ボットを使って自動化
- バグレポートの詳細化
- 似たようなissueが来るなら原因やドキュメントを改善する。異なる解決策や対策を見つけて書く
- issueに2ヶ月変更がないと、問題が完了しているかボットが聞いてきて、誰も応答しなければクローズされる。さらに1ヶ月後にロックする
- 大半のissueはCIでテストパスしていることをチェックしているが、テストだけでどのようにコードが変わったかまではわからない。Ortaを使うことでファイル変更や修正ライン数の通知やテストを要求することが可能。
- 方向性の舵取り Vision.comを使ってビジョンを共有する。
- DSL(Domain Specific Language) コードが複雑になる程貢献できる人は少くなる。できるだけフレンドリーにissueやPRに感謝を伝える。コードを拡張しやすいようにDSLで記述したりプラグインにすることも考える。
Day2-17 なぜ登るのか by Tachibana Kaoruさん
ボルダリングの紹介
- 難易度が異なるコースが混じっているので、レベルが異なっても同じ壁で楽しめる。
- 登り方に人それぞれの工夫ができる。柔軟性、筋力、ジャンプ力をそれぞれ活かせる。
- 一人でもチームでも楽しめる
Swiftにも言える。制限や条件は人それぞれで、それに合わせてソリューションを考える必要がある。
一人で仕事しても、時にはStackOverFlowやあるいはOSのバグなどで苦労したりすることでみんなと苦労とソリューションを共有できる。
UI/UX
Day1-16 UXエンジニアという働き方 by akatsuki174さん
■ユーザテストの必要性
エンジニアやサービス企画担当とは異なる年齢層・リテラシーという想像できない層の人にプロトタイプを利用してもらい、様々な知見を得る。
■デザイン思考
デザイン思考(創造性、ユーザ共感などに重きをおく方法論)を活用してUXにてイノベーションを起こす。
Day2-9 Swiftで堅牢なカラーシステムを構築するカラーシステムを構築する理由 by Laura Ragoneさん
- 決まった呼び方で簡単に色を取り出せる
- アプリ全体で一貫性のある色づかいを決めることができる
- 最小限の労力でデザイン設計を回せる
- Appleのヒューマンユーザインタフェースはよく変更されるので、それについていくため。
- tvOS10でDarkModeの導入あり
- OLEDスクリーンが来たときのため
- AppStoreのレビュアーからのプレッシャー
■デザイン設計:InterfaceBuilder
利点:
- とてもパワフルなツールとして使われて来ている
- ユーティリティパネルより簡単にカラーピッカーにアクセスできる
- .crlファイルでチーム横断でカスタムパレットを共有できる
欠点:
一度セットすると色の共通的な参照はできなくなる
- アプリ全体に及ぶ色の設定変更についてはたくさんのファイルを修正する必要あり
- マルチテーマのサポートができていない
■デザイン設計:プログラマティック
利点:
UIColorを拡張して、各UIエレメントから色定義にアクセスできる。
- すべてのビューのカラーアップデートを一度にできる
- コード差分として管理できる
- そのときに合わせてカラーを修正しやすい
UIColorを拡張してカラーをstructで定義する
- Zeplinのようなカラーをエクスポートできるツールを使うと、このプロセスはかんたんにできる。(透明度は明示的な定義がない場合は1.0を設定)
- 色規定を継承するのであればclass varやclass funcで定義
- テキスト・フィードバック・バックグランド・ボタンでそれそれの状態で色を規定
- コントラストを十分とること
■テーマの基本
- DynamicTypeの実装のように、アプリ側で状態を決めて反映するようにしてみる
- コントローラにて色更新
- NotificationCenterの通知にて、各Viewに更新通知
ColorUpdatableプロトコル
- テーマとして共有している色を更新可能とする
- アプリケーション全体を通して更新を反映
ColorChangeObservingプロトコル
- カラー更新用の通知を定義
- テーマカラーの追加・削除・変更通知を定義
- 通知はnotificationを使い、userInfoにthemeキーを設ける
使い方としては、
- 各UIエレメント(UITableView/UICollectionViewなど)はColorChangeObservingに準拠
- UIViewControllerはColorUpdatebleに準拠
- UIColor拡張で各テーマの色を定義しておく
- UIViewControllerのColorUpdateにて各Viewの色を変更、変更したら通知にて変更反映する
■デザインで他に考慮すべきこと
色覚異常は世界の全人口の4.5%程度。iOS10ではアクセシビリティの機能でカラーフィルタが導入され、色の見え方をシミュレートできる。
- モノクロームなテーマでは単色で輪郭を出すように考える
- テキストとバックグランドのコントラスト比率を計算してみる
- UXフィードバックを与えるときに色よりもビジュアルなインジケータを用いる
Day1-10 UIをSwiftyに書く by Sommer Panageさん
Swiftを使ってUIのコードを簡潔に書く
■シュレディンガーの結果
データ取得というイベントを考える。結果は大きく分けると成功と失敗に分けられる。
そこで結果を扱うResultというenumを考え、成功であれば、失敗であればErrorを返すというモデリングを行う。
まとめ
・成功失敗モデルはサーバとのやりとりをより正確に扱える
■レイアウトエンジンについて
昔はlayoutSubviewsで調整していたが、色々なサイズに対応するのが大変。
StoryboardとXibについてどうなのか?
チーム開発がやりにくい。なぜなら
- XMLなのでdiffやマージが難しい
- カラーやフォントが各部で埋め込まれている
- 文字列のIDでViewを操作するので型付があまり意味をなさない
- コンパイラはoutletの整合性はチェックしていないのでViewとのコネクションが壊れやすい
iOS9からのAutoLayoutはどうか
- コードを見てもレイアウトがよくわからない
- Cartographyを利用すると簡潔にかける
まとめ
・Cartography frameworkはSwiftのオペレータのオーバロードを利用していて、プログラマティクなAutoLayoutをスイスイ書ける。
■状態管理
Swiftyなlockと3つのView状態
Boolで状態管理を考える
・isLoading/isErrorで場合分け→パターン4つ+データの存在有無の確認で大変
・ここでView状態をenumで管理してみる。loadning/loaded/error。
・さらに各Stateについて取りうる画面パターンをhiddenで管理し、またデータ更新を行う。
・最後にデータ取得を成功と失敗で分け、成功ではstate=loaded、失敗はstate=errorで
まとめ
・enumでView状態をモデルし、関連する値を設定することで
- VCが簡単に書ける
- 曖昧な状態を避ける
- ロジックに集中できる
□ピーターラビットと繰り返されるコード
先のコードはStateごとに同じようなコードを書いている。
プロトコルで無駄を省こう
- メソッドとプロパティのインタフェースを共有できる
- 特定のタスクを紐づけられる
- 型埋め込みプロトコルであれば依存しない
まずenumでView状態を定義
DataLoadingプロトコルを作成し、update()を定義。
updateはView状態により、Viewのhiddenを制御する。
このDataLoadningプロトコルに準拠するには、
- errorViewを用意していること
- loadingViewを用意していること
- 都合の良いようにソートされたデータを含む状態変数を用意すること
- 必要に応じてupdate()を呼ぶ
以上のようにして繰り返されるコードについてパラメータと実装を分離して、それぞれデフォルトプロトコルで指定する。
まとめ
機能を細かく分けて、オブジェクトでなくプロトコルで共有することにより、
- コード重複を避けられる
- 一つの場所にロジックを固められる
結論
・Result: Success/errorというわかりやすい選択肢を利用
・Cartography: オペレータをオーバロードしてコードをもっと読みやすくする
・ViewState enum: 曖昧なView状態を持たないようにする
・プロトコル:型依存しないように値定義や各部処理の振る舞いを共有できる