シンクロ・フード エンジニアブログ

飲食店.COMを運営する、株式会社シンクロ・フードの技術ブログです

90名で使っていた無料版Slackから有料のスタンダードプランにアップグレードする際にやったこと

こんにちは。最近は動画制作を勉強している、シンクロ・フードの大久保です。

今更なのですが、弊社ではつい最近、Slackを有料のスタンダードプランにアップグレードしました。

すでにスタンダードでSlackを利用している企業は多いと思うのですが、弊社のように「無料版でケチケチ使っていたら、どんどん社員が増えていき、気づいたら90人くらいになっていて、有料化した場合の月額費用がすごいことになってちょっとアップグレードに勇気がいる…」という状態に陥っている企業もいるのではないでしょうか…?

参考になるかわかりませんが、以下に弊社がフリープランからスタンダードプランに切り替える際にやったことを紹介していきたいと思います。

Slack無料版(フリープラン)の課題

まず、Slackを無料で使い続けることの課題を整理します。 弊社が感じていた課題は、この2つでした。

メッセージが10000件で消えてしまう&検索不可能になる

数人で使う分には大きな問題ではなかったのですが、90人規模で使うと、本当にあっという間にメッセージが無くなってしまいます。 この状況だと、くだらないちょっとしたやりとりや、あとで参照しそうな重要なやりとりはSlackで行えない、という本末転倒な問題が発生し、コミュニケーションが阻害されます。 スダンダードプランにアップグレードする一番のモチベーションは、この課題解決でした。

※尚、スタンダードプランにアップグレードすることで、フリープラン時に消えてしまったメッセージは復活します!

連携できるアプリケーションの数に制限がある

連携できるアプリケーションの数も10という制限があり、ちまちま連携するアプリケーションを選別したりしていました。 実際は、ガンガン外部アプリケーションと連携して、生産性を上げるべきですよね。

スタンダードプランで使える便利機能が使えない…

スタンダードプランに変更することで使えるようになる機能はいくつかあるのですが、弊社で使いたかった機能は以下の2つです。

  • 画面共有機能
  • 共有チャンネルやシングルチャンネルゲストなどの外部接続機能

基本的には、遠方拠点とのやりとりや、外部の関連プレイヤーとのやりとりもSlackで行うようにしたい、という欲求です。 こちらもスタンダードプランに上げることで、使えるようになります。

スタンダードプランに上げるために取り組んだこと

スタンダードプラン対象範囲を決める

弊社の場合、エンジニアやデザイナー以外に、営業メンバー・経理・総務などのバックオフィスメンバー、インターン・アルバイトの方など、社内にいるすべての人間がSlackを利用していました。 具体的には、エンジニア・デザイナーが約20名、営業・管理部門が約50名、インターン・アルバイトが約20名、合計90名ほどの利用者がいました。 その中には、ほんの少ししか活用していないメンバーもいるため、本当に全員スタンダードプランにすべきなのか…という点を検討する必要がありました。

部署によってはSlackを使わなくても良いのでは…みたいなことも頭をよぎりましたが、全社的な生産性を考え、正社員は全員スタンダードプランとし、インターン・アルバイトの方は、無料のアカウントで使ってもらうこととなりました。

インターン・アルバイトをシングルチャンネルゲストとする

インターン・アルバイトの方を無料アカウントにしつつ社員はスタンダードプランにする方法について検討した結果、インターン・アルバイトの方は、スタンダードプランで利用できる、シングルチャンネルゲストになってもらうことにしました。

シングルチャンネルゲストとは、1つのチャンネルのみアクセスできるユーザーで、有効期限の設定も可能です。シングルチャンネルゲストは課金されません。

get.slack.help

具体的な対応の流れは以下の通りです。

  1. インターン・アルバイトの方を一旦、メンバー一覧から「アカウント解除」を選択する
  2. Slackのスタンダードプラン利用の手続きを実施→適用
  3. メンバー一覧の解除済ユーザーから「ゲストとして有効化する」を選択する(この時、このユーザーがアクセス可能なチャンネルを1つ選択します)

一時的にSlackを利用できなくなってしまうため、事前の調整が必要です。

この対応をすることで、費用をだいぶ抑えることができました。

会社への説得

弊社では割とすんなり受け入れましたが、100名前後になると、年間100万円近い費用になりますので、それなりの説明は必要だと思います。 私の場合は、先ほど挙げた現状の課題を説明することで、理解を得ることができました。

社員への説明

せっかくお金を払ったので、活用度を上げる取り組みをする必要があります。 こちらはまだあまりできていないのですが、特に非エンジニアの方に、スタンダードプランでできることを説明する必要があります。 一部ユーザーについては、外部アプリ連携や画面共有などを活用されていない状況のため、こちらは定期的に有効な利用方法を紹介していく予定です。

以上が、弊社がSlackをスタンダードプランにアップグレードするまでの流れです。 もっと早くにしていても良かったな…とも思いますが、これから使い倒すことで取り返そうと思います。

