Swiftの動向とアツさを追う try! Swift参加レポート

try! Swift 2日目 参加レポート

Swiftの世界的カンファレンス、try! Swiftが3月2日~4日の3日間にわたり、渋谷のサイバーエージェントのオフィスにて開催されました。

本イベントの興味深いセッションをいくつか、日ごとにレポートしています。1日目のレポートに続き、2日目の模様をレポートします。

Ayaka Nonakaさん「実践的 "Boundaries"」

venmoでiOSのリードをしているAyaka Nonakaさん@ayanogagonは、Boundariesで得た知見を元に実践的なSwiftのコードに落としこむテクニックを発表しました。

画像

Gary BernhardtさんのBOUNDARIESという講演を聞いた時に「Functional Core」「Imperative Shell」をどう活用できるか悩んでいたそうです。悩んだ結果、最初は理論を感覚で捉えて、実装時に「使えるのでは?」と思った時に使えば良いと考えるようになったそうです。

画像

IMMUTABLE CORE NETWORK-Y SHELL

Functional Coreを不変なコア、Imperative Shellをネットワーク環境による表面として例示しました。

最初に与えられた値によって表示内容が確定する画面の場合はFunctional Coreとして振る舞うことができます。上記とはまた別でネットワークを用いて後から詳細な情報を取得するような流動的な画面はImperative Shellとして振る舞うことができるとのことでした。

画像

境界(Boundary)を見つける

実装設計をする上で、コードのどの部分が不変なもので「堅実なパターン」に適しているか把握し、そして同じようにどの部分がネットワークコードのように「流動的なパターン」に適しているかを把握するのが大切だと言います。⁠堅実なパターン」「流動的なパターン」のバランスをとり、境界(Boundary)を見つけることで、安全で将来性のあるコードが書けると述べていました。

画像

Adam Bellさん「プロトタイピングの魔法」

facebookから提供されているアニメーションエンジンpopのメンテナンスをしているAdam Bellさん@b3llは、アニメーションのプロトタイピングについてセッションを行いました。

画像

振り返り

iOS 7以前のUIがスキューモーフィズムだった頃のアニメーションとiOS 7以降のフラットでシンプルなUIのアニメーションを振り返りました。スキューモーフィズムが実世界の物に似せるようなアニメーションをすることに対し、iOS 7以降のアニメーションはシンプルなものになっていました。ただアニメーションが不要になったというわけではなく、アプリケーション自体を楽しくさせるためにアニメーションは重要な要素であると指摘しました。アニメーションは何が起きるのかを見せるものであって、必ず目的と意図が必要とのことです。

アニメーションを入れない選択肢をしない

また、アプリケーションの動作が遅くなるからといってアニメーションを入れないのではなく、適切な方法で実装すべきとのことでした。CoreAnimationはフレームを落とさないように設計されており、CARenderServerで高い優先度で処理されるため、最適化をしていないコードで使わない限り遅くなることは無いと説明しました。

Xcodeのplaygroundでプロトタイピング

アニメーション作成のプロトタイピングツールとしてXcodeのPlaygroundを使った方法を実践していきました。次期バージョンよりジェスチャも使えるようになるため、タップした際のアニメーションも結果が見やすくなっていました。

画像

XcodeをSwiftで簡単にプロトタイピングができるようになったので、自分の限界を引き上げるようなコードに挑戦してくださいと述べていました。

Matthew Gillinghamさん「プロトコルエクステンション:歴史について」

Tokyo iOS Meetupの主催をしているMatthew Gillinghamさん@gillygizeは、プロトコルエクステンションに至るまでの言語の歴史を紹介しました。

画像

継承と抽象の問題

まずはオブジェクト指向のなかで、継承という概念が生まれ、やがて抽象クラスの概念ができました。ただし、シングルインヘリタンスはクロスカッティング問題が存在します。構造が違うサブクラスが2つ以上存在する場合、片方のサブクラスからサブクラスを作成した場合、もう片方のサブクラスの実装コードの共有ができなくなってしまいます。

また、同じインターフェースを持つ親を複数継承したときインターフェースが衝突してしまう問題があります。この問題はダイヤモンド継承問題と言われています。

画像

プロトコルの誕生

