My Favorite Things - Coding or die.

とある技術者の経験記録、的な。

try! Swift 2017 Tokyo に参加してきた - 2日目:午前

さて2日目です。
https://www.tryswift.co/tokyo/jp

1日目と同様にその場でのメモと感想を書いていきますが、ちょっとボリュームが大きいので午前・午後の2つに記事を分割したいと思います。(個人的に見返しやすくもあるので)

テスト可能なコードを書くということの2つの側面

メモ

  • 冒頭
    • テストするためには2つの要素が必要
    • Haskellのような関数型コードを例に
    • 我々の成果をOSS化した
  • なぜテストをするか?
    • テストできるコードだけテストする
    • 関数型で書くのは良い
    • テストをドキュメント化する
    • エッジケースも十分に考慮する
  • compute(file:) -> Int
    • 単純に見えてもいろんな値を参照している
      • Bundle
      • String(contentsOfFile:)
    • 副作用がある
      • Consoleへ出力
    • なぜテストしづらいか?
      • ハードドライブという外部の状態に依存する
      • コンソールへの出力を確認する必要がある(外部に影響を与えていないか)
    • 2つの世界
      • インプット
      • アウトプット
  • 副作用
    • OUTPUT
      • 我々は慣れているので考えやすい
      • 影響がないか確認する必要がある(それ単体ではなく連鎖的に反応していないか)
      • 副作用のあるコードを境界部分にのみ持ってくる
      • 戻り値をIntの代わりに(Int, String)にしてコンソール出力を無くす
    • INPUT
      • Co-effects - 共作用
        • INPUTは共作用のテスト
        • 他のグローバルな関数を参照している
        • Co-effects = アウトプットを出すための前提条件
        • 言い換えると、それがないと結果を出せないようなもの
      • やりかた
        • すべてをstructに入れ込む
          • apiService: ServiceProtocol
          • cookieStorage: HTTPCookieStorageProtocol
          • currentUser: User?
          • dateType: DateProtocol.Type
          • language: Language
          • mainBundle: BundleProtocol
          • reachability: SignalProducer<Reachability, NoError>
          • scheduler:
          • userDefaults: UserDefaultsProtocol
        • 日付を取るのはCo-effectsのわかり易い例
          • 日付を参照すると副作用がある
        • バンドルも当然Co-effects
        • 通信状態も
        • Rxにおけるスケジューラも
        • 当然UserDefaultsも
      • リファクタリング
        • バンドル
          • 成功 or 失敗
        • 全部引数に持ってくる
        • 宣言が複雑にみえるけれど副作用が宣言部分に集約されている
  • 結論
    • なぜテストが難しいかというとCo-effectsがある
    • グローバルに自由に参照しないように、strutctを用意して、それを利用するようにする
      • そこに副作用をすべて集約する
  • FAQ
    • 1
      • バグレポート = 失敗したテスト
    • テスト駆動をよくやっている?
    • 2
      • ReaderMonad / StateMonad
        • あまり意識していない
      • プロパティベースのテストを行うのか
        • やりたいとは思っているが、まだ行っていない

断片メモコード

ファイル名を受け取って、その行数を返す関数

file: String = "number.txt" -> compute(file:) -> Int (12345)

感想

どうやって品質の良いテストコードを書くか、という話。

テストするための2つの要素「インプット」「アウトプット」について非常に詳しい説明がありました。もっとも一般的な入出力の話ではなく、副作用についての話でした。

発表者も言われてましたが「アウトプット」、例えばDatabaseやファイルを書き換えたり、iOSであればUserDefaultsを書き換えたり、という副作用は考え慣れているので簡単だけれど、「インプット」についてはあまり考えなかったりする、とのこと。

その前提条件となる「インプット」のことを「Co-effects(共作用)」というらしいが、それは最近の研究で話に上がってきたものらしく、あまり広まっている用語ではない模様。具体的には「現在時刻」などがわかり易い例で、アウトプットを出すための前提条件となるものが「共作用」と呼ばれるようです。グローバル関数もその例に当たる、と。

ではどうやって解決するかというと、インターフェースをプロトコルとして宣言して、そのプロトコルを引数として全部渡せば良い、とのこと。

たしかに関数の宣言は複雑になってしまうけれど、副作用がその一箇所に集約されるので、結果的に品質が安定するとのこと。(副作用のあるコードを境界部分のみに集約する)

そしてテストではなく実際の値を返すプロトコルの実装群は、グローバルなStructにまとめておくと良いとのこと。

などなど、私にとっては得るものが大変多いセッションでした。

ちなみに質問でReaderMonadを使わないのか、プロパティベースのテストは行っているのか、といった、非常にレベルの高い質問がされていました。

誰もが知りたいSequenceとCollectionのすべて

メモ

  • 構造
    • BidirectionalCollection
    • Collection
    • Sequence
  • Sequence
    • 要件
      • リスト
      • 有限 or 無限
      • 1回だけIterateできる
    • Iteratorを生成する
    • LinkedList
      • enumを使って実装すると素直
      • indirectで自分自身で使うことを宣言
      • iteratorは状態(現在の位置)を持つ
      • currentで現在の位置(要素)を保持
    • Count
      • users.filter({test}).count // => 配列を生成しちゃうので少しコストある
      • users.count({test}) // => great
      • Rubyとかだとお馴染み?
    • Each Pair
      • zip(list, list.dropFirst) が一般的なアプローチ
        • これも良いけれど・・・
      • where Self.SubSequence: Sequence
      • Elementを==で型制限
        • ごちゃごちゃするけれど仕方ない
  • Collection
    • 要件
      • Sequenceを引き継ぐ
      • 有限
      • 何回もIterateできる(Sequenceは1回)
    • 実装
      • Indexを持つ
      • start / end
    • APIErrorCollection
      • privateだとアクセス出来ないので?
  • BidirectionalCollection
    • 要件
      • Collectionを引き継ぐ
      • 前にも戻れる
    • 実装
      • afterに加えてbeforeが追加される
    • RandomeAccessCollection
      • その値に直接
    • RangeReplaceableCollection
      • 中間値を変換?
    • Appleのドキュメントを見ればいろいろ分かる
  • FAQ
    • 他の言語ではSequenceはIteratorではなくElement、何のメリット?
      • IteratorはSwift内部で使う
      • 独自の走査方法を作る時にCollectionではなくIteratorを実装する

感想

Swift の Iterator、Sequence、Collection、BidirectionalCollection について、どんな感じになっているのか詳しく見ていこう、という話。

微妙に理解が怪しい部分だったのだけれど、順を追った分かりやすい説明だったので、頭が整理されたような気がします。

個人的には xs.filter(predicate).count ではなく、 xs.count(predicate)という書き方が勉強になりました。もしかしたら Advanced Swift あたりで一度見ていたかもしれないけれど。