シンクロ・フードはなんでもじゃぶじゃぶお金を使える環境ではありませんが、生産性向上については理解を得やすい会社だと思いますので、興味があるエンジニア・デザイナー・ディレクターの方は、是非ご応募ください!
特にWebディレクターさんはめちゃくちゃ募集しておりますので、興味があればお気軽にお問い合わせください!

www.synchro-food.co.jp

Drone CI で手軽に Docker コンテナで並列にジョブをぶん回す環境を構築した

基盤チームで CI 職人をやっている @fohte です。

今回は、Jenkins と独自ジョブスクリプトを用いたお手製 CI/CD 環境に無限のつらみが発生していたため、OSS の CI/CD ツールである Drone を使った CI/CD 環境に移行した話をします。

Drone とは?

Drone は、Go 言語で書かれた CI/CD 環境を提供する OSS ツールで、以下のような強みがあります。

  • YAML で設定を記述できる
  • 全てのジョブが Docker コンテナ上で動作する
  • master-agent 構成で無限にスケールアウトできる

また、比較的安くイマドキの Docker コンテナを使ったイミュータブルな CI/CD 環境を構築できるという強みもあり、特に CircleCI が大人の事情で使えないような場合に有力な選択肢になりうると思います。

YAML で設定を記述できる

Travis CI や CircleCI など、最近では CI/CD のジョブ設定は静的ファイルで管理することが一般的になっています。 Drone でも、ジョブの設定は YAML で書き、docker-compose の設定をベースとした構造で簡潔に記述することができます。

例として、実際に使っている設定の一部はこんな感じです。

pipeline:
  install-deps:
    image: ruby
    commands:
      - bundle install --jobs=4 --retry=3

  rubocop:
    image: ruby
    commands:
      - bundle exec rubocop

  mysql:
    image: mysql
    detach: true

  wait-mysql:
    image: jwilder/dockerize
    commands:
      - dockerize -wait tcp://mysql:3306 -timeout 30s

  run-tests:
    image: ruby
    commands:
      - bundle exec rspec -fd

  slack:
    image: plugins/slack
    channel: ci
    secrets:
      - slack_webhook
    when:
      status:
        - failure

全てのジョブが Docker コンテナ上で動作する

Drone は、対象の git リポジトリの clone から設定したビルドやテスト、そしてビルド結果の通知までの全てのジョブが Docker コンテナ上で動作します。

CI でも Docker コンテナを用いれば、毎回新規に用意されたクリーンな環境でジョブを実行できますし、ローカルでも同等の環境を使ったテストを実行することが容易になります。

他にもこの特性が活かされている例として、Drone プラグインが挙げられます。

Drone プラグインは、ファイルのキャッシュや Docker イメージの build, push といった汎用的なジョブを提供するもので、その実態はただの Docker イメージです。 これにより、Drone プラグイン自体も単体でテストしやすく、かつ Drone 外の環境でも簡単に利用することができます。

master-agent 構成で無限にスケールアウトできる

Drone は、Web UI を提供したり、実行待ちのジョブを agent に振り分けたりする master と、実際にジョブを実行する agent からなる master-agent 構成になっています。

基本的な流れは以下のようになっています。

f:id:Fohte:20180910183509p:plain

agent は起動時に自動的に master に接続し、master は接続されている agent 複数台に分散してジョブを配置します。
単純に agent の台数を増やせば、master はその分だけ自動的に並列で実行するようにしてくれるので、非常に楽に分散実行する環境を整えられます。

Drone を AWS ECS で構築する

Drone は、master (server), agent 共に Docker イメージが提供されており、それを用いることで簡単に構築できます。

公式のドキュメントでは、docker-compose でそれらの Docker イメージを使って Drone の環境を構築する方法が紹介されており、手元で試してみることも容易になっています。

今回は、1 ヶ月間に数百回の CI ジョブが実行されることを想定しているため、Drone agent を状況に応じてスケールすることを見据え、 docker-compose は用いずに AWS ECS 上に構築することにしました。

インフラ構成

弊社では基本的にインフラを AWS 上に構築していて知見も豊富なため、今回もそれに則り AWS 上に構築しました。

f:id:Fohte:20180906153721p:plain

Drone agent は管理やスケールのしやすさから ECS で立てるようにし、Drone server は (現時点では) スケールする必要がないため、直接 EC2 インスタンス上で Docker コンテナを動かすようにしています。

また、ECR は社内で用いるプライベートな Docker イメージを保持し、それを CI でも用いるために使っており、S3 はキャッシュや成果物の保存先として利用しています。

agent コンテナの配置戦略

今回 Drone を構築する上で最も悩ましかった点が、Drone agent を実行するコンテナの配置戦略でした。

今回は、AWS ECS を利用し、EC2 インスタンス上で複数の agent コンテナを動かしています。 最近東京リージョンでも Fargate がサービス開始しましたが、訳あって EC2 バックエンドを用いています。

Fargate か EC2 バックエンドか