そこでメソッドの名前で具体的な実装情報は持っていないprotocolという概念が生まれました。protocolはメソッド名のみで実装コードを持たないため、実装コード同士が衝突してしまうダイヤモンド継承問題を解決しました。

プロトコルエクステンションの誕生

protocol extensionが生まれ、継承関係のないクラス同士でもクリーンな形で実装コードの共有ができるようになりました。

ただしMatthewさんは、protocol extensionはパワフルですが、protocol extension同士が衝突した際の問題など、別の複雑さが導入されていることに注意しました。

Himi Satoさん「Building Women Who Code in Tokyo」

「Women Who Code Tokyo」のCo-founderをされているHimi Satoさん@himisantaは、コミュニティの運営に関わるきっかけとSwiftとの出会いを紹介しました。

画像

プログラミングとの出会い

以前在籍していた会社を休職していた時にプログラミングと出会い、コードアカデミーなどのオンライン学習サイトでHTMLやJavaScriptなどを学ぶうちにプログラミングの楽しさに目覚めたそうです。

Women Who Codeとの出会い

それからWomen Who Codeを知ったそうです。Women Who Codeはサンフランシスコに本部がある組織で、テクノロジ業界のすべての女性のエンパワーメントを目的として活動しています。当時は日本に支部がなかったのでCEOに直接メールを送ったところ「じゃあ日本でやったら?」とオファーされたとのことです。そして日本でキックオフイベントを行い、それから1ヶ月ニューヨークに滞在してmeetupに参加したそうです。

画像

日本における女性エンジニアを取り巻く環境

日本における女性エンジニアを取り巻く環境は決していいものと言えるものではありません。エンジニア全体における女性比率は11〜14%程度の割合で、それ自体が業界自体にネガティブな印象を与えてしまっています。Himiさんは、⁠海外では意欲的に学ぶ女性や、その人達をサポートする企業があるので、日本でもこの活動が活発になるために日々行動し続けている」と話していました。

画像

Rachel Bobbinsさん「Swift版 誰のためのデザイン?」

Stitch FixでiOSのリードをされているRachel Bobbinsさん@bobbinsさんは、心理学や認知科学から考えて製品を設計することについてセッションを行いました。

画像

ユーザーに対してフレンドリーなコード

D.A.ノーマン著『誰のためのデザイン?』を読んだ時、コードの設計にも当てはまるのではないかと気づいたそうです。まず、コードベースをやり取りする人(同僚、将来のチームメイト)をユーザーと捉えらていました。デベロッパーが無意識のうちに行っている行動を段階別に7つに分類し、そのユーザーに対してフレンドリーなコードを書くためのテクニックを説明しました。

画像
Discovarability

チームメンバーがコードを見た時、どうしたら何ができるかを発見できるようにすることが重要です。そのためには、命名規則を作ることと、Publicなどを正しく指定して、見つけるべきもの見つけないものを区別することです。

Feedback

テストなどで、失敗したら修正が必要なことを伝えたり、コンパイルエラーやWarningなど、自動化されたフィードバックが重要です。

概念モデル

概念モデルについては読み手の経験、バックグラウンド、教養によって様々に解釈されるため、わかりやすくなるように情報提供をすべきです。

Affordance

意味のあるメソッド呼び出しをすることと、getter/setterを正しく設計することが重要です。

Signifier

Swiftは様々なSignifierを持っており、それらが何らかのシグナルをデベロッパーに伝えています。例えばデータstruntで宣言されたオブジェクトの場合はコピーしても問題ないことを表しているなど、デベロッパーに対して重要な情報を伝えます。

Signifier

.xcodeprojの構成で部品の関係性を伝えています。

制約

Swiftの場合は型が正に最高の制約です。間違った型の使い方をするとコンパイルエラーが出るため、Objective-Cであったようなミスが無くなります。

画像

Daniel Eggertさん「モダンCoraData」

objc.ioの共同設立者の一人でもあるDaniel Eggertさん@danielboedewadtは、Core DataのAPIをベースにSwiftに置き換えていく方法を紹介しました。DanielさんはAppleでPhotos.appとCamera.appをCore Dataに関する仕事をしていたこともあるそうです。また、objc · Core Dataも執筆しています。