あとは EachPair の実装方法も面白かったです。

簡単にまとめると、以下のような感じでしょうか。 - Iterator:任意の値列を返す - Sequence:1回だけIterateできる - Collection:複数回操作できる - BidirectionalCollection:前にも戻れる

もう一度自分でコードを書いて、理解を深めておきたいところです。

様々な場面でSwiftを使う

メモ

  • Apple以外のプラットフォームの話
  • サーバサイドSwift / ライブラリ
  • OSS
    • 2015年に公開(Foundtion、SwiftPM)
    • x86_64のLinux環境サポート
    • Oct 2016: サーバサイドAPIを統一するための指針
  • Apple以外のプラットフォーム
    • Web
    • マイクロサービス
    • Deamon、Utility、Tool
  • なぜ?
    • 型付けされている
  • サーバサイドSwift
    • バックエンドのクローラ
      • Pythonで作ってたけど設計とか見直したい
      • リスクはあるけれどSwiftを使ってみることに
    • クローラ
      • ヘッダなどの余計な情報を落として、本文のみを保存する
      • MySQL/S3をデータストレージとして
      • APIを使って貯めたデータを取得するように → 社内で使えるように
      • gRPC protocol
        • Protocol Buffers
        • SwiftやGoでも使える
    • ライブラリ
      • HTTP(S) Client
        • libcurl(C based)
          • curlコマンドベース
      • HTMLパーサ
        • libxml2(C based)
        • XPathとかは簡単なものだけだったので正規表現
      • MySQL
        • mysql connector(C based)
      • S3 Client
      • 日本語変換(SJISEUC_JP) → クロール対象が日本語ページが多い
        • NKF(C based)
      • gRPC
        • 最近はOSSとして開発されている
    • SwiftとC言語
      • LLVMベースなので簡単に呼び出せる
      • C言語のライブラリがそのまま使える
    • 実際のプロジェクトについて
      • クローラ:10,000 lines
      • ライブラリ:9,000 lines
      • macOSで動かしてる
        • 20日動いてる
      • Linux環境も
        • 1週間くらいは動いてる
      • AWSへ移行する予定
  • 個人プロジェクト
    • ボードコンピュータで動かす
    • ラズパイとかで動かす
    • Swiftライブラリがそのまま動くように
    • ARM版のSwiftがある
    • ボード上でSwiftサーバを動かす
    • やり方
  • ポイント
    • C言語のライブラリをラップする
      • それを使ってSwiftっぽく
      • ex) libcurl, libxml, mysqlconnector
    • 他言語を呼び出す?
      • その実装が生のC言語APIを呼び出していればそれを
    • テスト済みのライブラリがあればテスト部分も減る
  • SPM
    • Node.jsのnpmに似ている
  • シェバンで使うと簡単なスクリプトとしても使える
  • まとめ
    • 安全で効率的
    • OSS
    • Cベースのライブラリ使える
  • FAQ
    • Pythonからパフォーマンスはあがったか?(C言語のスピードが大きい?)
      • これから測定予定
      • まとまったら記事として公開したいと思っている
    • NSURLSessionやNSURLConnectionは不十分なのか?(Foundationは不十分?)
      • Foundationの実装状況は公開されている
        • 殆ど実装されているので実プロダクト的には問題ないレベル
        • HTTPのローレベルを操作するためlibcurlを使った
    • ArdinoはLinuxではないのでSwiftは動かない

感想

Swiftをサーバサイド(MacLinux)やボードコンピュータ(ラズパイ)とかで動かす、という話。既存のPythonAPIの設計がイケてなくてパフォーマンスも改善したかったので、せっかくだからSwiftを使ってみた、とのこと。

他のセッションでもあったけれど、C言語のABIが安定していて、かつSwiftがLLVMを利用しているので、既存のC言語の資産を使えるとのこと。

実際にSwiftで開発したことで、いろいろと面倒なこともあったのではないかと思うけれど、そのあたりの話があまりなかったので、実際のところはどうなのだろうとは思います。

ただ実績として20日間動いているとのことなので、サーバサイドSwiftはもう実プロダクトとして利用できるレベルには達したのかな、と感じます。

⚡️🎤 VRの革新と新たなユーザー体験

メモ

  • VRをゲーム以外でも
  • 360°のVRが重要になってきている
  • ティム・クックはARは重要だと発言している
  • 事例
    • ショッピング(Alibaba)
      • VRショッピング(自宅にいながら有名なショップで買物)
    • 不動産
      • 360°の写真を取って、それを見られるようにする
    • 自動車
      • デザインやアクセサリの変更
      • 美しい形式でのドライブ
      • 店舗のスペース削減にも
    • ニュース・メディア
      • 360°の放送
      • 自らが実際に居るような体験ができる
      • NewYork Times
    • 運動
      • スケートのイメージトレーニング
      • 実際に効果があるとのこと

感想

VR(AR)が実際にどのような箇所で効果的に利用されているか、という実績紹介。

個人的にあまり強い興味は持っていない分野だったのだけれど、かなり身近になってきたし、うまく活用すれば良いサービスが提供できるのだと感じた。

iOSにおけるDocument IndexingとApp Search

メモ

  • 検索をアプリ内で
  • App Search → ほとんど使っている人がいない
  • App Search API
    • Core Spotlight API
      • private
      • 大量のデータの時に便利
      • 重要な属性
        • expirationDate(有効期限)
        • attributeSet(SpotLightで可視化)
        • uniqueIdentifier(まとめて管理が便利?)
      • プラクティス
        • 非同期でバッチ処理をする
        • コンテンツを常に最新にしていく
    • Search Continuation(from iOS10)
      • アイテムを探す時に便利?
      • 注意
        • beginBatch()はバックグラウンドスレッドで動く
        • beginBatchするまえにendBatchしないとクラッシュ
      • どうやってテストするか?
        • 開発者設定 > すべてのアイテム?
      • シミュレータでは機能しない(ので実機でテスト)
    • NSUserActivity
      • 見えるものだけが対象になる
    • SearchebleItem
    • Universal Link
      • Webページからアプリへ直接遷移
  • 統合する理由
    • コンテンツへのアクセスが速くなる

感想

iOS9からのAppSearchについて、実装方法とかの話。

個人的にはAppSearchはそれほど良い使われ方をしているように感じないので、まぁ効果的だと感じる人もいるのだなぁ、というくらいの感想でした。

ただ実践でのノウハウが共有されたのはありがたいと感じました。

スタートアップのSwift