今回は EC2 バックエンドを用いましたが、Fargate も非常に魅力的で、どちらを採用するかはなかなか決めあぐねていました。

Fargate と EC2 バックエンドは、それぞれ以下のような長所・短所があります。

Fargate EC2
データ永続性
料金の安さ
スケールの容易さ
運用コストの低さ

Fargate は、運用コストは最小限に無限にスケールできることが魅力的ではありますが、EC2 バックエンドに比べると、データの永続化が Fargate 単体では行えないことや、同等の CPU・メモリ構成でも 2 倍弱の料金がかかってしまうことが懸念点でした。

記事執筆時点では、コンテナごと *1 にストレージは用意されているものの、EBS のような外部ストレージがアタッチできず、停止するとデータが失われてしまいます。
この制約により、CI ジョブ内で用いる Docker イメージは agent コンテナを終了・起動するたびに新規に build や pull されることになってしまい、CI ジョブが遅くなることが Fargate を用いる上での一番の懸念点でした。

アプリケーションの依存ライブラリなどの依存ファイルに関しては、S3 にキャッシュとして置いておき、毎回キャッシュをダウンロードするという戦略が取れますが、Fargate の仕組み的に、Docker イメージに関してはそのような戦略を取ることが難しいように考えています。

運用し始めてから発覚したこと

EBS の I/O が多すぎて I/O クレジットが足りなくなる

現状の構成では、ECS のコンテナインスタンス (= EC2 インスタンス) はオートスケーリングせずに 1 台のみを用意しています。*2

その EC2 インスタンスのルートボリュームとして 10 GiB にも満たないサイズの EBS (gp2) をアタッチしていますが、CI ジョブが走っている間は EBS への I/O が 1,500-2,000 IOPS ほどあり、想定よりも遥かに多くなっていました。 アタッチしている EBS はベースラインパフォーマンスが 100 IOPS であるため、常にこれを超えてバーストされており、多くの I/O クレジットを消費していました。

f:id:Fohte:20180918172221p:plain
頻繁に CI ジョブが走っているときのコンテナインスタンスに紐づけている EBS の I/O クレジット (急激に回復しているところは EBS の容量を増やしています)

これは、CI ジョブでテストのために並列数分だけ立てているデータベースや、依存パッケージのダウンロードによって発生する頻繁な I/O 操作が原因でした。

解決策としては、コンテナインスタンスにインスタンスストアが用意されているインスタンスタイプを選択し、頻繁に行われる I/O 操作の先をインスタンスストアに向けることで、頻繁な I/O 操作に耐えられるようにしました。
具体的には、この I/O 操作はすべて Docker のデータボリューム内で行われたものだったため、/var/lib/docker/volumes をインスタンスストア内の任意のディレクトリに bind-mount することで解決しています。*3

今回はもともと C5 インスタンスを用いていたため C5d インスタンスに変更しましたが、大幅にコストが上がることはなく、スムースに解消することができました。
結論として、CI の worker (Drone の場合は agent) のホストにはインスタンスストアが用意されているインスタンスタイプを選択することがおすすめです。

Drone の所感

インフラ面で考えることは少なくありませんでしたが、小規模な CI サーバーを立てる場合は Docker コンテナを起動するだけで良く、敷居は比較的低いように感じました。

Docker コンテナでできることであればどのような用途でも柔軟に使うことができますし、Web UI も単純明快で扱いやすく、そして CI/CD としての役割を十分に果たしてくれるため、開発者の方々にも好評価でした。

まとめ

今回は、Drone の紹介と、それを構築した話から、構築・運用する上で課題となった点、そしてそれらをどのように解決したかという話をしました。

これからも継続的に今回構築した環境を改善していき、ガンガン CI/CD を回していける環境を整えていきます。


シンクロ・フードではエンジニアを募集しています。ご興味のある方は以下よりご連絡ください!

www.synchro-food.co.jp

*1:厳密にはタスクごと

*2:運用が安定し、CI の需要や負荷を計測した後に、必要であればオートスケーリングする予定です。

