GameWith Engineering Blog

GameWith のエンジニア、デザイナーが技術について日々発信していきます。

CircleCI 2.0 への移行の軌跡 - Sunsetting 1.0 -

ご無沙汰しております。GameWith でエンジニアマネージャーをしている @serima です。

8 月は弊社エンジニアが代わる代わる技術ブログを執筆してくれたので、出番が少なかったです。(とても嬉しい…)

まだ、読んでない方は是非こちらの記事もご覧ください。

CircleCI のレクイエム

さて、いよいよ 2018 年 8 月 31 日を迎えましたが、本日は何の日か覚えてますでしょうか?

はい、そうです。CircleCI 1.0 の終了日です。

f:id:serimaryo:20180831121832p:plain

circleci.com

こちらのサイトでは、CircleCI 1.0 のビルド終了までの時刻がカウントダウンされています...。

ちなみに GameWith には約 50 個のプライベートリポジトリが存在するのですが、プロジェクトで利用している CircleCI は先週ですべて CircleCI 2.0 への移行が完了しました。

もちろん全プロジェクトで CircleCI を使っているわけではないので、移行作業自体はそこまで大変ではありませんでした。

続きを読む

GameWithアプリ と GameWithアプリチームについてのご紹介

はじめまして!

GameWithアプリのiOS版の開発を担当をしている @peka3 と申します。

blogは初投稿となります。

最近は、ドラクエ10で夜な夜な聖守護者の闘戦記に通い続けています。 聖守護者の闘戦記ではバトル面で今までの常識を覆すパラダイムシフトが起きました。 ああいうのにすぐに対応出来る人は、エンジニアに向いているのではないかなぁ、と思ったりしてます。

本題に移ります!

最近は部内で情報をオープンに伝える動きがあるのですが、GameWithアプリに関しては全然オープンにできていませんでした。 今回はGameWithアプリが、どういう環境で、どういうプロセスで開発されているのかをお伝えできればと思います。

iOSアプリエンジニアなので、iOS寄りの観点になってしまいますが、ご了承ください 🙇

GameWithアプリ について

f:id:peka3:20180829120038p:plain:w200

GameWithをより便利に使えるアプリとなっています。

メインとなる機能としては

  • 攻略情報や新作ゲーム情報を閲覧するためのブラウザ
  • 攻略情報、イベント情報のpush通知
  • SNS機能

があります。

詳しくはぜひ AppStore からインストールして使っていただきたいです!

GameWithアプリのミッション

GameWithアプリは、ゲームユーザーの第一想起を取る、ということをミッションに掲げてやっています。

この第一想起を取っている状態がどんな状態なのか、というのはチーム内で議論の末、

攻略情報を見るのもゲームを探すのも、真っ先にGameWithアプリを使ってくれる状態

という共通認識でやっています。

GameWithアプリ チーム構成

2018年8月23日現在のチーム構成ですが、

  • PO兼デザイナー: 1名
  • iOSアプリエンジニア: 2名
  • Androidアプリエンジニア: 1名
  • サーバサイドエンジニア: 1名

となっています。

またiOS、Androidそれぞれ1名ずつ業務委託でお手伝いしていただいています。

施策によってはWeb面への影響もあったりで、関係者に話を通しに行くことはありますが、基本的には施策を生み出すところからリリースまで、全てをこのチームで行っています。

開発プロセス

軽めのスクラム開発を行っています。

リファインメント等のセレモニーはセオリー通りですが、朝会や作業時間の記録などはしていません。 今のコミュニケーションの取り具合からすれば、特に時間を決めて朝会をしたり、細かく作業ログをつける必要はないだろうという判断からです。

POが描いたKPI達成のための大きめのロードマップを、チーム内で揉んで具体的な施策として形にしてプロダクトバックログに落とし込み、スプリントごとにプロダクトバックログの優先順に計画をして開発しています。

カンバン等のツールにはJIRAを使っています。

f:id:peka3:20180829124307p:plain

