読者です 読者をやめる 読者になる 読者になる

👾 & ⌚️ (LT) | try! Swift Tokyo 2017 #tryswiftconf Day2-16 聞き起こし

twitter.com

このトークでは、watchOS 3上で動作するゲーム開発の手法についてお伝えします。最新デバイスで動く、懐かしのゲームに思いを馳せてみてください。

👾 & ⌚️

古くから人は時計上でゲームをしようとしてきました。

f:id:niwatako:20170303181944j:plain

f:id:niwatako:20170303181945j:plain

f:id:niwatako:20170303182044j:plain

ポケモンが出たのも記憶にあたらしいのではないでしょうか

f:id:niwatako:20170303182045j:plain

水中で水中面を遊ぶこともできます(水に使っているゲーム中のAppleWatch)。

これがVR

Objective C+で

続きはtry! Objective+Cで f:id:niwatako:20170303182139j:plain

f:id:niwatako:20170303182140j:plain

エミュレーターからテクスチャを受け取ってSpriteKitで描画

f:id:niwatako:20170303182159j:plain

エミュレーターの音声をAppleWatchで再生させる

f:id:niwatako:20170303182226j:plain

多くのセンサーが追加されました。

でもGestureRecognizerでTouch UPしかとれませんでした。

そこでめちゃくちゃ短いロングプレスを取得することで擬似的にタッチダウンとしました。

f:id:niwatako:20170303184007j:plain

マルチタッチができないのでデジタルクラウンでBダッシュ

これが2017年に書かれたコードです。

f:id:niwatako:20170303184048j:plain

ファミコンエミュレーターをラップしたライブラリも作成したのでCarthageで誰でも開発できます。

f:id:niwatako:20170303183928j:plain

大きな学びを得ました。

f:id:niwatako:20170303183854j:plain

AppleWatchにファミコン程度なら60fpsで描画できましたが、マリオのような入力の激しいゲームをすることは想定されていないようです。

皆さんよりポケモンライフをお送り下さい!

f:id:niwatako:20170303183841j:plain

なぜ登るのか (LT) | try! Swift Tokyo 2017 #tryswiftconf Day2-17 聞き起こし

twitter.com

2010年の東京オリンピックでも正式種目に選ばれたボルダリング。今日は、ボルダリングは Swiftエンジニアにとって最適なスポーツであることを紹介したいと思います。今まで試したこともない人も、是非tryしてみてください。

なぜ登るのか

f:id:niwatako:20170303182637j:plain

f:id:niwatako:20170303182638j:plain

タクシーを呼びたいときはこちら、Uberより安く呼べます、JapanTaxi

f:id:niwatako:20170303182739j:plain

f:id:niwatako:20170303182750j:plain

様々なクライムが有ります。ボルダリング、。。。その他

今日はボルダリングについてお話します。

f:id:niwatako:20170303182815j:plain

ロープなどのツールを使わず壁や岩を登っていくスポーツです。

f:id:niwatako:20170303182838j:plain

様々な色の付いたホールドを持って登っていくわけです。

同じ色が幾つかについています。スタートのホールドに手を置きます。それから、選ばれたマークされたホールドを掴みながら登っていきます。

両手をゴールのホールドにタッチすると完了です。

f:id:niwatako:20170303182923j:plain

2020年、オリンピックで競技種目に指定されます

f:id:niwatako:20170303182943j:plain

おすすめする理由は

f:id:niwatako:20170303182957j:plain

体育の授業でバスケットをしたと思います。 そのボールを渡しにはパスしないで?なんてことを考えたことはないですか?私はスポーツが苦手だったんです。

f:id:niwatako:20170303183026j:plain

こうしたスポーツはメンバーのレベルが同じである必要があります。

でもボルダリングは違いました。一つの壁に難易度の異なるコースが混ざっているので、初心者であれば初心者コース、上級者なら上級者コースを選んで昇ることができます。

レベルが違っても同じ壁で楽しめるのです。

これが第一の理由。

そして、もう一つの理由は、もし登れなかった時どうなるかということですね。人はそれぞれ得意なことが違います。ボルダリングは昇ることが得意なところが役に立ちます。柔軟性が高い、筋肉が有る、ジャンプ力がある、など。ひとそれぞれソリューションが違います。

自分にあったソリューションを考え出すのが面白い時間になります。

これが2つ目の理由です。

そして、ボルダリングは一人で出来るスポーツです。