メモ

  • Swiftの現場での経験(初心者からはじめて1年間)
  • スタートアップ
    • スタートアップは0から新しいものを作る、それもすぐに
    • 製品の様々な面を自分たちでカバーする必要がある
  • どうやって作るか?
    • Parse + Swift = Fast (To write)
    • CocoaPodsでいろんなOSSがあったので活用できた
  • リリース
    • 最初の2週間で10万人
    • 予想外の人数
  • 問題
    • 秒間リクエスト数を超えてしまった
      • リクエストを絞込
      • お金を払っても解決しなかった
      • 地域も絞る
    • Slackとテストフライトでフィードバックを得られるように
    • CEOがSlaskでクラッシュ解決を募集(再現している人)
      • 一人来てくれたのでiPhoneを繋いで調査した
      • ユーザ名が入っていなかった
    • 他に問題
      • 強制アンラップを使用しないように
      • switchのデフォルトシンタックス
      • 最初だから知らなかった
    • Extension
      • コードベースの改善に便利だった(丸くする、とか)
    • 最初に書いたコードは捨てる時期にもなってきている
    • Parseが閉じるアナウンス!
      • バックエンドをマイグレーションする必要がある
      • サービス性質上、全員分のデータを一気に移行する必要があった
      • ダウンタイムの間でデータ移行
      • 問題
    • Swiftのバージョン移行は大変だった
    • Swiftの学習カーブは低い(短期間で習得しやすい)

感想

スタートアップで Swift + Parse を利用した結果、サービスがどのように成長し、どのようなトラブルに巻き込まれかというリアルな話。

使いたいからではなく早く作るために Swift + Parse を採用し、その結果としてスケールしない問題に出くわしたり、それを解消するためにどのような対策を取ったのか。クラッシュの原因が分からない問題に対して、Slackでユーザを募集したり、そこからのフィードバックをいかに反映したか。そして Parse が閉じる事になった時に、どのようにデータ移行を行ったか。

などなど、非常に貴重な話を聞くことが出来ました。

外部サービスに依存した場合のリスクという話は以前からも聞いていましたが、今回の発表を聞いてそういったことが実際にあるのだという実感がわきました。

またクラッシュを解消するためにSlackでユーザを募集するというのは衝撃を受けました。日本でそんなことはまず出来ないと感じたからです。

try! Swift でスタートアップのリアルな話が聞けるとは思わなかったので、思わぬ誤算という感じのセッションでした。

try! Swift 2017 Tokyo に参加してきた - 2. 1日目

1日目の内容を感想を混ぜつつまとめていきます。
https://www.tryswift.co/tokyo/jp

通訳で聞いた内容で、ちゃんと聞き取れなかった箇所もあったと思うので間違っている箇所もあると思います。

なお迷ったのですが、箇条書きについては発表の場で書いたものをそのまま載せています。なのでたぶん講演を聞いていないと、あるいは聞いていても分からないような表現もあるかもしれませんがご了承ください。(まぁそこは自分用のブログなので、ということで)

一見して不要な情報に思えても、あとから見るとそうではないこともあると思うので。

Swift開発者が知りたかったけど聞きにくい機械学習のすべて

メモ

  • 機械学習、最新の技術をキャッチアップしていくのは大変。
  • データを集めて、関数を定義。
  • 誤差 → エラー
  • 線形回帰?
  • 驚くような結果を出すので、みんな熱中してる
  • Swiftの開発者にどんな関係があるか?
    • YES
    • そのうちどこでも採用するようになって普通になる?
    • 勉強していなくても出来る
    • 代数的データ型
    • Swiftが普通になったように、機械学習も同じようになる
    • Pythonは科学技術の分野でたくさん使われていたから
  • AVFoundation、CoreImage
    • 遅延実行モデル?
    • UIと同じように正確ではない(ユーザに見せてみるまで分からない)
  • どこから始めればよいのか?
    • 誰も専門家ではない
  • まとめ
    • 単なる流行りではない

感想

最近のビッグワードではある「機械学習」について、Swift開発者にとっても今後、あるいは既に関係してきている、という話。

そこまで目新しい内容があったわけではないけれど、機械学習というものが一般化してきているということをあらためて感じた。

今まであまり強い興味を持ってはいなかったけれど、勉強してみようと思った。

Swift on Android

  • なぜ?
  • C言語のABIは安定している
  • Android NDK は中途半端
  • Bionic(libcは使ってない)
    • いろんなプラットフォームから取ってきた寄せ集め
  • Lua→組み込み向けのスクリプト言語(AnsiCに互換)
  • 様々なNDKバージョンがある
    • バイナリを公開してもNG
  • libICU
  • staticにリンクすれば良いけれど、DLLにしないとだめ?
  • JNI
  • Cに見えるけれどSwiftのコードになっている
  • Swiftの関数に対して、C向けの設定をできる(@_cdecl)
  • イベントループをブロックしてはいけない
  • ObjcRuntimeはAndroid上ではない
  • グローバル変数の扱いには注意(DLLがメモリ読み込み済みだと前回の値が残る)
    • 再初期化用のAPIを用意する
  • 3つのテクニック
    • SwiftPM
      • 使えない
    • 自分でやる
      • 超大変
    • CMake
      • Android Studio でサポートすることを表明
      • Xcodeのプロジェクトを生成できる
  • IUP
    • Luaを作ったのと同じ大学?
    • GUIだけ
    • Cで書かれている
    • モバイルでも行ける
    • ダイアログをViewController、Activityにマップ
    • デスクトップ、モバイル、全部サポート
  • まとめ

感想

AndroidとかWindows上でSwiftのコードを動かす、という話。 なんというかハッキリ言って大変難しい内容でした(笑)

Swiftの関数宣言に@_cdeclという属性をつけることで、C言語から呼び出せるインターフェースにできるというのは知らなかったので、そんな機能が備わっていたのか、と思いました。

おそらくこれらのテクニックを自分で使うことはないと思いますが、クロスプラットフォームについていろいろ聞けて面白かったです。機会があればクロスプラットフォームとまでは行かないにしても、SwiftでModelコードを書いて、それをAndroidJava)のJNIから呼び出せるようなことが出来たら面白いと感じます。

SwiftのPointy Bits

メモ

  • Safe / Unsafe
  • ExeBadInstruction
  • off by one
  • 未定義動作
  • unsafe API を使えばメモリ操作が出来る
  • 8byte=ワード(64bit)
  • メモリアドレスは最小単位が8byte
  • なぜ4つのタイプがあるのか?
    • 型あり
      • 中途半端な位置にアクセスすることはない
      • Intなどの具体的な値がpointeeで返ってくる
      • UnsafePointer
      • UnsafeMutablePointer
    • 型なし
      • UnsafeRawPointer
      • UnsafeMutableRawPointer
    • インスタンスではなくタイプでMutabilityを制御
  • どういったときに使うのか?
    • CのAPIを使う
    • SKSearchFindMatches、暗黙的な変換が行える
      • ので、明示的にRawPointerなどを渡す必要はない
    • 安全性と引き換えにスピード
    • defer
    • UnsafeMutablePointのstaticメソッドを使えば余計な初期化も省ける
    • バブルソート
      • Unsafe使うとかなり速くなる
  • ポインタの誤用(2つ)
    • ポインタをエスケープしない
  • FAQ
    • rawPointerを使うと未定義動作に繋がる(エスケープに注意)