毎週金曜日にスプリントレビューとKPTを行ってます。まだまだスピード感を出してどんどん新しい施策をやっていきたいので、どこかがネックになっていないかなどを洗い出して、トライに繋げていきます。

今は各エンジニアの技術領域がはっきりと分かれてしまっていて、APIの進捗がクライアントに影響するような状態です。

今後は学習コストを適切に払いつつ、複数領域触れるエンジニアを増やしていきたいと思っています。

施策の生み出し方

ロードマップはあくまでざっくり案なので「○○機能強化」などざっくりしたものも多いです。

そういったものはチーム内でブレストを行って案出しをし、それぞれ効果と工数のマトリックスにマッピングして、やることを決めます。

決まったものはプロダクトバックログに追加されていきます。

エンジニアの思いつきからでも、実際に形になり、アプリに反映されることが多くあります。

働き方

エンジニアは裁量労働制なので、勤務時間等は基本的に個人の裁量に任せられています。

自分の場合は大体1日8時間勤務で見てます。周囲もそのようにしている人が多いようです。

またリモートワークの導入も進めていて、iOSアプリエンジニアは週2回までリモートワーク可能となっています。

iOSアプリのアーキテクチャ

レイヤードなMVVMで行っており、各層はRxSwiftのObservableで連携しています。

大雑把に書くと、

View -> ViewModel -> Repository/UseCase -> Infrastructure

という構成になっています

RepositoryとUseCaseを同一レベルの層にする(ViewModelがどちらにも依存しうる)のは議論があったのですが、現状のアプリの機能であればここを切り離して別の層にしても、メリットよりも一層間にかます作業工数のほうが取られるだろう、という考えで同一層で取り扱うことになりました。

また、この大まかなアーキテクチャの方針は iOS / Android とも共通にしています。

どの層にどういった実装が必要か?といった会話をする際に、共通認識を得やすくするのが目的です。

開発環境

PCは選択制なのですが、自分はMacbook Pro13インチがいいと入社時に伝えたら、なぜか iMac Pro と Macbook Proが支給されました。

Xcode は重いので iMac Proでの作業が最高に捗っています!

終わりに

ざっと広く浅く、GameWithアプリがどういう風に作られているのかを書いてみました。

個人的にはチームの心理的安全性が担保できてれば、大体のことはうまく回るんじゃないかなぁと思っています。(それが難しいのですが)

事業的な成長にあわせて人員も増えているため、最近は開発部内で「エンジニアリング組織論への招待 ~不確実性に向き合う思考と組織のリファクタリング」という本をテーマにした社内勉強会も行うなど、皆で組織やチームをより良くしていこうとしています。

gihyo.jp

もしGameWithアプリチームに興味を持ってくださった方、もっと詳しい話を聞いてみたい方がいましたら、下記からご連絡いただけるとありがたいです🙇

www.wantedly.com

Google オフィスで開催されたKubernetes/GKE セミナーに参加してきました!

こんにちは!7月にGameWithに入社し、新規事業でエンジニアとして働いている田口航です!

つい先日奇跡的に水着ジャンヌを引けて、今年の運を使い切ったかなと悲観しているところです・・・。

現在GameWithはAWSを利用しているのですが、僕が携わっている新規事業はGCPを利用しています。

構成をGAEとGKEで悩んだのですが、運用フェーズでGAEより融通が効きk8sの知見も貯まることからGKEを採用しました。

GKEはまだまだ情報量も少なく、所々詰まりながら開発を行っています(nginxとphpを別Podで立てる場合や固定IPなどなど)。

そんな中、先日Google様のKubernetes/GKE セミナーの招待をいただき、弊社エンジニア3人で参加してきました!

僕自身は本番環境の運用等の知見はあまりなく不安多めで参加したのですが、とてもわかりやすく濃いセミナーでした。

簡単にですがセミナーの内容をレポートしていきたいと思います!

f:id:tiwu_gamewith:20180806183047j:plain
ステッカーいただきました!

Kubernetes/GKE セミナー