f:id:niwatako:20170303183237j:plain

あるいはグループで登ったり競ったりもできます。一人でも

f:id:niwatako:20170303183256j:plain

Swiftに重なりませんか?初心者でも上級者でも多のチムことができます。

そしてここ2日間、私たちも素晴らしいアイディアを聞かせていただくことができました。情報共有もできました。でも同じ形で技術に挑むことはない?かもしれません。制限や条件は人それぞれです。それに合わせてソリューションを考える必要があります。

それぞれのソリューションを状況に合わせて作るところが面白いところです

そして一人で働くことも有りますよね。家で仕事につくこともあります。そして、ときに問題に直面してStackOverFlowで助けられたり助からなかったりもします。さきほどもありましたがAppleのバグとも対応しなければなりません。

こういった体験を共感できるのです。それはボルダリングと一緒です。

f:id:niwatako:20170303183505j:plain

Swiftが好きな方はボルダリングも好きだと思います。是非挑戦してみて下さい。

Q&A

冬で寒いですけど、東京エリア、この周辺でボルダリングするとしたらどこへ行ったら良いですか?

インドアボルダリングが良いと思いますね。冬は。新宿のレックスジムにはFloatingRoofがある。おもしろい。ホールドに飛びついたりすると面白いです。一度チェックしてみて下さい。

Swiftでのエラーハンドリングとエラー耐性についての教訓 | try! Swift Tokyo 2017 #tryswiftconf Day2-15 聞き起こし

twitter.com

ソフトウェアを書いているとき、私たちはハッピーパス(例外やエラーが発生しない正常系のこと)についてはちゃんと考慮する一方、潜在的な障害についての考慮はおろそかになりがちです。しかしアプリが考えていたよりも長く、いろいろな状況で使われるようになると、コードはより複雑に分岐します。この講演では、あなたのアプリのエラー耐性を高めて少しでも'アンハッピーパス'がユーザーやアプリを保守する人たちにもたらす憂鬱を軽減するために、Lineで遭遇した様々なタイプのエラーに対処するために学んだ教訓を紹介します。

Swiftでのエラーハンドリングとエラー耐性についての教訓

f:id:niwatako:20170303175302j:plain

Swiftのエラーについてお話したいと思います。

Error型ではなくて、誤作動しそう、理想的コードパスではないもの

f:id:niwatako:20170303175336j:plain

  • 安定的、正常に動作するものを求めている。常にそうでありたい
    • 改善や新機能を早く出せる
  • 予期せぬ不具合から復帰して影響を最小限にしたい
    • DBからユーザーの一部が読めない時、諦めてクラッシュしたくない。
    • ユーザーがエラーを避けられない場合は特に注意したい
    • 起動してビューを表示するのは一つのよくある例ですが、自動で同期するなどの処理ではなおさら大事になります。ひょっとするとDoSのような状態に陥るかもしれないです。
  • サポートに電話して、再インストールしてくださいというのも、大事なデータを失うかもしれません

ただしコードを書く

維持できる、テスト可能なコードをどう書くか、誤作動しないように。

今日は簡単に入力について話します。

エラーを防ぐにはすべての入力を扱える必要があります。

  • 明示的
    • 読み手に目立つ、意図を明示的に伝える
    • 関数パラメータ
    • self(暗黙的に渡される引数、まだ明示的な部類と言って良いでしょう)
  • 暗黙的
    • 状態

明示的な例

f:id:niwatako:20170303175651j:plain

暗黙的な例

f:id:niwatako:20170303175708j:plain

状態、グローバル変数、Singleton。関数がこれらに依存すると、インプットは同一の明示的インプットでも、結果が異なります。これらに依存しないものはピュアファンクションといいます。

ピュアをfunctionに指定できるようにしたいという要望もSwiftに寄せられています。

状態

f:id:niwatako:20170303175825j:plain

ある時間で実行されているコード 命令形コードの順番によって定義される。 暗黙的だが明示的にすることも出来る。コメントで、〜の前に呼ばないと大変、など。 間違った順番でコンパイルできないようにコードを書くことができます。

f:id:niwatako:20170303175927j:plain

print文を独立して実行していきます。

スレッドが異なったパターンで降り混ざるに連れ、実行順序の状態が増幅します。

f:id:niwatako:20170303175959j:plain

3つの外リームに別れました。3の階乗パターンが有ります。

同時並行なしの例

f:id:niwatako:20170303180032j:plain