感想

Swiftでポインタ操作とかをやる、という話。

安全性と引き換えにスピードが必要な場合、あるいは本当にローレベルのプログラミングが必要な場合に使えるテクニックだと感じました。

個人的にポイント型がいろいろあってあまり理解できていなかった部分が整理できて良かったです。

ポインタのエスケープがマズイという話が最後にあったのですが、そのあたりは微妙に理解できませんでした。

アプリを新次元に導く3D Touch

メモ

  • iPhone6+ 以降で導入
  • 5年かかった
  • 早く機能にたどり着ける
  • 3D Touch 対応だとストアでも目立つ
  • APIとして使いやすい
  • 最大4つ
  • static / dynamic
  • static
    • コンパイル時に決定
    • info.plistに書く
    • 必須が2つ、他はオプショナル
  • dynamic
    • コードで生成
    • ユーザが使ったことがないと表示されない?
    • 直近で使ったメニューを表示とか(カフェ)
  • Widget
    • compact / expanded
  • Peek / Pop
    • プレビューとか(画面に遷移せずに見れるというメリット)
    • 確認すべきこと:ユーザが使えるか(自分でOFFにも出来る)
      • viewDidLoadでチェックすると良い
      • アプリを使っている最中でもOFFにされる可能性がある
      • 互換性
        • UIGestureRecognizer(Long)
    • 実装
      • UIViewControllerPreviewingDelegate
      • showだけでコミットできる
    • UIPreviewInteraction
      • 0〜1で生の値を取れる(例:スピード調整)
      • ソースとなるViewを設定する
  • 通知にも利用できる
    • ユーザの目を引く
    • 実装
      • UNNotification framework #別プロセス
  • FAQ
    • テストできるか?
    • ラッパーはあるのか?

感想

3Dタッチは簡単に導入できて、ユーザビリティを改善できるからみんなも導入してみては、というお話。AppleStoreでも目立つので、そういった意味でも良いとのこと。

3Dタッチの知識が不足していたので、いろいろと技術的な説明もあってありがたかったです。そしてAppleがこれを開発するのに5年を要したというのは驚きでした。

3Dタッチを利用して、画面に遷移させずにプレビューさせる、という使い方を初めて知ったのですが、個人的にはユーザにどうやって気付かせるか、というのが課題だと感じました。

まだ3DタッチはUIとして新しいものなので、今後広く使われるようになったタイミングで真価が発揮されるのかな、とも思います。

Pixcels、プロセスと情熱

メモ

  • 暴露療法
  • モチベーションを維持するのは大変
  • 実験とフィードバックを繰り返しながら(小刻みに)
  • 解決ではなく課題に注目するようになった
  • プロダクトではなく人々が大変
  • 自分や周囲を含めて幸せを目指す(自分のモチベーションを保つの大変)
  • コネクションを大切にする
  • 快適なゾーンを抜けてみる
    • 最低でも何かを学ぶことが出来る

感想

プロダクトを開発する過程についてのお話。

このような発表の場で「モチベーションを維持するのは大変」という事実を話してくださって、個人的には勇気づけられました。

そして「解決ではなく課題に注目する」というのは面白い視点だと思いました。

毎日リアクティブ

メモ

  • リアクティブ楽しい
  • パラダイムをmixして使っている
  • 非同期に変更されるデータに対して反応する
  • ポイント
    • Stateを減らす
    • 宣言型のコード(How -> What)
  • FW
    • RxSwift
    • RxCocoa
    • SwiftBond
  • 背後にあるアイディア(コンセプト)は一緒
    • 1回学べば潰しが効く
  • いつ使うべきか?
    • 複雑なアプリケーション
    • MVVM
    • async ops
    • 解決を目指す
  • トレードオフ
    • デバッグが辛い(コールスタックは使えなくなる)
      • 怪しいストリームをロギングする
    • 命令形のコードを混ぜるとリアクティブの意味が無くなる
      • bindを使う
    • Hot/Cold
      • 副作用は本当に必要な場合だけにする
    • カオスを避ける
      • 別スレッドから呼ばれるケースを考える
      • 値を変更せずに新しい値を生成するとか
  • リアクティブプログラミングの展望
    • AppleのFWなどのリアクティブ前提でないものとの連携は大変
    • APIがちゃんとリアクティブをサポートするように

感想

特定のFW(RxSwift)とかではなく、リアクティブプログラミング一般についての話。発表でもいろいろなFWのコードが混ぜて説明されていました。

個人的には「デバッグが辛い」というのが利用者にとっての共通の課題だということを知って安心しました。

そしてアンチパターンについてもきちんと言及されていたのも良かったです。頭でわかっていてもこうやって講演で実際に聞けると自信が持てるものです。

リアクティブプログラミングという考え方はやはり有用だと思うので、適材適所をよく考えて適用していきたいと感じました。

⚡️🎤 Unsafe Swiftの安全性

メモ

  • 未定義動作は辛いよ
  • Swiftではいろいろ考えている
    • 非初期化されていない値へのアクセスは許可しない
  • Set/Dictionary

感想

ハッシュ値の計算をメモリ内容からやったら良いんじゃないか、という話。 コード内容を覚えていないのですが、あとでスライドが公開されていたら試してみたいと思いました。

ちなみに文字列連結によるハッシュ値計算はよく使っていたのですが、ヒープアロケーションが増えるというのは本当なのかな、と思いました。SwiftのString型は構造体なのでスタックに確保されると思ったので。そのあたりも含めて理解したいところ。

クックパッドアプリのテストを味わう

メモ

  • UIの刷新を何回かしている
  • リリース
    • 1ヶ月単位
    • 5000 -> 100,000Loc
  • 品質
    • Must-be(最低限の品質)
      • クラッシュしないこと
  • ユニットテストを先に書く、はやらない
  • 内部から
      1. UI Tests
      1. re-write / re-factor
      1. Unit Tests
  • 外部から
  • UIテスト
    • 非常に重要
    • 時間もすごくかかる
  • テストピラミッド(上に行くほど小さい)
    • UI Test
    • Integration Test
    • Unit Test
  • 汚いコードで自動化するのはやめろ
  • 8割くらいUITestサポートしてる
  • ターニップ?
  • アンチパターン
    • XPathはView階層に依存するので良くない
    • ラベルを使う
  • バリデーションとかはUIではなくメソッドでテストする
  • Image diff
  • ネットワークリクエストの回数とかも記録してる
    • 余計なリクエストとかが増えてないか、とか
  • 怖がることなく変更できる
  • アールグレイとかも検討(Appiumは使い続ける予定)
  • UIテストは re-enginering をサポートする
  • FAQ
    • XCUITestだとシステムアラートが出ない
    • 遅いけれども毎回クリーンな状態で実行できる Appium を選択している

