SwiftらしいインターフェイスでUTIを扱うことができるようです。
簡潔な記述
同一性の確認(Equality)
パターンマッチによる識別(Confirmance)
例えば、MIMEタイプがimage/jpegであるものと、拡張子がjpegであるものの等値性を以下のようにして確認できます。
UTI ( MIMEType : "image/jpeg" ) == UTI ( filenameExtension : "jpeg" )
HUDKit
続いて紹介したHUDKitもアプリケーション開発の中で生まれたもので、以下のような場面においてHUDを利用するために作成されたそうです。
ブログ記事投稿後のユーザの操作への割り込み
SNSへのシェアの際にシェアするかどうかの確認
HUDに関しては既存のライブラリもありますが、viewベースのものでは不十分で、viewControllerとして扱うことができるHUDKitを作成されたそうです。このライブラリでは以下の2つのコンポーネントが提供されていることを紹介しました。
HUDPresentationController
UIPresentationControllerベースで自由にviewControllerを指定できる
HUDProgressViewController
進捗状況をHUDとして簡単に表示できる
HTTPRequestMatcher
最後に紹介したHTTPRequestMatcherは、Universal Linkやhandoffなどの対応で、特定のURLのパスでは特定のviewControllerを出したい、という際の処理を簡単にするものです。PerlのRouterSimpleを参考にしたもので、文字列でパスの制約を記述し、正規表現でのマッチングとキャプチャを行うことができると説明しました。例えば、あるURLが指定したblogのURLパターンとマッチしているかの判定、また、そのパターン内のblog_idのキャプチャ部分を以下のように書くことができます。
let URL = NSURL ( string : "http://example.com/blog/123/article/456" )
if case . Match ( let parameters ) =
PathMatcher ( "/blog/{blog_id:[0-9]+}" ). match ( URL ) {
let blogID = parameters [ "blog_id" ]. first !
}
}
問題の一般化
これら3つライブラリはどれも実際に直面した問題について、一般化可能な問題である場合や、または他の人にとっても役に立つものかもしれない、と思った際にそれを抜き出して解決したものであると述べました。そういったコードに対し、再利用性を持たせるためには以下が重要であるとのことです。
Generalize
Parameterlize
Abstraction
この"一般化可能かどうか"については、
直感
向き合っている問題がどのドメインに属している問題なのか。
といったものを判断材料にしているとQ&Aで回答していました。我々開発者がやるべきことは誰かの要望を叶えるアプリを作ることですが、その過程で他の人にも役立つことがあればコードをシェアしていこうと語り、このセッションを締めました。
Yasuhiro Inami氏「Parser Combinator in Swift」
続いてはLINE株式会社所属で、ReactKit などのライブラリの作者としても知られるYasuhiro Inami氏(@inamiy )による、Parser Combinatorについてのトークを紹介します。
Parser Combinator
Inami氏はまずParser Combinatorとそれを構成するParser(構文解析器)について、どういったものなのかについて次のように解説しました。
Parser
テキスト等のデータ、特にLexer(字句解析器)の結果としてのトークンを入力として受け取り、AST(Abstract Syntax Tree)のようなデータ構造を生成
ボトムアップなアルゴリズムとトップダウンなアルゴリズムの2種類が存在
Parser Combinator
Combinatorによって複数の小さなParserを組み合わせ、より複雑なParserを構成
結果として1つの大きいParserが動いているように見える
SwiftでのシンプルなParser
以上を踏まえた上で、実際にシンプルなParserをSwiftで複数定義し、それらを組み合わせて複雑なParserを構成する例を示しました。Parserのモナドとして以下を定義します。
struct Parser < A > {
let parse : String -> ( A , String )?
}
これは次の状態の変換を行うコンテナと言えます。
入力: String
出力: 出力と入力の残りのタプルのオプショナル値(失敗することがあるため)
これを利用し、例えば常に成功するParserは以下のように書くことができます。
func pure < A >( a : A ) -> Parser < A > {
return Parser { ( a , $0 ) }
}
こういったシンプルなParserを多数定義していき、さらにそれらを組み合わせたParser(Parser Combinator)の例を多数紹介しました。それぞれの具体的な中身全てを今回のレポートに載せるのは難しいため、ぜひ発表資料 を確認してみてください。例を挙げると、あるシンボルのParserは次のようにskipSpacesに挟まれたハンバーガー状になると紹介しました(個々のParserの定義は省略します)。
func symbol ( str : String ) -> Parser < String > {
return skipSpaces () *> string ( str ) <* skipSpaces ()
}
その後、BNFで表現した自然数で構成される計算機に基づいた、小さなParserを組み合わせたParser Combinatorを構築し、実際に"(12 + 3) * 4 + 5"という数式を解く例を示しました。しかしこれはまだ単純な例ということで、トークは次のTryParsecの紹介へと続きます。
TryParsec
TryParsecは今回のカンファレンス用にInami氏が実装したParserで、以下のレポジトリでその内容を確認できます。
以下のような特徴を持っています。
CSV、XML、JSONのパースをサポート
HaskellのAttoparsec/Aesonにインスパイアされたもので、Monadicである
独自のParserも簡単に作成可能
実際にSwift標準の機能を利用せず、TryParsecによりJSONデータをパースする例をまず示しました。さらに、マッピングルールを記述したモデルに対してのJSON Decoding/Encodingが簡単に行えることと、その例を紹介しました。例えばあるモデルに対するJSON DecodingについてはFromJSONを採用し、以下のように書くことができます。
extension Model : FromJSON {
static func fromJSON ( json : JSON ) -> Result < Model , JSON . ParseError > {
return fromJSONObject ( json ) {
curry ( self . init )
<^> $0 !! "string"
<*> $0 !! "num"
<*> $0 !! "bool"
<*> $0 !! "null"
<*> $0 !! "array"
<*> $0 !! "dict"
<*> $0 !! "object"
<*> $0 !? "dummy"
}
}
}
SwiftでJSONを扱う際の有名なライブラリの1つであるthoughtbot/Argo と同じApplicative Styleでの記述が可能になっており、非常に興味深い内容でした。まだパフォーマンス面が課題とのことですが、改善は継続していくとのことです。
Jesse Squires氏 - Contributing to Open Source Swift(オープンソースSwiftへの貢献)
JSQMessagesViewController の作者としても知られる、Instagram社のiOSエンジニアであるJesse Squire氏(@jesse_squires )の発表を紹介します。
Squires氏はまず以下を順に解説しました。
LLVMのコンパイラアーキテクチャ
Clangのパイプライン
Swiftのコンパイル時のパイプライン
例えばSwiftのコンパイル時のパイプラインは以下のようになることを述べました。
Swiftで書かれたコードをパースしAST(Abstract Syntax Tree)を生成
意味解析によってAST*を生成
SILGenでraw SIL(Swift Intermediate Language)を生成
最適化によりcanonical なSIL*を生成
IRGenによってLLVM IR(Intermediate Representation)を生成
LLVMによって最終的なバイナリを生成
実際にシンプルなコードに対し、swiftcコマンドを利用してAST, SILなどの各ステップの生成物を出力する例を紹介した上で、このパイプラインの各ステップがSwiftのレポジトリのどの部分に該当するのか、ということを紹介しました。例として、上記のステップ1, 2については以下のような対応関係があります。
こういったことを説明した上で、Swiftを取り巻くコンポーネント毎のContributeのしやすさを紹介しました。
Swift core
コアの部分。コンパイラなどはC++の知識が必要で、難易度が高い
Compiler
stdlib
SourceKit
INFRA
深い知識が必要で、Contributeするのが難しい部分
もうある程度固まったもので、開発が活発でない
Parckage Manager
Cライブラリを多くラップしている、チャレンジングな部分
Core libs
Evolution
try! contribute()
我々は具体的にどのようにContributeしたら良いのでしょうか。氏は次のように説明しました。
ディスカッションはメーリングリストでスタート
レベルに関係なく意見を言う
困ったら助けを求める
Pull RequestについてはCONTRIBUTING.mdを守り、ベストプラクティスに従う
たとえPull RequestがRejectされてもそこで落ち込まず、Contributeをそこでやめるべきではない
コアチームはすべての人に参加してほしいと思っている
Pull Requestに関しては、英語話者ではない場合にはTypoがあるだけで理解が大変になることもあるため、Typo fixも大事であると述べました。Chris Lattnerの次の言葉を引用していたのも特徴的でした。
Making small improvements is the way everyone starts getting involved!
最後に以下のような熱いメッセージを残し、このセッションを閉じました。
Swiftの成功が我々開発者にとっての成功であるのだから、Contributeすべき
コードだけではなくアイデアもContribute
Swiftは単なる言語ではなくコミュニティ
Ash Furrow氏「An Arsty Testing Tour(Artsyにおけるテスト手法の紹介)」
try! Swift最後のトークとなったのは、Moya などの作者としても知られ、数多くのOSSに関わっているArtsyのiOSエンジニア、Ash Furrow氏(@ashfurrow )によるセッションです。冒頭で以下の3つの項目を述べ、これらについてはセッションを通して強調していました。
テストにおいては完璧、理想形を目指さない。100%のカバレッジを目指さない。
コンポーネントは小さくし、Publicなインターフェイスのみをテストする。
新しいアプリケーションも小さなコンポーネントから始める。
その上で、Artsyで実際にどのようなテストの戦略を取ってきたのかについて、以下4つの実際のプロダクトを順に紹介しました(すべてGithub上に公開されています) 。
以下で順番に紹介します。トークを通してコードはほとんど用いず、図をメインで説明しているのが特徴的でした。
artsy/Emergence
Apple TV用のアートワークを見るためのアプリケーションであるEmergenceが最初の例でしたが、テストは全くないとのことです。プロジェクトのデッドラインが厳しく、作業は1人のみという最小限のリソースの中でバランスを考えた結果であるとのことで、テスト戦略に際してはバランスが重要だと語りました。ですが、同時にテストが書けないことを気にはすべきだと述べていました。
artsy/energy
アートギャラリーのアプリケーションのテストケースの紹介です。元々はテストはなかったのですが、非常に大きいコードベースだったため、途中でテストを書くことになったとのことです。
まず、Bus Factor(もしチームの誰かがバスに轢かれてもプロダクトを出荷できるかどうか) 、イコールどれだけチーム内の個人に情報が集中しているかの指標について触れ、その集中を避けるために行うべきこと・行ったことについて述べました。
良いテスト => 外部に対しての振る舞いのテスト
クラスは小さく保つ
Dependency Injectionを多く活用
オブジェクトは必要のないものは生成しない
RSpecスタイルでのテストで、共通処理は外に出す
artsy/eigen
eigenというアートのアプリについても後からテストを加える形だったそうですが、以下の困難があったことを紹介しました。
複数の箇所からネットワークアクセスがある状態へのテスト
iPhone, iPadという複数のプラットフォームに対してテストが必要
また、特徴的なテストとして、Snapshot Testの紹介がありました。こちらはfacebook/ios-snapshot-test-case を利用したもので、スクリーンショットの比較によってUIのテストを行っていたそうです。
その他にも以下のような説明をしていました。
新しいコードはテストがなければならないというルールを設けた
クラスはできるだけ小さく保つ
テストは小さな要素から始める
よくないコードを書かなければならない場合でも、どう修正したいのかを残しておく
artsy/eidolon
最後にアートオークションのアプリであるeidolonでのテスト事例の紹介です。Swiftが出た直後から始めたプロジェクトで、すべてが新しい中で、Unit Testが唯一慣れ親しんだもので、それがSwift自体を理解することにも繋がったと述べました。また、Quick やNimble を利用することで、RSpecスタイルのテストを効果的に書くことができたと述べました。特にNimbleの利用により、XCTestで記述していた部分を以下のようにシンプルに書くことができることを紹介しました。
XCTAssertEqual ( 1 + 1 , 2 , "..." )
expect ( 1 + 1 ). to ( equal ( 2 ) )
expect ( 1 + 1 ) == 2
最後に冒頭の3つの項目を繰り返し、セッションを閉じました。
終わりに
すべてのトークを紹介できないのが残念ですが、これ以外にも3日目の発表はSwiftでの統計学的な処理やサーバサイドでSwiftを利用する方法など、興味深い話が非常に多くありました。クロージングでは今回のカンファレンスでの様々な数値も発表されましたが、来場者は536名、そのうち147名は海外からの参加者だったそうです。
日本でのMobile・Web技術系カンファレンスで海外からの参加者の比率がこれほど高いものはそれほど多くはないと思います。私自身も多くの海外からの開発者と話す機会を持つことができ、非常に濃密な3日間を過ごすことができました。最終日の夜には参加者全員での懇親会も開かれたのですが、通訳ができる方を有志で募り、海外からの参加者と日本人の参加者がより交流を持てるようにするという試みも行われました。そのこともあってか懇親会も大変盛り上がり、3日間のカンファレンスの幕が閉じられました。
以上がtry! Swift3日目のレポートになります。主催者のNatashaTheRobotさんが以下ブログで語っていますが、開催に至るまでの道のりは大変だったようです。運営に携わった皆様、本当にありがとうございました。素晴らしいカンファレンスでしたので、ぜひまた開催されることを期待したいです。
Do you believe in magic? The making of try! Swift Conference Tokyo 2016