トップダウンの順番になっています。

あたいの一部は他の関数で呼ぶために引数として呼ばれている。

関係がコンパイラによって矯正されている。

1行目にlet c を置けません。aの値がないからです。

関数の呼び出しが何故ここにあるのでしょうか。入出力がありません。

  • リアル世界の状態
    • ファイルシステムやネットワーク
    • 以前のコードの実効出力
      • バグっていたコード
      • 忘れられたしよう

皆さんのコードに起因している。負の数以外を格納していると想定したが、過去のすべてのバージョンでそうだったか。誰かが-1やnullを入れて同期が取れていないことを示そうとしなかったか、バグが有ったかもしれない、今後アウトプットデータ上で実行できるのか。 ユーザーが直接弄ったデータを扱えるようにしておきたいか。

こういった状態の変更は無計画にやるべきではない。

きせかえ機能があります。

f:id:niwatako:20170303180326j:plain

今使われているきせかえテーマの設定を移動させる。設定はUserdefaultに格納されている。コードを追加して、Update後初めて起動した時に取り出して新しいフォーマットで格納するということをしました。しかしすぐ問題があることがわかりました。

アプリ起動時はDefaultテーマで、立ち上げると一つ前のテーマに戻ってしまいます。

テーマのサブシステムが私のコードの前に初期化されてしまいました。

でも次からの起動では移行したデータを読み出してきちんと起動してくれました。

曖昧な依存関係に起因している。

f:id:niwatako:20170303180523j:plain

一つのやり方は、2者の関係を肩を使って明示的にすることです。

方のインスタンスがないなら入力としてその方を必要とする者を呼び出せない。

特定の状態への遷移を表す方を用意し、その型を受け取ることで、その型を前提とする定義ができます。

f:id:niwatako:20170303180630j:plain

状態が発生した時にこのインスタンスを作って渡せばよいということになります。

少し話題を変えて、Swiftの実際のError型の話をしたいと思います。

f:id:niwatako:20170303180708j:plain

f:id:niwatako:20170303180723j:plain

大抵はOptionalが正解になります。

f:id:niwatako:20170303180803j:plain

よく知られる例としては壊れたDBにアクセスしたときやIOが落ちたときです。エラーを捉えてなんとかしようよりは、Happyパスを書くことに向いています。

私が思うに殆どのSwiftプログラマはカーソルを後戻りさせたりthrowしたりは嫌がると思います。

errorはそんなに頻繁に起きないのでいちいち考えたくないということ織田と思います。

でも起きると結構酷いのでその時の処理をabortすることになります。

なのでその時どうするかちゃんと設定する必要があります。do {} catch{}を使うことになります。そんなに頻繁に起きる・起こすものではいでしょう。

f:id:niwatako:20170303180959j:plain

早めに戻ってエラーをログすることになります。でも大抵はこれを見るとDBから来る、当然正常処理されると、OptionalのUnWrapを利用するんです。そこでthrowを付けました。

こちらの場合だと、サーバレスポンスを処理するようなものです。このような理想的状況がない場合、API利用者が最終的にOptionalに変換することになると思います。

Errorを使おうということにしたのでここには密結合が有りますね?

Error型はErrorハンドリングがその型と密結合している時に有用ということがわかります。

全体のコンテキストを知りたい。このような状況がError型が適している状況。

f:id:niwatako:20170303181243j:plain

コードのどこを明示的にモデリングしないといけないか

エラー入力や入力値を見落とすことがなくなるでしょう。

無関心ではいられないようなコードを見つけましょう。コードを堅牢に書く。

Optionalは情報量が少ない発生頻度がやや起こりがちなエラーに使いましょう。

Errorは情報量が多い場合や稀、複数の箇所から起きうる、コンテキスト依存のとき

f:id:niwatako:20170303181410j:plain

Q&A

たとえばFatalErrorを使う状況はどうしようもない、クラッシュしか無い物を使うことにどう思いますか

具体例がないと説明が難しいが私のコードでは!を使うことも有りますね。 ただ、単に無視するよりはどちらかと言うと探っていきたい、何故そういう状態になっているか。

(Resolve?Result?を使っているかとか?通訳に入っていなかったので質問不明)

Resolvを使っています。一部コードに最初のサーバーレスポンスとか。でもあまり機能性が高いかというとそうではないかなと思っています。もしでんぱさせるなら、もっとファンクショナルなアプローチになるかもしれません。