感想

クックパッドさん定番?のテストについての話。

UIを刷新するタイミングで大規模なリファクタリングが行えているのは、素直にすごいなと思いました。それだけ回帰テストがうまく回さているのだと思います。

個人的にはAppiumでのテストでキャプチャを取って、それを前回のキャプチャとdiffを取る、というテクニックがクールだなと思いました。個人的にもUIテストを導入するのであればぜひやりたいと思っていたテクニックなので、UIテストを今後やることがあれば是非取り入れたいと思いました。

テストについてのいろいろな知見が得られたので、勉強になったセッションです。

⚡️🎤 データレイヤを分離する

メモ

  • 階層がきちんと分離されていれば良い
  • 最小限のアーキテクチャ
  • 層の詳細な実装が隠されるべき
  • DTO、translatorを用意する
  • 複数のチームでも機能する(実装の詳細が隠されるから)
  • 変換コードを書くのは時間かかるけど、スレッド間の問題を負うほうがよっぽど時間かかる
  • チームごとに必要なことだけを知る

感想

データレイヤを分離して、複数チームでも円滑に実装できるようにしよう、そのために昔ながらのDTOを使ったら良いんじゃないか、という話。

個人的にはシンプルだけれど良いアイディアだなと思いました。アーキテクチャがどうのというよりは、複数チーム間で機能させるように考えた、というところがです。

こういう話を聞くと、正解のアーキテクチャなんて無くて、プロジェクトやチームに応じた最適なアーキテクチャがあるだけなのだということを再認識させられます。(これも何度となく言われていることではありますが)

UIをSwiftyに書く

メモ

  • 事前に決めておくこともある
  • けれどコーディング中にパターンが見えてくることもある
  • UIは冗長なコードになりがち
  • 4つのパターン
  • シュレディンガーのコード
  • layoutSubviews
    • 大きくなると辛い
  • Storyboard
    • チームだとコンフリクト解決が辛い
    • 色などが定数で書けない
    • 文字列ベースになってしまう -> Swiftの型安全性がない
    • Outlet接続が間違っているとクラッシュしちゃう
    • AutoLayoutは使わない
  • コードで書く
    • レイアウトが分からない(たった5行であっても)
    • Cartography
      • 宣言的なコードで記述できる
      • 線形方程式を書いている
  • ステート
    • 取得中
    • 成功
    • 失敗
  • 単純にフラグ変数で用意すると不必要な状態も持ち合わせてしまう
  • enumを使う
    • .loading
    • .loaded(item: [MovieItem])
    • .error(message: String)
  • didSetだけで状態を更新する
  • viewのロジックを一元化できる
  • protocolを使って複数画面でも共通化する?
  • デフォルト実装を使う

感想

StoryboardがSwiftの型安全とマッチしないという点と、プロトコルを使った共通的なパターン(取得中、成功、失敗)の実装方法が面白かったセクション。

個人的にはわりとStoryboard派ではあったのですけれど、ちょっと考え方を変えてみても良いかなと感じました。そしてプロトコルの使い方はとてもおもしろかったので、今度サンプルコードとか書いてみたいと思いました。

SwiftのWeb APIとアプリをともに構築する

メモ

  • 良いAPIとは?
  • ページネーションで重複するのを解決する
    • 最後の項目のidを渡す(before)
  • 変更をどうやって管理するか?
    • バージョニング(原始的なアイディア)
  • REST
    • APIの結果にURLとかDOMの情報を含める
      • クライアントが変更不要になる
  • Frank
    • ちっちゃな感じ?
  • Kitura
  • Vapor
    • Web FW
  • Heroku
    • Procfile
    • web: Hello
    • BluemixはHerokuの拡張?
  • Papertrail
  • まとめ

感想

良いAPIの設計指針としてバージョニングではなく、レスポンス自体に画面描画や次のリクエストを含めるという話。あとはSwift製のWebFWについての紹介。

APIの設計指針については微妙に理解が怪しい感じではありますが、なんとなくコンセプトは理解できたような気がします。

WebFWについては個人的にVaporとKituraは触っていたのですが、それぞれの特徴がしれて良かったです。そしてHerokuへ簡単にデプロイ出来ることもわかったのも収穫でした。

⚡️🎤 楽しく便利なSwiftチャット

メモ

  • 良いUIを作ればボットはまだまだ可能性がある
  • たくさんのインターフェースを詰め込みすぎないようにする
    • manページが必要になる
  • Heroku + Vapor
  • Bot用のインターフェースはいっぱいある
    • 文字
    • 画像
    • ロケーション

感想

ボットはUIやアイディア次第でまだまだ可能性はあるよ、という話。

ボットというと地味なイメージがあったのですが、デモを見たらわりと面白いと感じました。個人的にもなにかボットを作ってみたいなという思いもしました。

Realmを使ってコラボレーションアプリを作る

メモ

  • Realmとは
    • オブジェクトデータベースではない
    • モバイル機器のためにゼロから開発
      • SQLiteはモバイル向けに設計されたわけではない
    • 特別な記法は必要ない
  • データベースの同期
    • バイス間の同期
    • 共同編集
    • コンフリクトした場合は自動的に解決してくれる
    • オフラインでも大丈夫
  • Realmの通知機能
    • プロパティの変更監視
    • オブジェクトの変更
    • コレクションの変更
    • ファイル全体の変更通知
    • すべてのRealmを同期

感想

ちょっとRealmの宣伝的なセクションだったような気がします。(まぁスポンサーだし仕方ないね!)

まぁしかしRealmでデータベースの同期がシンプルに実現できるというのは勉強になりました。まぁFirebaseでも出来るようですが :-)

独自のツールを構築する