*3:初めは bind-mount ではなくインスタンスストア内に用意したディレクトリにシンボリックリンクを貼っていたのですが、シンボリックリンクでは Docker がデータボリュームを削除できないという問題があったため、bind-mount で回避しています。この問題に関しては issue が上がっている (moby/moby#33800) ので、そちらを参考にしてください。

builderscon tokyo 2018に参加してサービス開発への知見を深めた話

こんにちは、サービスチームの日下です。

9月6日〜9月8日にかけて開催された『builderscon tokyo 2018』に参加してきました!
buildersconは技術的な制約のない、様々なテーマのトークを聞けるとても濃密な内容のカンファレンスです。

buildersconではトークに関して技術的な制約はありません。特定のプログラミング言語や技術スタックによるくくりも設けません。 必要なのは技術者達に刺激を与えワクワクさせてくれるアイデアのみです。
builderscon.io

この記事では、私が聞いた発表の中でも今興味を持っている「サービス開発」に関わるものを御紹介します。

パスワードレスなユーザー認証時代を迎えるためにサービス開発者がしなければならないこと

builderscon.io
speakerdeck.com

パスワードを使用しないユーザー認証方法、「パスワードレス」の現状・課題についての発表です。

そもそもパスワードを使用した認証は何が問題でしょうか?パスワードは特定デバイスに依存しない最強の認証方式ではないのでしょうか?
しかし、ユーザーはパスワードに簡単な文字列を設定し、使い回してしまう事があります。さらにはパスワードを要求するサービス側が、文字数を制限する等の制約をかけてしまう事もあります。
これらの問題は、パスワードがユーザーへ負担をかけているという事であり解決すべきものです。そんな状況だからこそ「パスワードレス」は来たるべき未来となっています。

実際のパスワードレスの現状を見てみると、実現するためにFIDO 2.0という仕様が策定されています。また、Web仕様としてWebAuthn APIが存在します。
このWebAuthn APIを実装したデモサイトwebauthn.orgを使用した解説も発表の中で行われました。

ただ、パスワードレスを実現しても我々サービス開発者が考えなければならない事はあります。それは既にパスワードを使用している既存サービスへの対応であったり、パスワードを使用しない事によるユーザー体験への変化にどう対応するか等様々です。

弊社のサービスにもパスワードレスの波がやってきた時に、どういう対応が求められるのか考えさせられる発表でした。

Webサービスにて200週連続で新機能をリリースする舞台裏

builderscon.io
speakerdeck.com

200週連続リリースという偉業を成し遂げられた訳、これからどうするのかという内容でした。

対象サービスMackerelはとても小さなサービスとしてスタートし、顧客獲得の大きな武器として連続リリースがあったそうです。
実際、1つのサービスに200週連続で「新機能」をリリースするのは驚異的だと思いますし、とても強みだと感じます。

実現できた理由として、連続リリースをチームの最重要事項にするのはもちろん、エンジニアに余力を持たせる(自主的な活動ができる余地を残す)、チームのスキルバランスを常に把握するなどの様々な工夫が施されていたのが印象的でした。
また、個人的にはプロダクトオーナーが3年の長期ロードマップ、四半期ごとの中期ロードマップを作成している事が凄い重要な事だと思いました。200週の連続リリースを達成してもサービスの方向性がブレないのは、そのような導きがあってこそだと思います。

200週連続リリースを機に連続リリースは終了するそうですが、より価値に集中するためらしく、サービスの成長への熱意がとても感じられる発表でした。

ボクが考える i18n の未来

builderscon.io
speakerdeck.com

i18nの現状・問題について解説後、次世代のi18n対応について考察する内容です。

i18n対応は面倒ですが、ハードコーディングをしていると後に大変な事になったり、考えていないUIデザインをしていると再設計が必要になったりしてしまいます。

i18nは現状プログラミング、フレームワーク、文字コード、ライブラリ、フォント、絵文字に至るまで幅広くサポートされるようになってきています。
しかし、発表中にも言及された以下の記事のように「完璧」なi18n対応はとてもとても難しいものです。 qiita.com また、プロジェクト固有のエッジケースがある場合は開発者が頑張るしかなく、i18n対応自体が開発者を疲弊させてしまう問題があります。

そこで、開発にフォーカスした次世代のi18nのソリューションについての考察が発表されていました。
次世代のi18n対応にはUsability、Maintainability、Testability、Extendability、Integrityの5つの要素が不可欠としています。
その要素を満たす解決策として、提案されていた内容は以下の2つです。

  1. i18nのSaaS
  2. i18nフレームワーク

特に具体的に説明されていたのがi18nフレームワークでした。
i18nフレームワークは、要求に応じて解決手段が異なるプログレッシブフレームワークであるべきで、問題に応じて公式のライブラリが用意されているべきとしています。また、アーキテクチャもプラグインシステムとして機能を自由に拡張できるものが良いとしていました。
確かに多種多様な対応が要求されるi18n対応では、ビジネスの段階や問題に応じて柔軟な対応ができるべきだと私も思います。まだ考察の段階ではありますが、とても実現が望まれるアイデアなのではないかと感じました。

弊社もFoodJobJapan等の多言語対応のサービスを開発しており、開発が進んでも辛くならないi18n対応について考える必要がありそうです。 foodjobjapan.com

おわりに

buildersconは公式サイトにもあるように、まさしく「知らなかった、を聞く」カンファレンスでした。
私が所属しているサービスチームで、今回聞いた内容を考慮に加えて開発をしていきたいと思います。

この記事ではサービス開発に関する発表を紹介しましたが、他にもTLS 1.3策定の話だったり、自作キーボードの話など多種多様な内容を聞くこともでき、とてもエキサイティングな体験でした。

buildersconは「知らなかった、を聞く」をテーマとした技術を愛する全てのギーク達のお祭りです。 builderscon.io


シンクロ・フードではbuildersconをはじめとするカンファレンスへの 参加費の支給・業務としての出席 を行っております。
技術を愛するbuildersの方々を絶賛募集しておりますので、ご興味のある方は以下よりご連絡ください!

www.synchro-food.co.jp

builderscon tokyo 2018 に参加してきました! (@fohte)

基盤チームで CI 職人をやっている @fohte です。

9 月 6 日 (金)、9 月 7 日 (土) に開催された builderscon tokyo 2018 に参加しました!

builderscon.io

今回は、個人的ベストスピーカー賞のいくつかのセッションをご紹介させていただきます。

セッション紹介

Algorithms in React

@koba04 さんによる、React の内部アーキテクチャである Stack (~ React 15) と Fiber (React 16 ~) に関するセッションでした。

Stack とは何か、Fiber とは何かを詳細に説明されており、名前しか聞いたことがなかった筆者にもすんなりと理解できる発表でした。

React 15 以前まで用いられていた Stack は、同期的に再帰的に ReactElement を探索して処理する構造で、途中で中断したり再開することが難しいという問題や、ツリーが大きくなると UI をブロッキングしてしまうといった問題がありました。

そこで、React 16 から採用された Fiber では render phase と commit phase が分けられており、render phase では非同期で処理が行われ、commit phase では同期的に処理が行われるようにしています。
そして、なるべく render phase で処理を行うようにすることで、Stack が抱えていた問題を解決しています。

また、Fiber のアーキテクチャを活かした Time Slicing や、React 17 で実装予定の Suspense と呼ばれる機能も、デモを用いながら紹介されていました。 デモが非常に実用的で分かりやすかったため、スライドや下記リポジトリをご参考ください。

React の内部は触れたことがなかったためほとんど知識がありませんでしたが、そんな筆者でも分かりやすく説明されており、React の内部も見てみようと思えるセッションでした。

lld − 開発ツールの主要コンポーネントの1つをスクラッチから作成した話

(スライドが見つかりませんでした。)

Turing Complete FM (以下 TCFM) というポッドキャストをされていることで著名な Rui Ueyama (@rui314) さんによる、Rui さんが作られた LLVM リンカである lld の設計思想などに関するセッションでした。

lld は 1 度作り直されており、その際に「複数のリンカを抽象化せずにそれぞれ実装していく」という方針に切り替えたそうです。
そこで、「リンカはそれぞれ異なる独立した仕様を持っているが、コードの重複を防ぐために抽象化した結果、あるリンカにだけ存在する機能と、また別のリンカにだけ存在する機能を同時に使うケースが発生し、実用上は存在しないケースについて考慮する必要が出てきて、完全に無駄」という話があり、これはなんでも抽象化したくなってしまう筆者にとって衝撃的な話でした。
また、「抽象化しないことによって抽象化によるパフォーマンスの低下をなくせる」といった話もまた自分の考えを改めるきっかけになりました。

「自分で良いと思ったことはアンチパターンであってもやってみるべき」ということで、実際に手を動かして、さらにそれで成功した方の発言はかなりの説得力がありました。

Rui さんの単独 TCFM のような感じで、非常に分かりやすいセッションでした。
「リンカとは何か」といったところから基礎的な部分から丁寧に分かりやすく説明されていて、低レイヤーにあまり詳しくない筆者にも話を理解でき、興味深く聴くことができました。

このセッションは、個人的ベストスピーカー賞でした。

高集積コンテナホスティングにおけるボトルネックとその解法

GMO ペパボの P 山 (@pyama86) さんによる、コンテナホスティングサービスのロリポップ!マネージドクラウドを運用するにつれて直面した課題と、それをいかにして乗り越えたか、という発表でした。

特に、strace でプロセスが発行するシステムコールをトレースし、perf でシステムコールのボトルネックをシンボルレベルまで確認する、といったボトルネックの調査方法は非常に参考になりました。

P 山さんも仰っていましたが、「コンテナはあくまでプロセスである」ということを改めて感じました。

筆者も規模は違えど似たような課題を抱えており、タイムリーで参考になるセッションでした。

ブログサービスのHTTPS化を支えたAWSで作るピタゴラスイッチ

はてなの @aereal さんによる、はてなブログの独自ドメインの HTTPS 配信環境をどのように構築したか、という発表でした。

Let's Encrypt はプログラマブルにアクセス可能で、自動的に TLS 証明書の発行・更新が行えるようになっています。 そこで、はてなブログではどのように自動化したのかということを詳細に解説されていました。

具体的な構成についてはスライドをご覧頂くとして、主に AWS Step Functions と Amazon DynamoDB の TTL Trigger を活用されていました。

Step Functions は任意の AWS Lambda を起動し、エラー処理も柔軟に行えるワークフローエンジンです。 はてなブログでは Lambda には状態を持たないようにし、Step Functions に状態をもたせることで、実行ステップ全容を把握しやすくしているとのことでした。

また、DynamoDB の TTL Trigger は、アイテムが期限切れになったときに任意の Lambda を起動するといった、pub/sub 方式を取ることができます。
証明書の更新タスクのようなバッチ処理は、あるタスクがエラーになったときなどに複雑になってしまいがちです。そこで、TTL Trigger を使ってある証明書の期限が切れたときに更新タスクを起動するようにすることで、単一のタスクに集中でき、処理単位が小さく、失敗も把握しやすくなったとのことでした。

大規模処理の戦略に関するベストプラクティスがうまく言語化されていて、深く共感できるセッションでした。

雑感

builderscon は今回が初めての参加でしたが、常に「同時刻に行われている他のセッションも聞きたいんだけどこっちも捨てがたい…」となってしまうほどに、興味深いセッションで目白押しでした。

聴講したどのセッションも多くの知見が得られ、非常に充実した 2 日間になりました。
体力的には疲れて 2 日目終了後にはヘトヘトでしたが、次回もぜひ参加したいと考えています!

iOSDC Japan 2018 に参加してきました

こんにちは、アプリチームの増山です。
8月30日(木) から 9月2日(日) にかけて開催された、iOSDC Japan 2018 というカンファレンスに参加してきました!
今回は参加したセッションの中でいくつか印象に残ったものをご紹介させていただきます。

f:id:hofzzy:20180904152246j:plain

Playground 駆動開発のすすめ

Playground で View をテストすることで、ビルド時間を短縮しデザイン調整のサイクルを高速に回そうという趣旨の内容でした。

Kickstarter でも提唱されている手法です。

Playground で View をテストするためには View を Embeded Framework 化する必要がありますが、既存プロジェクトに導入する場合は View の依存周りの解決が難しそうだなと感じました。
逆に新規で開発するプロジェクトに関して言えばこの Playground 駆動開発は検討する価値は十分にあるなと思いました。

MicroViewController で無限にスケールする iOS 開発

コンポーネント毎に ViewController を定義して画面を構成することで、ViewController のコードをスリム化し開発効率を向上させようという趣旨のセッションでした。

1 画面 1 ViewController という構成で開発をしていると、ViewController がすぐ肥大化したり、また複数人で開発している場合はコンフリクトやオーバーヘッドが発生します。
セッションで紹介されたこの方法は、これらの問題を根本から解決するような手法で非常に興味深く、また実際に会場からも「お〜」といった声が様々なところからあがっていました。

因みにこちらのセッションは今年のベストトーク賞に選出されていました。

差分計算アルゴリズムを用いた高速な UITableView 描画

Myer 法、Wu 法、Heckel 法といった差分計算アルゴリズムの紹介と、それらの計算アルゴリズムを使用した場合と reloadData で更新した場合とのパフォーマンスの比較について話されていました。

パフォーマンスの比較は全体の 10% を DELETE・INSERT するパターンと、30% を DELETE・INSERT するパターンとで比較を行っていました。
結果的には Heckel 法を使用した差分更新が一番パフォーマンスが高いという結果になっていましたが、Cell のレイアウトがシンプルな場合は reloadData した場合とであまり差はありませんでした。

実際弊社プロダクトでも UITableView の更新はほとんどを reloadData による更新を行っていますが、パフォーマンス上いまのところは問題は起きていません。
最初から差分計算を考えるのではなく、パフォーマンスに問題が起きたら差分計算を検討するくらいでいいのかなと思いました。

In-App Purchase 再考 -サーバーサイドエンジニアの運用経験と他決済手段との比較を添えて-

決済ゲートウェイの観点から In-App Purchase と他決済手段との比較を行い、その上で In-App Purchase を本当にプロダクトに導入すべきか?という内容に関するセッションでした。

In-App Purchase は他決済手段と比べてトランザクション周りの制御の複雑さやデバッグのしづらさなど、実装においてややハードルの高い印象がありますが、UX の観点から見ると決済完了までステップが簡潔なため、コンバージョンに直結しやすいというメリットがあります。
しかし、運用面やビジネス面の観点から In-App Purchase を考えたときには以下のデメリットが存在するということを話されていました。

  • 顧客から問い合わせに対して丁寧な対応ができない (iTunes Connect 上からユーザーの情報を照会することができないため)

  • 他決済手段と比べて手数料が高額である (In-App Purchase の場合は 30% の手数料を Apple へ支払う必要がある)

また、この他にも In-App Purchase という決済手段が iOS でしか利用できないという点も、マルチプラットフォームで運用しているサービスにとっては大きな足枷となるということも話されていました。

iOS で決済手段を導入するなら In-App Purchase と安易決めつけるのではなく、それぞれのメリット・デメリットを考えた上で検討をするのが良さそうです。

デバイス・OS バージョンの依存が少なく、メンテナンスしやすいビューを作る

なぜレイアウトが崩れるのかという問題に対する考察から、View を作る上での Good Practice・Bad Practice について話されていました。

レイアウトが崩れることとそれを未然に防ぐことが難しい理由として岸川さんは以下の三つを挙げていました。

  • アプリ内で管理する状態が多い

  • レイアウトが動的に変化する

  • 実行するまで分からない

しかしこれらの問題を解決するための銀の弾丸はなく、色々な方法を試しつつその中でその人にとっての Good Practice を選定していくのがベストだと仰っていました。
セッションでは岸川さんが実際のプロダクトで活用しているいくつかの Tips を紹介されていましたが、その中で IBDesinable / IBInspectable を活用した View の作り方が非常に参考になりました。
レイアウトをコードから定義することを極力減らし、また Storyboard のライブレンダリングを活用することでシミュレータの実行前にテストできる範囲を広げています。

また、これらの Tips を実践したサンプルアプリが以下のリポジトリに公開されています。

個人的にはアプリの View の作り方に関する正に教科書とも言えるような内容で一番印象に残ったセッションでした。

iOS アプリの開発速度を 70% 高速化したデバッグノウハウ

開発速度を向上させるための 5 つの Tips について紹介されていました。

個人的に印象に残ったのは LLDB を活用したデバッグ方法と動作確認の自動化でした。

前者については今までコードをデバッグするのにブレークポイントを貼り直してはリビルドを繰り返していたので、コールスタックを遡るという方法は目から鱗でした。

後者に関しては要するにテストを書くということと、そのためどういう設計をしていくべきかということでしたが、これについては弊社でも以前から色々試行錯誤しつつ取り組んでいた内容だっため非常に参考になりました。
発表では時間の都合上概要だけで詳細はほぼ割愛となっていましたが、公開されているスライド上には具体的にどのように導入していくのか、コードも交えて詳細に書かれていました。

また、サンプルアプリも以下のリポジトリに公開されており、テストをあまり書いたことのない人でも明日からテストを書きたくなると思えるようなセッションでした。

感想

どのセッションも内容の濃いものが多く、非常に勉強になりました。iOSDC 自体は初参加で勝手がわからず結構あたふたしていたのですが、ランチタイムやセッションとセッションの合間などに他の iOS エンジニアの方と情報交換を行ったりと、初参加ながらも 4 日間充実した時間を過ごせた気がします。来年も機会があれば是非参加したいと思います!


最後に現在開発しているプロダクトについて宣伝をさせて下さい。
現在弊社アプリチームでは、飲食店向け発注ツール PlaceOrders の iOS 版を開発しております。

f:id:hofzzy:20180904164727p:plain

iOS 版 PlaceOrders は今年の 7 月にリニューアルを行ったのですが、その際にデザインを刷新し Human Interface Guidelines に準拠することで直感的な UI を提供するようにしました。Human Interface Guidelines - Design - Apple Developer
また、iOS の独自の機能である State Restoration などに対応することで、途中で発注作業をストップしてしまったとしてもすぐに現状復帰できるような快適な操作性を追求しました。

今後も PlaceOrders は幅広く機能の追加を行っていきます。
皆様の周りで飲食店を経営されている方がいましたら是非 PlaceOrders を宣伝していただければと思います。

RubyKaigi 2018 に参加してきました (@n0_h0)

開発部サービスチームの日下(@n0_h0)です。

今回、初めて RubyKaigi に参加してきました!
この記事では、印象に残ったセッションを3つご紹介いたします。

弊社からは2人参加しており、もう1つのレポート記事は以下のリンクになります。

セッション紹介

bancor: Token economy made with Ruby

@kurotaky さんによる Bancor Protocol に関するセッションです。

暗号通貨等のトークンは、マイナーなものほど売りたい時に買手が見つからない流動性リスクという問題があります。
そこで、トークンの価格決定を自動化することで流動性リスクを解決しようとしているのが Bancor Protocol です。

より詳細な説明に関しては、スライドにも挙げられていました以下の記事に書かれています。

しかし、Bancor Protocol を実際にブロックチェーン上で試してみるにはインフラの問題や学習コストの高さ等のハードルがあります。
そこで、Bancor Protocol はただのプロトコルですので、シミュレーションを行える bancor gem を作成されており、デモも行われました。
実装を読んでみると、結構シンプルだったのが興味深かったです。

Hijacking Ruby Syntax in Ruby

@joker1007 さんと @tagomoris さんのお二人によるセッションです。

BindingTracePointRefinements 等を使用したメタプログラミングの力を紹介されていました。

特に、TracePoint と Binding を使用する事で任意のコード中の変数を上書きすることが出来るというのは強烈だと感じました。
また、メタプログラミングの力を行使するだけではなく、Refinements を使用することで安全に利用できる gem を作られていたのは本当に凄いと思います。

個人的には、1番 Ruby の大いなる力を感じることのできる発表で、とても面白かったです。

How to get the dark power from ISeq

発表資料

@youchan さんによる ISeq の可能性を探求するセッションです。

ISeq とはパーサー&コンパイラ、RubyVM の中間に位置するものです。
Ruby のコードはパーサーによって解釈されて ISeq にコンパイルされ、RubyVM によって実行されます。
ISeq は内部APIとして扱われており、ドキュメント化されていません。

しかし、ISeq の仕様をドキュメント化する事ができれば、他の言語で作成されたコードを ISeq バイナリ形式に変換することで、RubyVM で動かすことができるようになります。

実際、@youchan さんが ISeq Builder というものを作成されており、brainfxck コンパイラのデモが行われました。
有効に使うことで Ruby の方言を作れるのではないか等、とても面白い提案をされており聞いていてワクワクするセッションでした。

おわりに

Rubyist の熱気を肌で感じる3日間でした。
同時に、自分の力不足による危機感も感じ、まだまだ勉強していきたいです。


シンクロ・フードでは RubyKaigi は出張として扱っており 参加費、交通費、宿泊費の会社負担、土曜日の休日出勤扱い を行っております。
Rubyist を絶賛募集しておりますので、ご興味のある方は以下よりご連絡ください!

RubyKaigi 2018 に参加してきました (@fohte)

基盤チームの川井 (@fohte) です。

2018 年 5 月 31 日 (木) 〜 6 月 2 日 (土) に仙台で開催された RubyKaigi 2018 に業務として参加してきました。
弊社はスポンサー枠ではありませんが、出張として宿泊費や交通費を負担していただいて参加しました。

今回は、印象に残ったセッションと、個人的に興味があった型にまつわるセッションについてご紹介します。

セッション紹介

Day 1 Keynote「箴言 Proverbs」

Matz ことまつもとゆきひろさんのセッションです。 今回は「ことわざについて話す」ということで、プログラミングをことわざで例えた話が中心でした。

初めに紹介されていた「名は体を表す」は、つまり命名は重要であるということです。
物事を十分に理解すれば命名が容易になることがある、ということを話されていて、なるほどと感心しました。

また、Ruby 2.5 で導入された Kernel#yield_self は何がしたいのかを表現しておらず、悪い例であると話されていました。
(これは考え直しましょうというチケット #14594 があり、alias として then を追加する変更が Matz によって発表前日に commit されたそうです。5 年ぶりの commit らしい。)

質疑応答の際に Ruby の型に関する質問があり、型があることで助かるケースはあるが、Ruby の言語仕様として型宣言が入ることはないと名言されておりました。

A practical type system for Ruby at Stripe.

Stripe 社内部で用いられている Sorbet という Ruby の type checker についてのセッションでした。

Sorbet は記事執筆時点では公開されていませんが、Web 上で実際に試せるページが用意されています。

Sorbet は C++ 製なため非常に高速で、社内では好評らしいです。 また、近々 OSS として公開する予定であり、公開時には 公式ブログ で通知するとのことでした。

Ruby Programming with Type Checking

発表者の @soutaro さんが製作されている Steep という Ruby の type checker についてのセッションでした。

Steep は Sorbet とは異なるアプローチをとっており、Sorbet は Ruby コード上で型を宣言しますが、Steep は専用の構文を用いた型宣言ファイルを用意するかコメントで型注釈をします。
また Steep は Ruby で実装されているため Sorbet よりも低速ですが、Ruby 2.6 で導入される予定の MJIT で高速化することを期待していると話されていました。

既存のプロジェクトに導入する際などに便利な型定義ファイルの雛形を生成する steep scaffold コマンドも用意されています。

しかし、ライブラリの型宣言はまだ自分で書いていく必要があったり、Hash の構造の型宣言ができなかったり、動的に定義されるメソッドは型チェックを行えないなどの問題があるとのことでした。

Type Profiler: An analysis to guess type signatures

Ruby commiter の一人である @mametter さんによる Ruby 3 の型システムについてのセッションでした。

既存の型システムとしては Steep, RDL, contracts.ruby, dry-types, RubyTypeInference, Sorbet などがありますが、代表として RDL という半静的 type checker について紹介されていました。

RDL は型検証を行うタイミングを指定でき、静的型チェックを無視して動的型チェックのみを行うようにすることもできます。
また、メタプログラミングもサポートしており、動的に生えるメソッドの型宣言もできます。

Steep のように型宣言がファイルで分かれているほうが良いが、メタプログラミングは難しいということで、RubyTypeInference のように型情報を推定する Type Profiler という構想が生まれました。
この推定された型情報は厳密なものではなく、推定結果を人間がチェックすることを想定した設計になっています。

型情報をプロファイリングするには、void 型の推定が困難なことや、TracePoint API を用いて動的に解析しようとすると非常に遅くなるという問題があると話されていました。

感想

RubyKaigi は今回が初参加でしたが、レポート記事や実況ツイートではわからない会場の雰囲気を味わえて非常に良かったです。
特に、今回は型システムにまつわる発表が多く、個人的に今非常に興味があるので、Ruby 3 に向けた型システムの構想を聞いたり懇親会などの場で参加者と話をできたりして面白かったです。

ぜひ来年も参加したいと思っています。


シンクロ・フードでは Ruby に詳しいエンジニアも募集しています。ご興味のある方は以下よりご連絡ください!