画像

以下の方法で置き換えていきました。

1. Insert New Object

従来だとエンティティ名をStringで指定していたので型安全ではありませんでした。まずProtocol Extensionでエンティティ名を切り出しました。インサート処理の際に切り出したメソッド名を呼ぶようにすることでコンパイルでチェックできるようになります。

2. Key Value Coding

従来の方法だとキーの値をタイプミスしやすく型安全ではありませんでした。型制約付きのProtocol Extensionを利用し、キーの値にEnumを用いることで、型安全に指定できるように改善できました。

3. Fetch Request

Fetch RequestはSortDescriptorをProtocolに切り出し、Protocol ExtensionでSortDescriptor処理を実装することでシンプルに改善できました。Predicateを使用する場合も同様です。

4. ValueTransformer

Protocol ExtensionにA→Bの変換、B→Aの逆変換をそれぞれ実装し、typealiasで宣言しておくことで様々な型に適用できるようにしました。

5. NSNotification

ClosureでDelete、Updateなどを処理できるように修正しました。NSManagedObjectContextにProtocol Extensionで通知を確認し、Closureで返すヘルパーを実装し、DidChangeNotificationをラップすることでシンプルな書き方に改善していました。

画像

既存APIのスピリットを尊重する

上記のようにProtocolとProtocol Extensionを駆使して既存APIをベースにSwiftコードに置き換えていました。これにより、既存APIのスピリットを尊重しつつ、Swiftの書き方で活かすことができると話していました。

画像

Novall Khanさん「SwiftコンパイラとLLDBの連携」

SplitwiseでiOSエンジニアをされているNovall Khanさん@novallkhanさんは、デバッグコンソールを使ったテクニックを紹介しました。

画像

LLDBについて

LLDBのデバッグコマンドを知ることで、エラーをより早く見つけられるようになるそうです。

LLDBはObjective-Cの場合はClang、Swiftの場合はSwift compilerの2つのコンパイラを持っています。コンパイラが内蔵されているため、デバッグコンソールに打ち込んだコードは実行中のアプリケーションで呼び出すこともできます。また、モジュール(UIApplication)にもアクセスできます。

Swiftのエラーハンドリング

LLDBはSwiftのエラーハンドリングに対応しており、該当箇所でブレークした後、LLDBのコマンドで「expression」を使用すればthrowされるエラーの結果を見ることができます。

また、エラーを起こしたコードを見る際に「breakpoint set -E swift」とすればエラー発生時にブレークされるようになります。特定のエラーの場合は「-O EnumError」と指定すればよいそうです。

画像

CustomStringConvertible

また、ネストされたデータ構造をデバッグ出力するときに、出力結果を見やすくする方法を説明しました。CustomStringConvertibleを実装することで、出力されるデータ構造を見やすくなるとのことです。

Jeff Huiさん「ライブラリの開発」

RSpecライクなSwiftのテストライブラリのQuick/NimbleのコアチームメンバーであるJeff Huiさん@jeffhuiは、Swiftのライブラリの開発についてセッションを行いました。

画像

テスト(CI)について

一定のレベルを保証したいのでテストは必ず組み込むようにしているそうです。テスト(CI)についてはオープンソースであればTravis CIが有効な選択肢で、.travis.ymlファイルだけで設定が完了するのでオススメとのことです。テストスクリプトもプラットフォームごとに同じことを書けば良いとのことでした。

画像

実際にライブラリを例に作業手順を説明しました。

パッケージマネージャへの対応

その際、以下の3つへの導入を考慮すべきとことでした。

CocoaPods
  • 依存性のあるライブラリを含めて自動でライブラリ化してくれる
  • PodSpecファイルの作成が必要
Carthage
  • プロジェクトに直接インクルードする場合
  • Cartファイルの設定が必要
Swift Package Manager
  • 唯一Linuxでの配布サポート
  • 対応作業が他の2つのパッケージマネージャより多い
画像

Swift Package Managerの注意点として、SwiftLinux自体が安定していないことを挙げていました。新しいバージョンが毎週出るほど問題があるそうです。そのため、SwiftEnvという環境ツールを使って指定のスナップショットからインストールしなければならないと話していました。