メモ

  • DANGER(コードレビューを楽にする)
  • 問題
    • アプリ開発はスケールしない
    • もっと早く開発できるようにしたい
    • アプリの全体または部分を再コンパイルする必要がある(から遅い)
    • 画面ごとにXcodeプロジェクトを作るというアイディア
      • 長期的には現実的ではなかった
    • ReactNativeが良かった
      • 開発者のエクスピリエンスは満足
    • コンパイル時間長くて辛い
      • ネイティブ開発は辛い
      • インジェクションというテクニックを使うとビルド時間は1秒くらいに
    • 画面に関するコードは結構な量になる
  • ReactNative
    • デメリット
      • 依存性は593 -> 理解するのはほとんど不可能
      • 若い
      • 変更される
      • 万能薬ではない(当然ながら)
    • JavaScriptのテストはネイティブよりずっと進んでいる
    • TypeScript(現代のJavaScriptは楽しい)
  • React
    • View階層をマスクしようという試み
    • ネイティブ階層を作る
    • JavaScriptをネイティブコードに変換するようなことはしていない
    • Relay便利
  • Appleの主要なアプリでネットワークを使っているのは2つくらい?
  • まずはApple向け、次に外の開発者向け
    • だから良い企業になった
  • Appleは超安全なリリースが重要
  • 我々はそこまで必要でないこともある
    • Xcodeの外に目を向けてみるのも手

感想

開発速度を改善するためにあえてReactNativeを使った、という話。

Swiftは型安全ですし、個人的にも結構気に入っている言語ではありますが、如何せんコンパイル速度は遅いです。そうした現実を受けて、あえて型安全がない代わりにコンパイル速度(開発サイクル)が高速なJavaScriptを選択した、というのは非常に勉強になりました。

Swiftという言語がApple社内向けに作られた言語であり、その次に外の開発者向けである、という洞察にも舌を巻きました。なるほどその考え方は無かったです。

⚡️🎤リアルタイム物体検出アプリでよりよいフィードバックを提供する

メモ

  • ユーザにフィードバックを提供する
  • ラッキング(物体にIDを振る)
  • 検知だけではなくトラッキングについて考えるのも手

感想

リアルタイム物体検出で、トラッキングしたりしてユーザにフィードバックするとより良いUIが提供できるよ、という話。

Wantedlyさんのアプリだったと思うのですが、なかなか良い感じのUIが出来上がっていて、とても良いと感じました。

⚡️🎤 UXエンジニアという働き方

メモ

  • 使ってもらえるから意味がある
  • UXを良くするためにやっていること
    • ユーザテスト
    • デザイン思考
      • 優秀なデザイナーが行っていること
      • 「共感」がポイント
  • まとめ
    • ユーザを忘れない
    • 小さなことでも出来ることから

感想

エンジニアでもUIとかUX大切ですよ、という話。

個人的に「デザイン思考」という優秀なデザイナー日々行っているという言葉を初めて知って勉強になりました。

1日目の終わりに

慣れない通訳でのプレゼンに戸惑いながらも、すごくいろいろな事が聞けて、とても刺激的な一日でした。(あらためてメモをみると、最初はなかなか苦労していましたね・・・やはり)

いやはや、なんというか1日で咀嚼できるボリュームではとてもありません。

Swiftのカンファレンスでありながら、それ以外の発表も多くあったりして、最初はちょっと戸惑ったのですが、結果的にはいろいろな知識を吸収できてよかったような気がします。

try! Swift 2017 Tokyo に参加してきた - 1.全体を通して振り返る

はじめに

参加してきました。
https://www.tryswift.co/tokyo/jp

家に帰ってから記事を書くまでがカンファレンスです、という名言を最初に聞いたのはXP祭りだったでしょうか? そんなわけで今回も個人的な感想を書いていきたいと思います。