f:id:tiwu_gamewith:20180807122629j:plain
セミナーの様子です!

流れ

  1. Kubernetes/GKE 概要紹介
  2. 実践編
    1. CI/CD
    2. ロギング
    3. モニタリング
    4. オートスケール
    5. ログ管理
  3. 質疑応答
  4. 個別相談会(自由参加)

Kubernetes/GKE 概要紹介

Kubernetes

  • Kubernetesは「コンテナオーケストレーション」
  • k8sとよく呼ばれる
  • コンテナを中心としたインフラを構築し、デプロイする
  • 当初はGoogleが開発して、2014年にオープンソースとなった
  • 開発者はAPI/UI/CLI経由でMasterに命令が可能

GKE

  • Google Kubernetes Engine
  • ワンクリックでk8sクラスタを作成できる

実践編

CI/CD

  • この前「Cloud Build」を発表
  • GitHubとも連携
  • プログラミング言語に依存せずビルド可能
  • 一般的なビルド用コンテナが、あらかじめオープンソースとして公開されている
  • その他、様々なビルド用コンテナが、コミュニティによって公開されている

ロギング

  • Stackdriver Loggingを有効にすると自動でログを収集
  • コンテナログとシステムログを収集
  • 30日間しか保持しないので、必要に応じてBigQueryに渡す

モニタリング

  • Stackdriver Monitoringでモニタリングできる
  • リソースの使用率、CPU、メモリ等ができる
  • クラスタ、ノード、PODの段階でできる

アクセスコントロール

  • namespaceによりPODを論理的に分ける
  • RBAC(Role-based access control)
    • 各ロールがどのnamespaceに何ができるかを定義する
    • このユーザーはこのnamespaceにデプロイができる or できないなど