リリースの際のバージョニング

セマンティックバージョンの付け方についても言及がありました。詳しくはsemver.orgを参考にしてくださいとのことです。

Yosuke Ishikawaさん「Protocol-Oriented Programing in Networking」

ネットワークライブラリAPIKitの開発者のYosuke Ishikawaさん@_ishkawaは、Protocol-Oriented Programmingを適用したネットワーク関連のコードに関するセッションを行いました。

NSURLSessionをProtocolを使ってラッピングする

実装のゴールとしてはリクエストの型を指定すると自動でレスポンスの型が決定され、型安全にレスポンスが取得できるようにすることでした。

画像

この設計にProtocolが適している理由は以下の2つだそうです。

リクエストとレスポンスを紐付けが可能になる

Protocol内でtypealiasなレスポンスを宣言し、レスポンスを返すメソッドを作成することで、リクエストとレスポンスを紐付けることができます。リクエストの結果を受け取った時にレスポンスを返すメソッドを使用することで、リクエストごとに違う型を返すことができます。

デフォルト実装をフレキシブルに実装できる

DecodableというProtocolでdecodeメソッドを定義します。Protocol ExtensionにDecodableに準拠したResponseの型制約を使うことで、Protocol ExtensionのメソッドでResponseからdecodeメソッドが呼べるようになります。

参考になるソースコードは以下のものだそうです。

Generic Programing on Protocols

ページングなどの制約をprotocolで表していました。

  • ページ情報とページ指定をするメソッドを定義したProtocolを定義
  • 次のページの有無を表すProtocolを定義
  • 上記のProtocolに準拠したページネーションクライアントを実装

Protocolで定義したメソッドでしか実装しないことで汎用的なページネーションタイプのクライアントになれるとのことです。

Reactive Stream

画像

最後にRxSwiftを用いて、リフレッシュとネクストページをトリガーにしたリアクティブプログラミングをライブコーディングを行っていました。

画像

Maxim Cramerさん「ライブデザイニング:🎙🎨 」

Maxim Cramerさん@menneniaは、Sketchをつかったアプリアイコンの作成方法を紹介しました。

画像

Sketchを使ったAppIconの作成

例としてSketchを使ってアプリのアイコンを作りました。矩形はShiftを押してドラッグすると必ず正方形になるそうです。矩形を組み合わせてビルを表現したり、楕円を組み合わせて雲を表現していました。

画像 画像

また、ウェブアイコン(地球儀)も円、縦線、曲線をうまく組み合わせて作成していました。

画像

こうして10分くらいでアプリのアイコンを作成方法を説明しました。

画像

アイコンの切り出しはiOS Devicesというデバイス画像のテンプレートを使うのがオススメとのことでした。

Chris Eidhofさん「SwiftらしいTable View Controllerの使い方」

DecksetSceneryの開発者のChris Eidhofさん@chriseidhofは、SwiftらしいTable View Controllerの使い方を紹介しました。

画像

セッションで使用されたコードはGitHubで公開されています。

まずはシンプルなTableViewを作成し、最終的にはGenerics、Structを用いて編集した内容を戻すUndo機能を実装していました。

画像

TableViewConfiguration

次に、TableViewConfigurationというItemをGenericsで指定されたStructを作成しました。

TableViewに表示するitems、TableViewのstyle、cellのstyle、editable、セルの設定を行うclosureも実装しました。

TableViewを表示するのに必要な構成要素をStructに切り出したことで、TableViewController側に表示制御するためのコードがなくなりました。TableViewControllerの実装がシンプルになり、TableViewConfigurationの要素を変更すればTableViewControllerを再利用できる構造になりました。

画像

Undoの実装

そして、UndoHistoryというItemをGenericsで指定されたStructを作成しました。Itemを2重のArrayにすることで操作によるItemの変化を逐次残せるような構造になっていました。

画像

懇親会

2日目のセッション終了後にスポンサー限定の懇親会が開催されました。スピーカーの方々や参加者とコミュニケーションしたりと貴重な経験となりました。次回はスポンサーとして申し込むことも検討してみてはいかがでしょうか?

画像

(3日目のレポートに続きます。)

おすすめ記事

記事・ニュース一覧