おそらく長くなるので記事は以下のように分割したいと思います。

  1. 全体を通して振り返る(この記事)
  2. 1日目
  3. 2日目
  4. 3日目(ハッカソン

要約

とてもハイレベルなイベントで、参加してすごく良かったと思えるイベントでした。

正直なところ早割で$250、通常だと$350する参加費は高いと感じました。 (もちろん開催にあたってかなりの経費がかかることはわかりますが)

しかしながら他ではなかなか聞くことが出来ない"リアル"な話が聞けて、 個人的には参加費として$350払う価値は十分にあったかと思います。

ちなみに外国人の登壇者が多かったですが、同じく外国人の参加者も多かったです。 日本で開催されるIT系のイベントでここまで外国人率が多いイベントも少ないように感じます。

開催場所

1日目と2日目が新宿、3日目が神田で開催されました。

1日目と2日目(新宿)

新宿の会場へはJR新宿駅から会場に向かったのですが、いやはや思ったより遠かったです(笑)

会場は広く、前半分くらいはテーブルがあって、後ろ半分はテーブルなしでした。 幸いにもテーブルがある席が確保できてメモが捗りました。

ちなみに会場の電源は使用することが出来ず、Macのバッテリーはギリギリでした。

3日目(神田)

神田駅からわりと近い位置でした。

1日目と2日目が平日、しかも早い時間帯ということもあって、満員電車で揺られた後、そこそこの距離を歩いて会場に到着、という感じだったのでありがたかったです。

同時通訳について

同時通訳があるイベントに参加したのは恐らく初めてだったのですが、 技術ワードについてもきちんと通訳できており、非常にレベルの高い通訳だったと思います。

わたしはかろうじて英語が少し読める程度の力なので、今回のカンファレンスでの同時通訳は無くてはならないものでした。 通訳してくださった皆様方には大変感謝です。

発表について

発表内容はそれぞれ違うのですが、以下のような共通項があったように感じます。

  • 銀の弾丸は無い
  • 可読性の重要さ
  • Protocol Oriented Programming(プロトコル指向を使ったテクニック)
  • 型を意識したコード

銀の弾丸は無い

銀の弾丸は無い」というのは(多くの発表者も言われてましたが)古くからあるもので新しいものではありません。 しかし、これほど何度も繰り返し言われるということは、それだけ人がその存在を信じやすい、ということでしょう。

最近について言えば「リアクティブプログラミング」がその良い例だったように感じます。あの騒ぎは何だったのでしょうか?

もちろん優れた技術ですし、私自身も勉強会を開催するくらいには気に入った技術です。 しかし、それを「銀の弾丸」だと信じて採用した開発チームの末路はどこも一緒なのではないかとも思います。

可読性の重要さ

これも多くの発表に共通しているものだったように感じます。

プログラミング言語というのは半分は技術の進歩で、もう半分は(数学のような)記法の進化である、という言葉はハッカーと画家に書いてありましたが、つまりそういったことではないでしょうか?

可読性、言い換えるとコード上でのコミュニケーションの重要さを軽視すべきではない、ということかと思います。

Protocol Oriented Programming(プロトコル指向を使ったテクニック)

これもSwiftを使った実践的なテクニックの面では多用されていました。 プロトコル指向の原型はHaskellの型クラスにあると思うのですが、やはり関数型のテクニックはSwiftのコードにおいても有用、ということかと思います。

個人的にProtocolを大げさに感じていた面もあった(これはJavaのインターフェースの時代からですが)のですが、これを気に考え直したいと思いました。

型を意識したコード

Interface Builder が必ずしも最適解ではないという理由に、Swiftの良さである型安全が保たれない、という説明がありました。 他にも型を重要と(明示的あるいは暗黙的に)捉えた発表が多くあったように感じます。

発表テーマ

1日目

2日目に比べると「Swiftにかぎらず」「詳細よりもコンセプトを」という発表が多かった気がします。 もちろんそれだけに限っているわけではありませんが。

個人的には「Orta Therox」さんの「独自のツールを構築する」が面白かったです。

2日目

1日目に比べて「具体的なSwiftコード」という側面での発表が多かったです。 まさにSwiftカンファレンスという感じで、個人的には2日目の方が楽しめました。

個人的には「Jon Reid」さんの「モックオブジェクトをより便利にする」が面白かったです。 今までの人生で聞いた発表の中で一番かもしれません。

3日目

わたしは友人と一緒に2人チームでハッカソンに参加しました。

合計48組の中で、審査員の選考を通過した10組が壇上でプレゼンし、うち上位3組が商品をもらえるという形式でした。

残念ながら入賞はできなかったのですが、10組には選出されて壇上でプレゼンすることができました。

swift-heredoc
https://devpost.com/software/swift-heredoc

朝食・昼食・パーティーについて

朝食

タイムテーブルにある”朝食”という文言で、ホテルの朝食のようなビュッフェを想像してしまったのですが、実際には菓子パン1つでした(笑)

これは勝手に期待してしまった私が悪かったのですが。 ただ3日間を通じてコーヒーが自由に飲めたのは大変ありがたかったです。

昼食

これ系のイベントにしてはわりと豪華なお弁当だったように感じます。 ただし人気のあるメニューはわりとすぐになくなったような気がします。

パーティー

IT系のイベントに限らず、これほど豪華なパーティーに参加したのはわたしは初めてでした。 美味しい料理を開発者たちで飲み食いできるのは楽しかったです。

わたしはシャイなので自分からは話しかけられないタイプなのですが、話しかけてくださった方には大変感謝です。ありがとう。

まとめ

この一言で片付いてしまうのですが、本当に参加してよかったと思えるイベントでした。

もしSwiftに興味がある技術者は、多少無理をしてでも来年参加されてみることをおすすめします。

業務が忙しい人も多いと思いますが、何倍ものリターンが得られるかと思いますし、その知見を日々の業務にフィードバックすることで、より生産的な仕事が出来る様になると思います。

Swift3 例外メモ(try、try!、try?、do-catch)

try?の仕組みとか曖昧になってしまったのでメモ。

例外のスロー

  • 例外をスローする関数はthrowsを宣言(書く位置は引数宣言の直後)
  • スローする例外はErrorプロトコルを実装している必要がある
enum MyError: Error {
    case notFound
    case fail(String)
}

func fatalError() throws -> String {
    throw MyError.fail("fatal error.")
}

呼び出し元

すべての例外の補足

  • do { try throws宣言された関数呼び出し } catch { ... }といった構文で例外をキャッチ
  • throws宣言された関数を呼び出すときには、頭にtrytry!try?のいずれかをつける
  • catch { ... }またはcatch let error { ... }ですべての例外をキャッチ(switchdefaultみたいな)
  • enumのようにエラーの種類から網羅性はチェックされないので、網羅するにはすべての例外を補足するcatchが必須
func catchAllErrors() {
    do {
        try fatalError() // `throws`宣言された関数を呼ぶには`try`が必要
    } catch MyError.notFound { // エラーの種類を記述
        // ...
    } catch MyError.fail(let message) { // enumの関連値はパターンマッチで取得できる
        // ...
    } catch let error { // enumと違って網羅するにはこれが必須
        // ...
    }
}

部分的に例外を補足

  • すべての例外を補足しない場合は、関数の宣言にthrowsを記述する必要がある
func catchSomeErrors() throws { // 例外を網羅できていないので`throws`宣言が必須
    do {
        try fatalError()
    } catch MyError.notFound {
        // ...
    }
}

例外を強制的に無視する(try!)

  • try!を使うと例外を無視できる(do-catchが不要)
  • ただし例外が発生したときにはクラッシュする(強制アンラップと同じ挙動)
func forceCall() {
    try! notError() // 例外を無視する(が、発生したときはクラッシュする)
}

例外を安全的に無視する(try?)

  • try?を使うと、try!と同じように例外を安全に無視できる
  • try!と違い、例外が発生した場合でも単純に無視される
  • 呼び出した関数に戻り値がある場合は、戻り値がnilとなる(失敗した、というニュアンスか)
func safeCall() {
    try? fatalError() // 戻り値がない場合はセーフな呼び出し
    let s1 = try? fatalError() // => nil
    let s2 = try? someString() // => some string
}

まとめ

個人的にこんな感じで考えたらよいのかなという指針。

  • 発生した例外に興味がなければ、try?を使って例外を無視する
  • 発生した例外に興味がある場合は、do { try xxx() } catch { ... }を使って補足
  • 入力値が完全に固定など、確実に例外が発生しないと断言できる場合はtry!を例外的に使う(かも)

個人的にはEitherあるいはResultのほうが好きなのだけれど、シンタックスシュガーがよく出来ているので場合によっては例外の使用を検討しても良いのかも。

Vagrantfile: Ubuntu14.04 で Swift製Webフレームワーク「Vapor」を使える状態にする

Swift製のWebフレームワークである「Vapor」をUbuntuに入れてみた。
github.com

せっかくなのでVagrantfileを書いてみた。(たぶんこれが一番楽だと思います)

ちなみにVagrantについてはドットインストールの動画が分かりやすいです。
http://dotinstall.com/lessons/basic_vagrant

環境

手順

作業ディレクトリ作成

$ mkdir ubuntu-server # 適当なディレクトリを作成
$ cd ubuntu-server
$ curl -O https://gist.githubusercontent.com/YusukeHosonuma/54a2f4f294e87cf0dbc87b7420b5ae1c/raw/c181f41b05f2a7dddbe452dd5119b5dcbd857a96/Vagrantfile

VM起動+ssh接続

$ vagrant up
$ vagrant ssh

Vaporプロジェクト作成・ビルド

$ vapor new hello
$ cd hello/
$ vapor build

ビルドがわりと長い・・・依存関係の解決に時間かかってる?

実行

$ vapor run serve
Running hello...
No preparations.
Server 'default' starting at 0.0.0.0:8080

Tomcatと同じ8080ポートで起動されている模様。

動作確認

ホストマシン(Macとか)で以下のURLをブラウザで表示。 http://192.168.33.19:8080

真っ白な画面の中央に以下のロゴが表示されればOK。 f:id:yu_dotnet2004:20170102150015p:plain

簡単でしたね。

Vagrant + CentOS7 で、RustのWebフレームワークRocketを発射する

Linuxとか環境面詳しくないのでメモ。

Rocketは最近出たRustのWebフレームワーク。
https://rocket.rs

環境

VirtualBox: 5.0.30
Vagrant: 1.9.1
CentOS: 7.1
Rust: 1.16.0-nightly
Rocket: 0.1.2

ちなみにこれを書いている時点で最新のCentOSは7.3だったけれど、vagrant upで立ち上げたら途中で止まってしまったので断念。

VagrantでCentOS7を立ち上げる

まずは発射台を準備。

$ mkdir launch-pad
$ cd launch-pad

Boxイメージは、Chef社がOSSとして公開してる「Bento」を使う。
(弁当箱とは誰がうまいことを)
https://atlas.hashicorp.com/bento

$ vagrant init bento/centos-7.1
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.

Vagrantfileは以下のようにしてプライベートネットワークとして接続できるようにしておく。

Vagrant.configure("2") do |config|
  config.vm.box = "bento/centos-7.1"
  config.vm.network "private_network", ip: "192.168.33.11", auto_config: false
end

原因はよく分かっていないのだけれど、auto_config: falseを設定しておかないと、立ち上げたVM上で正しくIPアドレスが振り当てられなかった。

VMイメージを起動。(Boxの取得から始まるので時間かかるよ!)

$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
...

SSHで接続。

$ vagrant ssh
-bash: warning: setlocale: LC_CTYPE: cannot change locale (UTF-8): No such file or directory
[vagrant@localhost ~]$

基本設定

ファイアウォールを切ってしまう。(仮想環境なので)

$ sudo systemctl stop firewalld
$ sudo systemctl disable firewalld

SELinuxが無効か確認。今回は無効になっているのでそのまま。

$ getenforce
Permissive

Rustのインストール

Rocketでは構文拡張を利用するため、NigthlyなRustが必須。(2016/12/30時点)

Rust1.14.0で公式ツールとなったrustupをインストールする。 https://rustup.rs

$ curl https://sh.rustup.rs -sSf | sh
info: downloading installer
...

選択肢が表示されるが、とりあえずデフォルトの1)を選択。