デプロイ、ロールバック

  • デプロイは kubectl apply -f hoge.yamlで基本はできる
  • kubectl rollout undo deploymentでデプロイをロールバックする
    • ロールバックはレプリカセットにはない機能
  • deployment strategyを設定することでアップデート方法をコントロール可能
    • 全てのPODを削除して、作り直す(本番ではやらない
  • PODをローリングアップデート
    • maxSurge アップデート用に追加で作成可能なPODの数
    • maxUnavailabele アップデート中に停止できるPODの数

リソースマネジメント

スケールアウト スケールアップ
PODレベル  POD数を制御 POD数をに対するリソース割当を制御
HPA(Horizontal Pod Autoscaler) VPA
クラスタレベル Node数を制御 Nodeのソース割当を制御
Cluster Autoscaler VM scale up
  • PODのCPU使用率がトリガー
  • GKEにはCustom HPAがあり、CPU以外をトリガーにできる

Quality of Service

  • CPU/MEMをPODに割り当てができる(最低と最大)

Pod Disruption Budget

  • ノードのアップデート時に落ちてもいいPODの数を定義

まとめ

僕は今までフロントエンドやサーバーサイドの開発が多く、本番環境の運用の知見等は多くはなかったのですが

今回のセミナーでぐっと運用の課題とk8sの解決方法の知見が深まりました!

Google の皆様、ありがとうございました!

最後に

Kubernetes/GKEの構成は事例が少なく、GameWithとしても知見は少なくチャレンジの毎日です!

こういった技術的なチャレンジが好きなエンジニアを募集しています!

ご興味のある方は是非連絡をください!

www.wantedly.com

入社して1ヶ月でiOSアプリをリリースした話

先月、ゲームの攻略や最新情報を動画で視聴することができるアプリ「Mipple(ミップル)」のベータ版をリリースしました。 今回はこのMippleの紹介を兼ねて、タイトル通りいかに素早くアプリをファーストリリースしたか、ということをテーマに執筆しています。

f:id:keeetaka:20180807141821p:plain

‎Mipple | サクっと見るゲーム攻略動画まとめ on the App Store

Mippleとは

先月リリースしたMippleについて簡単にまとめると、

  • ゲームの攻略情報や最新ニュースを短尺動画で視聴できるアプリ
  • 動画の企画・作成・編集は基本的に社内のGameWithメンバー
  • 毎日更新

といったアプリとなっています。

今回はエンジニアブログということで、何故このアプリが開発されたかや今後どのようにグロースハックさせていくのかといったマーケティング的な話は割愛させて頂いて、技術寄りで紹介していきます。

開発の流れ

自分は6月にiOSエンジニアとして入社しました。

配属されたのが短尺チームという新規事業チームで、自分が入社する半年以上前からアプリの構想を練っておりどういったゲームの動画がユーザーに刺さるのかを、SNSに動画を投稿し検証をしているチームでした。 自分はそのチームのエンジニア第一号でした。

チームからプロダクトの話を聞いてどういった技術を使えば実現できるかなどを調査をしながら提案し、入社して一週間過ぎた後くらいにアプリの実装が始まりました。 ファーストリリースの方向性に関してはチームでMTGを重ねながら開発と共にデザインや仕様を徐々に確定させていき進めていきました。

採用した技術やツール

新規事業ということもあり、とにかくスピード感を持ってリリースし、PDCAサイクルを回していく事が大事なプロダクトだと感じました。 よって出来る限りサービスの質を落とさずサービスの要件を叶えられる選択肢をいくつかピックアップし、比較検討した上で以下のものを採用しました。

設計

設計に関しては非常に悩みました。 アプリの規模もそこまで大きいわけではなく、複数人開発でもないため過度な冗長化は逆に時間がかかるなと思いました。 後から人が入った時に考えれば良いというのもあるかもしれませんが、最低限どういう思想で開発をしているかは他人に話せる必要があると考え、サービスに合ったアーキテクチャを取り入れることにしました。

採用したのは Clean Swift というアーキテクチャです。 なぜ Clean Swift なのかを書くとそれだけで終わってしまいそうなのでここはまた別の機会に書きます。

f:id:keeetaka:20180809144548p:plain

Clean Swift のサンプルに関してはこちらが参考になりました。 github.com

バックエンド

バックエンドに関してはサーバーを立てたわけではなく、YouTube Data APIを全面的に採用しました。 当初はAWSなどの採用を検討しましたが、初期の価値検証のフェーズであれば YouTube Data APIを使うことでクライアントエンジニアのみでより素早く開発できると考え一旦見送りました。

APIを使う機能に関しては、おすすめリストの取得、ランキングの取得、検索、各ゲームのリスト取得などがあるのですが全て実現できます。

各リストの取得に関しては、playlistItems APIなどを使いplaylistId(プレイリストのID)を指定することで任意のリストを取得できます。

検索に関しては基本的に、Mippleのチャンネル内からの検索となるので、 search APIに対して、q(キーワード)channelId(自分のチャンネルID)を付与してあげれば 検索部分のAPIは機能として果たします。

もちろん、取得件数やページトークンのパラメーターを付与することで、下にスクロールして20件読み込みなどどいった一般的なページネーションの仕組みも入れることができます。

f:id:keeetaka:20180809154934p:plain

ネットワーク

個人的にAPIKitを好んで使っています。 APIリクエストをシンプルに定義する事ができて、他の開発者がチームに入った時もAPIのインターフェースが見やすく理解しやすいです。

データベース

アプリ内にお気に入り機能があるためRealmを採用しています。 動画がお気に入りに入れられたり外されたりした場合即座にUIに反映したいため、Realmの通知システムであるNotificationTokenを用いてデータの更新を受け取ったら即座にリストに反映させています。検索履歴機能に関してもRealmを使って実装しています。

f:id:keeetaka:20180807151710p:plain

その他補助ツール

計測

Facebook Analyticsに関してはシェア機能のためにFacebook SDKを導入したためその流れで導入しています。

Firebaseに関してはイベント計測のために用いています。 ユーザー属性などを適用してがっつり運用というよりは、どういった動画が再生されるのか、この機能は使われているのかなどといった事を知るためにイベントメインで計測しています。

こちらのメソッドを活用すると、独自のパラメータなども設定できます。

+ (void)logEventWithName:(NSString *)name
              parameters:(nullable NSDictionary<NSString *, id> *)parameters
    NS_SWIFT_NAME(logEvent(_:parameters:));

課題と対策

これはシンプルで Youtube Data API を使うことによる制約。これに尽きると思います。

API使用量の制約

YouTube Data API では1日に利用できるリクエスト数に制限があるため、何も考えずに適当に実装するとユーザー数が増えた時にサービスが機能しなくなる恐れがあります。

API使用量に関して

MippleではRealmを用いて各リストをアプリ内に保存しておき、任意の保存期間を過ぎた場合最新のものを取得するようにしています。 現状まだユーザーが好きなタイミングで最新のリストを取得できるようなPull To Refresh(引っ張って更新)機能は入れていないため、こちらは実装する必要があると感じています。

UI・UXの制約

YouTubeの動画を再生するという仕組み上、AVPlayerなどを使わず、iOSだとYTPlayerViewを使うことが一般的でどうしても再生するViewがYouTubeっぽくなってしまいます。

- (BOOL)loadPlayerWithVideoId:(NSString *)videoId playerVars:(nullable NSDictionary *)playerVars;

そこで読み込みの際に、どういった状態で読み込ませるかを設定できるplayerVarsを指定することである程度Viewの見た目をコントールできます。

YouTube埋め込みパラメータ

これらを上手く活用することで、動画のプレーヤーコントロールを非表示にし読み込みが完了したら自動でインライン再生させるなどができるようになります。

シンプルにリストをタップしたらビュアーが立ち上がるようなアプリだとこれで良いのですが、Mippleの場合、UICollectionViewをスクロールしていくと一つのセルごとに一つの動画を自動再生させるといったフィードがあります。

YTPlayerViewの殆どがUIWebViewで作られており、自動再生を繰り返すとUIWebViewがやたらクラッシュして最初困りました。(※YouTube側でも複数のYTPlayerViewインスタンスの作成を推奨していない)

ですのでWKWebViewで作り変える + UIScrollViewDelegateメソッドでセルが表れるタイミング、消えるタイミングなどを取得しハンドリングする事で無事解決しました。

ストアにアプリを公開してから早1ヶ月近く経ちますがアプリのクラッシュ数は0でクラッシュフリー100%を実現できています。 今後機能が増えるにつれてクラッシュが出ないように頑張ります。

今後やりたい事

駆け足で紹介しましたが、まだまだやりたい事がたくさんあります。

  • バックエンドの開発・強化
    • AWS LambdaやCloud Functionsなどサーバーレス部分に興味があります
    • 次開発予定の機能で上どちらかをメリットデメリットなど慎重に考慮した上で採用予定(YouTubeData APIからの移行)
  • flutterでAndroid版を開発
    • 勉強会に行ったりコード書いたりして学習してるのでどうせならプロダクトを作りたい
    • flutter勉強会も開催予定です
  • 自分の好きなゲームタブを追加
    • 開発者でもありユーザーでもあるので自分の好きなゲームも攻略タイトルとして扱われるようになってほしい(シャドバと人狼殺が好きです)
  • 開発体制の強化
    • まだテストやQAの仕組み化が完全に整っていないため徐々に整備
  • 新しい試み

終わりに

長くなってしまいましたがここまで読んで頂きありがとうございました。

リリースしたのは入社して1ヶ月後ですが、実際の開発工数だけで見ると2週間弱くらいかもしれません。 ディレクター、デザイナー、エンジニア等、各ファンクションでの意思決定の早さが新規事業ではスピード感に直結したなと感じました。

まだまだベータ版ですが日々着実にユーザー数は増加してきており、エンジニア側としてもより安定して使いやすいアプリにしていこうと努力していきます。 一緒に開発したいメンバーや話を聞いてみたいメンバーは是非Wantedly経由で会いにきてください!

Webのイメージが強い弊社ですが最近ではアプリにかなり力を入れており、アプリエンジニアの採用を強化しています。

www.wantedly.com

GameWith PHP もくもく会 #6 を開催しました

こんにちは!エンジニア 兼 技術広報の @serima です。

7 月 19 日 (木) に GameWith 主催で第 6 回目のもくもく会を開催しました!

今まではずっとフリーテーマで運営していたのですが、今回は PHP というジャンルに絞って開催してみました。

今回は外部の参加者の方 3 名にお越しいただきつつ、GameWith のエンジニアは 3 名で参加しました。

f:id:serimaryo:20180724160614p:plain

続きを読む

PHP カンファレンス関西 2018 にブース出展してきました #phpkansai

こんにちは!毎日とても暑いですね。

一昨年、隣駅まで自転車で走ったら割と重度な熱中症になってしまい、それからはかなり気をつけるようにしている GameWith の技術広報 @serima です。

7/14 (土) に PHP カンファレンス関西 2018 でブース出展をしてきました。 ブースに立ち寄ってお話を聞いてくださった方々、本当にありがとうございました!

GameWith は今回、PHP カンファレンス関西 2018 にゴールドスポンサーとして協賛させていただきました。 (すでに下記のポストでお伝えしたとおりです!)

tech.gamewith.co.jp

f:id:serimaryo:20180718182144j:plain

準備〜当日

GameWith としては初の遠征でのブース出展だったのですが、自分を含め 4 名のエンジニアがブース出展のために大阪まで行ってきました!

f:id:serimaryo:20180718152406j:plainf:id:serimaryo:20180718152414j:plain
灼熱のグランフロント大阪(この日の最高気温 37 ℃)

ブースで簡単なアンケートにお答えいただいた方に、GameWith のロゴ入りモバイルバッテリーをプレゼントしました!

こちらのノベルティ、予想以上に好評なので追加発注を行ったばかりです。 次にどこかのカンファレンスでブースを出す際も必ず持っていきますので、是非ゲットしてください!

PHP カンファレンス関西 2018 では、運営側から各ブースに「カード」が設置され、参加者さんはそのカードを集めることで記念品がもらえるような仕掛けがあったようです。(当日聞かされましたw)

この仕掛けによってスタンプラリーのように参加者がブースを訪れてくれるという工夫があり、ブース出展側としては嬉しい配慮でした。

そのおかげで、GameWith のブースには約 150 名ほどが遊びに来てくれ、そのうちの半数弱の方にアンケートを回答していただけました(本当にありがとうございます…!)

f:id:serimaryo:20180723170845j:plainf:id:serimaryo:20180723191402p:plain
落ち着いたタイミングでしか写真を撮っておらず残念...

遠方でのブース出展

遠方への出張ということで、下記のような思わぬ効果もあった個人的に感じています。

  • 移動時間が長いためメンバー同士でのコミュニケーションが必然的に多くなる
  • GameWith を使って頂いているユーザさんが遠方にもいらっしゃることを体感でき、よりサービス開発に身が入る
  • ポケモン Go で新たなポケストップにチェックインできる(!)

最後に

GameWith ではゲームも PHP も好きなサーバサイドエンジニアを積極的に募集しています。ゲームが好きな方大歓迎です!

(現在、関東圏にお住まいでない方もお気軽に!)

ご興味のある方は、Twitter の DM でも、Wantedly でもよいので是非お気軽にお声がけください。

www.wantedly.com

recruit.gamewith.co.jp

builderscon tokyo 2018 にスポンサーとして協賛します

GameWithbuilderscon tokyo 2018 にスポンサーとして協賛します。

gamewith.co.jp

弊社のエンジニアも当日は何名かで参加する予定です。 ぜひ会場でお会いしましょう!

イベント概要については、以下をご覧ください。

イベント概要

f:id:serimaryo:20180720094523j:plain

イベント名 : builderscon tokyo 2018

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

日時 : 2018 年 9 月 6 日 〜 8 日

会場 : 協生館(慶応大学)

公式 HP :

builderscon.io