Current installation options:

   default host triple: x86_64-unknown-linux-gnu
     default toolchain: stable
  modify PATH variable: yes

1) Proceed with installation (default)
2) Customize installation
3) Cancel installation

Rust is installed now. Great!

To get started you need Cargo's bin directory in your PATH environment variable. Next time you log in this will be done automatically.

To configure your current shell run source $HOME/.cargo/env

パスを設定してくださいと言われるので、.bash_profile に記述しておく。

# Rust
source $HOME/.cargo/env

再読込して現在のシェルに反映させておく。これでRustが使えるようになった。

$ source ~/.bash_profile
$ rustc --version
rustc 1.14.0 (e8a012324 2016-12-16)

そしてRustを最新版(Nightly)に変更。

$ rustup default nightly
$ rustc --version
rustc 1.16.0-nightly (4ecc85beb 2016-12-28)

Hello, world

Rocket用のプロジェクトを作成して、そこに移動。

$ cargo new hello-rocket --bin
     Created binary (application) `hello-rocket` project
$ cd hello-rocket

Cargo.toml の依存ライブラリに以下を追加。

[dependencies]
rocket = "0.1.2"
rocket_codegen = "0.1.2"

src/main.rs を以下のように編集。このあたりは公式ドキュメントどおり。

#![feature(plugin)]
#![plugin(rocket_codegen)]

extern crate rocket;

#[get("/")]
fn index() -> &'static str {
    "Hello, world!"
}

fn main() {
    rocket::ignite().mount("/", routes![index]).launch();
}

そしてビルド・実行・・・するがエラーになる。

$ cargo run
...

error: aborting due to previous error

error: Could not compile `unicase`.

To learn more, run the command again with --verbose.

どうやらgccが入っていないのが原因らしいのでインストール。

$ sudo yum -y install gcc
...

今度こそロケットを打ち上げられた。

$ cargo run

Finished debug [unoptimized + debuginfo] target(s) in 79.19 secs
 Running `target/debug/hello-rocket`
🔧  Configured for development.
=> listening: localhost:8000
=> logging: Normal
🛰  Mounting '/':
=> GET /
🚀  Rocket has launched from http://localhost:8000...

VM内でcurlを叩くとちゃんと動いていることが分かる。

$ curl localhost:8000
Hello, world!

80ポートで起動する

ここからはあんまり正攻法じゃない。 ので、とりあえずこの方法でうまくいった程度の話。

Rocketのドキュメントを見ると、Productionで実行するには以下のようにすればよいと書いてある。

$ sudo ROCKET_ENV=staging cargo run
sudo: cargo: command not found

が、エラーとなる。

これは環境変数PATHがsudo時に引き継がれないのが問題らしい。

$ env | grep PATH
PATH=/home/vagrant/.cargo/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/vagrant/.local/bin:/home/vagrant/bin
$ sudo env | grep PATH
PATH=/sbin:/bin:/usr/sbin:/usr/bin

で、調べるといろいろと情報が出てくる。

CentOS で sudo 時に実行ユーザーのPATHを引き継ぐ http://qiita.com/ogwmtnr/items/3ec2fab50d069a3cf335

sudoで環境変数を引き継ぎたい http://mikio.github.io/article/2012/03/10_sudo.html

が、何を試しても一向にcargoのパスが引き継がれない。

仕方ないのでルートユーザーでもrustupを入れてしまう。(同様なので方法は割愛)

$ su -
# rustupのインストールと設定

ちなみにパスワードは「vagrant」。

そしてそのままルートユーザーで以下を実行すると、80ポートで起動する。

# ROCKET_ENV=staging cargo run

🔧  Configured for staging.
    => listening: 0.0.0.0:80
    => logging: Normal
🛰  Mounting '/':
    => GET /
🚀  Rocket has launched from http://0.0.0.0:80...

ホストマシンからブラウザでアクセスしてみるとちゃんと動いている。 http://192.168.33.13

GET /:
    => Matched: GET /
    => Outcome: Succcess
    => Response succeeded.
GET /favicon.ico:
    => Error: No matching routes for GET /favicon.ico.
    => Warning: Responding with 404 Not Found catcher.
    => Response succeeded.

ちなみにデフォルトの8000ポートだと以下のように指定してもアクセスできなかった。
http://192.168.33.13:8000/

ファイアウォールを切ったので問題ないと思ったのだが、何か設定がマズイのかもしれない。

終わり

Linuxとか環境構築とかあんまり経験ないので思ったよりもずっとしんどかった。 まぁしかしVagrantとか楽でいいなと思った。

とりあえず以下は解決したい課題。

  • ルートユーザで実行しちゃってる。(本番環境なら大問題)
  • 8000ポートでホストマシンから接続できるように。
  • Linuxとか詳しくなる。