GameWith Developer Blog

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

GameWith で初のエンジニアインターンを実施しました。 #GameWith #TechWith

エンジニア兼インターン総合実施責任者のめもりー (@m3m0r7) です。 GameWith では 2019/03/7(木) から 2019/03/20(水) にかけて、サービス開発部主催の初のエンジニアインターンシップを行いました。 本インターンには想像以上に多くの方からご応募があり、本当にありがとうございました。

この記事ではどんなインターンシップだったのか、インターンシップを実施するまでの裏話的なのを書きたいと思っています。

どんなインターンシップだったのか

初日から開発まで

本インターンシップは2週間(営業日換算10日)という期間で1つのサービスをチームで作っていくものでした。本インターンの趣旨は「チーム開発」としており、 チーム対抗ではなく、そのチームのリソースや動きなどを自分たちで意思決定して進んでいってもらうものでした。

タイムスケジュールとしては、1日目はオリエンテーション、2日目からは実際に開発と開発の時間を長めに取れるような構成にしました。 下記は実際に今回のインターンシップで使用されたタイムスケジュールです。

f:id:m3m0r7:20190322122511j:plain

初日はオリエンテーションを行い、メンター各自の自己紹介を行いました。 f:id:m3m0r7:20190322122948j:plain

開発のお題は予め GameWith で3つほど用意し、インターン生達にどのお題でやりたいかを話し合って頂いて、お題を決定しました。 今回のお題は「ゲームでマッチングするサービス」となり、2つのチームに分かれてチームの運用方針から Git の使用方法、技術選定などを考えていただいて 実際に開発していくものとなりました。

開発に入る前にチーム名を決めていただき、それぞれ「宇治抹茶チーム」、「2 / 3 メガネチーム」となりました。 最終的にはチーム名に愛着があったようで良かったです!

f:id:m3m0r7:20190322121810j:plain

チーム責任者のもとで、インターン生のみなさんが白熱した議論をしていて、私も議論に参加したいぐぬぬ…と我慢した覚えがあります。

また、今回のインターンでは1日の終りに メンターとインターン生が対面で話す 1 on 1 の時間を毎日設けました。 インターン生が抱えている課題を一緒に解決していって、このインターンシップをより良いものにしたいという思いがあったため、設けました。 また、 1 on 1 実施後はメンター同士で集まり、課題を収集し解決していく方針を決定していました。 初めての実施ということもあり、メンター自身が困っていることがないかどうかもその場で洗い出して、解決していくという方針になっていました。

実際の開発

インターン生の実際の開発では AWS の EC2 を GameWith が提供したり、 Firebase を使ってもらうなど実際の業務に近いかたちの環境化で開発していただけたのではないかなと思っています。 f:id:m3m0r7:20190322124045j:plain

自発的に S3 を使いたい、 Firebase を使いたいという声があがって、改めて学生は優秀だなと実感しました。 GameWith はPHPをメインとして扱っている会社であるため、 両チームともに PHPのウェブフレームワークである Laravel や、フロントエンドに関しては Vue, Reactなどモダンなものを選んでいらっしゃいました。

いろいろとつまづきポイントがあったり、メンターと一緒になんで動かないんだろうと考える時間を思い出すととても楽しかったという記憶があります。

中間発表

中間発表では、サービス開発部の島付近で各チームの進捗と開発しているものを発表していただきました。インターン生たちが緊張している中ではあるものの、中間発表も各チームのいい味が出せていて良かったのではないかなって思ってます。

(すみません、写真を取り忘れました…!)

最終発表

最終発表では中間発表と同じ形で発表していただきました。中間発表は1チーム15分でしたが、最終発表では1チーム30分の時間を取っていただきました。 泣いても笑っても最後という段階で、緊迫している中、サービス開発部からは盛大な拍手があり、無事終了しました。

f:id:m3m0r7:20190322125655j:plain

f:id:m3m0r7:20190322125633j:plain

インターンシップの実施を通して

最終的にアンケートを取って、インターン生たちからはとても良かった、有意義だった、参加して本当に良かった、また参加してみたいなどの嬉しいお言葉をいただきました。 GameWith のエンジニアインターンは初めてという中で、メンターの皆さんも成功させたいという一心で動いていたと思うので、成功したのではないかなと思っています。

f:id:m3m0r7:20190322125721j:plain

インターンシップを実施するまで

インターンシップの企画

開発部で初のインターンシップを行うという企画自体は2018年の8月から9月にかけて行われました。 部長、マネージャーと話を進めながら、他社のインターンを参考にしつつ企画を進めていきました。 例えば、インターンシップを行う目的はなにか、実施することによって会社が得られるものはなにか、何人採用するのか、契約形態はどうするのか、時給はどうするのか etc... いろいろと詰めていてあっという間に年末に近づき、そろそろ募集文を出さないとヤバイ、ということで募集文の準備をしていました。

片一方で

片一方で、インターンシップを一緒に実施してくれる有志を募りました。 f:id:m3m0r7:20190322131650p:plain

合計で9人ほど集まりました。 最初にキックオフを行い、どういうことをインターンシップで行うのか、タイムスケジュールはどうするのかなどを話し合って詰めていました。 また、採用基準をどうするのか話し合って決定しました。

面接 / 面談について

集まっていただいた9人から、面接/面談を担当する方を決めて、多くの学生さんたちとお話させていただきました。 今回はメンターの人数の問題もあり、1次面接のみという形で進めさせていただきました。

メンターの役割

本インターンシップでは4つのロールを定め、それぞれの役割にメンターが専念して貰う形にしました。 定めることにより、自分たちがどういった行動をすればよいのかが明確になるためです。

f:id:m3m0r7:20190322132713p:plain

実施前に期待値の確認を行う

インターンシップ実施の前にインターン生にアンケートをお送りし、GameWith のインターンシップに期待していることを予め知ることにより、 期待値の調整や、期待していることに応えられたのではないかなと思っています。

多くの部署を巻き込んだ

今回のインターン実施では多くの部署を巻き込みました。それでも各部署の方々は快くサポートしてくださったので、今回のインターンが成功したのだと思っています。

インターンを実施時に出てきた課題

主にタイムスケジュールに関連した課題が多いかなと本インターンでは感じました。 タイムスケジュールの調整が間に合わず、大枠しか確定していない状態で面接を開始してしまったのが今でも課題だったなと思っています。 インターンの実施については、事前にどれだけ準備・他部署と連携するかが大切だと改めて実感しました。 タイムスケジュールの組み方も初めてだったということもあり、オリエンテーションはオリエンテーションで固めすぎていましたが、分散させるべきだったなと反省しています。 メンターやチーム責任者がインターンをどう進めていくべき・どういう存在であるべきか、もう少しディスカッションする時間があっても良かったかなとも感じました。 今回は私の事前準備の至らなさで、ディスカッションする時間がほぼなく、それでもアドリブでインターンを成功させようと尽力してくださった皆様には感謝しきれません。

最後に

いかがでしたでしょうか、今回のインターンシップを実施するまでから実施してみてまでの一連の流れを書かせていただきました。 GameWith ではこのような企画などもしているので、興味があればぜひご応募お待ちしております。

www.wantedly.com

LINEチャットボットをリリースして得た知見 #GameWith #TechWith

こんにちは、iOSエンジニアのchuymasterです!最近バイオハザード RE:2をようやく始めて、悲鳴を上げながらストーリー攻略を目指しています。

2月下旬、GameWithの初めてのチャットボットをリリースしました!今回は、チャットボット作成で得た知見を共有したいと思います。技術構成も記載しますが、かなりプロダクト寄りの内容になります。

f:id:gwchai:20190311183737p:plain:w300
マルチ募集チャットボット

どんなチャットボット?

モンストのマルチプレイの仲間募集を手伝ってくれる可愛らしいLINEのチャットボットです。「マルチ募集チャットボット」と呼んでいます。何ができるか?どうやって使うかはこちら↓

gamewith.jp

チャットボットの検証と仮実装は昨年末から始まっていて、こちらの記事で詳しく説明したので、よかったらどうぞ合わせて読んでください。

tech.gamewith.co.jp

プロジェクトの前提

本当にユーザーがチャットボットを使ってくれるかどうかの確信がないため、今回は最小限のリソースでプロダクトのリリースを最優先した「実験プロジェクト」になります。

「マルチ募集チャットボット」はあくまでもチャットボットの価値を検証するためのプロジェクトという前提で進めています。

開発スケジュール

f:id:gwchai:20190308141552p:plain
当初のガントチャート

僕がiOSエンジニアの掛け持ちでチャットボットを作っているので、半分ぐらいの時間を使う感覚で開発期間を1ヶ月程度設けました。開発者は、Androidアプリ開発以外は僕一人です。

1月末公開の予定でしたが、iOSアプリの開発が押していて優先対応したので、結果的に2月22日が公開日となりました。

技術構成

バックエンド

LINE Messaging APIのやりとりと、アプリ向けAPIはFirebase Functionsを使っています。

サーバーレスなので、インフラの心配をしなくて良い点と、iOS開発者としてFirebaseに馴染みがある点が採用の理由です。

フロントエンド

Firebase Hostingを使っています。アプリへのリダイレクトページと、画像の提供で使っています。本当は画像はStorageを使うべきですが、量が少ないのでHostingでとりあえずやりました。

データベース

Realtime Databaseを使っています。Cloud Firestoreは開発しているとき、データの1件取得に2秒かかることが多くて許容範囲外だったので、その問題がないRealtime Databaseを採用しました。Cloud Firestoreは今はBetaが外れたので、いずれ移行したいと考えています。

上記で分かるように、チャットボットを支えるのはすべてFirebaseの機能です。Firebaseだけで本当にいろいろなことができます。Firebaseの他の機能の説明は、弊社のエンジニアが詳しく書いてあるので、よかったらお読みください。

tech.gamewith.co.jp

言語

Firebase Functionsの開発はTypeScriptを使っています。Functionsの開発言語はJavaScriptも選べます。ですが、SwiftでコーディングしているiOSエンジニアとして、型がないことは死活問題なので、型があるTypeScriptを選びました。

SwiftとTypeScriptは意外と似ていて書きやすかったです。機会があればこの2つの言語を比べたいと思います。

クライアントアプリ

クライアントアプリはGameWith本体のiOS/Androidアプリに、チャットボットから送るURLスキーム情報を受け取って、マルチ募集を自動で開始する処理を追加しました。

学んだこと

ここからが、プロダクト開発を通して得た知見です。チャットボットの成功の秘訣!とまではいかないですが、失敗しないための3つの知見を紹介します。

1. チャットボットだからこそ「ものすごく便利に」できることを考えよう

チャットボットは対話UIを通したアプリだと僕は思っています。アプリと同様、価値がないと判断されるとすぐ削除=ブロックされてしまうので、チャットボットだからこそ「ものすごく便利に」なる体験を提供しないといけません。

幸い、モンストユーザーの課題は明確です。マルチで遊ぶ仲間を募集するためには、モンストから一度募集メッセージをLINEに送信して、GameWithアプリにコピペしないといけないことです。

コピペの手間は大きくないかもしれませんが、ヘビーユーザーは1人1日、20回以上募集をかけているので、かなりストレスに感じるはずです。

マルチ募集チャットボットなら、そのものすごい手間がなくなるので、使う価値はあります。

リリース後、マルチ募集をかけているアプリユーザーの2割以上がチャットボットを使っているので、かなり多く使っていただいていると思います。

2.チャットボットのイメージを可視化してメンバーに伝えよう

チャットボットは画面がないので、サービスのイメージがパッと分かる一枚資料が作れません。

そこで、プロジェクト関係者にイメージ共有するため、公式ツールのLINE Bot Designerを使いました。

f:id:gwchai:20190311130042p:plain
LINE Bot Designerの実際の画面

想定したユースケースを全部洗い出して、各ケースの会話シミュレーションを作りました。これが設計書になっていて、プロジェクト関係者に説明するときは、ユーザーになったつもりで、各ケースの会話の順番を追いながら説明して認識を合わせることができました。

モンスト攻略担当者がこれを見て、会話の内容を指摘してくれたし、デザイナーが直接これを使って、色の調整などをしてくれたので、とても使いやすいツールだと思います。

3. キャラクターを決めて、ボットに命を吹き込もう

マルチ募集のチャットボットは、「乃灯あろん(のとあろん)」というキャラクターで返事しています。あろんちゃんは開発部のデザイナーが心をこめて描いた(非公式)キャラクターです。

f:id:gwchai:20190311185949p:plain
LINEのチャットアイコン&ホームで登場する「あろんちゃん」

今まで、活躍するところが少なくて、GameWithアプリのチュートリアルぐらいでしか登場する場面がないですが、今回はチャットボットで登場してもらうことにしました。

そこで必要になるのがセリフですが、最初のリリースでは、「機能的」なセリフしか用意していなくて、モンストの募集メッセージ以外の言葉を送ると「ごめんなさい」としか返事できませんでした。

開発部内でもこれは切ないという声が上がったので、早速あろんちゃんの生みの親に、いくつかのキーワードに反応するセリフを作ってもらいました。そして実装したところ、ツイッターでちらほら画面のキャプチャをして拡散してくれるユーザーがいて、だいぶ盛り上がりました。

f:id:gwchai:20190311182942p:plain:w300
セリフのおかげで可愛らしくなりました

チャットサービスを使うと、ウェブと違ってユーザーは人と話す感覚になるので、愛用されるチャットボットになるには、こうした人間らしさが必要だと気付きました。

ちなみに「乃灯あろん」の名前は社内公募で決めました。名前の由来は英語のNot Aloneとかけて、マルチでゲームをするユーザーの手助けができるよう「あなた一人じゃない」「私がいます」という意味を込めています!

今後の展開

今は各種プロモーションを使ってマルチ募集チャットボットの認知度を上げています。

一定数のユーザーに使っていただけて、アプリのユーザー増加に十分貢献できると判断できれば、本格的にチャットボット開発に取り組みたいと考えています。

その際、チャットボットだからこそものすごく便利にできることって何だろう?を真剣に考えて、ユースケースを設計し直す必要があるので、さらに大きな挑戦になりそうです!

GameWithではチャットボットに限らず、様々な新規事業に挑戦しています。我も新規開発をしてみたい!という志を持つ方をGameWith開発部が募集中です!

興味があって話を聞いて見たいなぁと思った方は是非Wantedlyで会いに来てください! www.wantedly.com

エンジニア公式ツイッターもはじめてます。フォローをよろしくお願いします! twitter.com

ExoPlayerを使ってAndroidアプリに動画を入れた話 #GameWith #TechWith

はじめまして、GameWithでAndroidエンジニアをしているgiです。 iOSの攻略動画に続き、Androidもv2.1.0で攻略動画を見られるようになりました。

前回kyamさんが書いたiOSの記事:

tech.gamewith.co.jp

今回はExoPlayer(v2.9.6)の使い方について話をします。

目次

簡単の紹介

公式サイト: https://google.github.io/ExoPlayer/
Source code: https://github.com/google/ExoPlayer
ExoPlayerはGoogleが開発したアプリケーションレベルのMediaPlayerです。Libraryとして扱うため、AndroidのSource codeにはありません。

メリットとデメリット

メリット

  • DASH、SmoothStreamingなどMediaPlayerがサポートされてない動画もサポートしています
  • カスタマイズは簡単
  • アプリと一緒にアップデートできます

デメリット

  • Libraryですので、アプリのサイズが増えます
  • Android 4.1からの MediaCodec API に依存しているため、4.1以前は使えません

使い方

Gradle設定

GoogleとJcenterのリポジトリが必要です

    repositories {
        google()
        jcenter()
    }

dependencies

  // core、必須のdependency、ほかのdependencyは全部オプショナルです
  implementation 'com.google.android.exoplayer:exoplayer-core:2.9.6'
  // hlsをサポートしたいときのdependency
  implementation 'com.google.android.exoplayer:exoplayer-hls:2.9.6'
  // smoothstreamingをサポートしたいときのdependency
  implementation 'com.google.android.exoplayer:exoplayer-smoothstreaming:2.9.6'
  // dashをサポートしたいときのdependency
  implementation 'com.google.android.exoplayer:exoplayer-dash:2.9.6'
  // デフォルトのUIを入れたdependency、自分でUIを書くのもできますが、これがあると便利です
  implementation 'com.google.android.exoplayer:exoplayer-ui:2.9.6'

ほかにrtmp、flacなどのextensionもあります:https://github.com/google/ExoPlayer/tree/release-v2/extensions/

Java 8の設定

compileOptions {
  targetCompatibility JavaVersion.VERSION_1_8
}

ExoPlayer v2.9.0以上はJava 8の設定が必要です。

playerのインスタンスを作る

  val player = ExoPlayerFactory.newSimpleInstance(context)

newSimpleInstanceメソッドが複数あって、ContextRenderersFactoryTrackSelectorLoadControlなどいろいろなカスタマイズができます。一番簡単なのはContextだけ設定して、ほかは全部デフォルトにするこのメソッドです。

playerをViewに設置する

exoplayer-uiを使っている場合

直接中のPlayerViewを使うことができます:

  playerView.setPlayer(player)

exoplayer-uiを使ってない場合

自分が書いたViewとplayerの連携を取る必要があります。

動画Url(mp4)を使ってMediaSourceを作る

  // 1つの動画
  val dataSourceFactory = DefaultDataSourceFactory(context, Util.getUserAgent(context, context.packageName))
  val mediaSource = ExtractorMediaSource.Factory(dataSourceFactory).createMediaSource(Uri.parse(url))

  // 1つの動画を10回ループする
  val mediaSource = ...
  val loopingMediaSource = LoopingMediaSource(mediaSource, 10)

  // 3つの動画を連続で再生する
  val mediaSource1 = ...
  val mediaSource2 = ...
  val mediaSource3 = ...
  val concatenatingMediaSource = ConcatenatingMediaSource(mediaSource1, mediaSource2, mediaSource3)

hls、smoothstreaming、dashが必要なとき、それぞれのHlsMediaSourceSsMediaSourceDashMediaSourceを使う必要があります。

MediaSourceとplayerを組み合わせて動画を再生する

  player.prepare(mediaSource)

EventListenerを使ってplayerの状態変化を取る

  player.addListener(object : Player.EventListener{
    // タイムラインが変わった、再生が始まった、再生が止まった、再生がエラーになったなどの情報はここで取れます
  })

音量の設定

  player.setVolume(audioVolume)

audioVolumeは0〜1のfloat、0は音なし、1は最大。この設定は、あくまでplayerの音量設定です。デバイスの音量をOFFにしたら、setVolumeで最大に設定しても、音が出ません。

動画のplayとpause

  // play
  player.setPlayWhenReady(true)

  // pause
  player.setPlayWhenReady(false)

動画画面を閉じるときの処理

  player.release()
  player = null

UIのカスタマイズ

exoplayer-uiを使っている場合

  • Libraryにあるexo_simple_player_view.xmlを参照して、自分のUIをカスタマイズする、exo_simple_player_view.xmlのコード:
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 The Android Open Source Project

     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->
<merge xmlns:android="http://schemas.android.com/apk/res/android">

  <com.google.android.exoplayer2.ui.AspectRatioFrameLayout android:id="@id/exo_content_frame"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:layout_gravity="center">

    <!-- Video surface will be inserted as the first child of the content frame. -->

    <View android:id="@id/exo_shutter"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/black"/>

    <ImageView android:id="@id/exo_artwork"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="fitXY"/>

    <com.google.android.exoplayer2.ui.SubtitleView android:id="@id/exo_subtitles"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <ProgressBar android:id="@id/exo_buffering"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:indeterminate="true"
        android:layout_gravity="center"/>

    <TextView android:id="@id/exo_error_message"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:gravity="center"
        android:background="@color/exo_error_message_background_color"
        android:padding="16dp"/>

  </com.google.android.exoplayer2.ui.AspectRatioFrameLayout>

  <FrameLayout android:id="@id/exo_ad_overlay"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

  <FrameLayout android:id="@id/exo_overlay"
      android:layout_width="match_parent"
      android:layout_height="match_parent"/>

  <View android:id="@id/exo_controller_placeholder"
      android:layout_width="match_parent"
      android:layout_height="match_parent"/>

</merge>

動画の場合、exo_content_frameが必須です。再生している動画を表示するTexureView/SurfaceViewがその中に入るためです。ほかのViewは全部なくっても問題ないです。別のIDが付いたViewを追加しても問題ないです。ただしその場合、そのViewを自分で制御しなければならないです。 コントローラーが欲しい場合、exo_controller_placeholderあるいはexo_controllerが必要です。

  • コントローラーをカスタマイズする場合、exo_playback_control_view.xmlを参照して、自分のUIをカタマイズする。

  • PlayerViewplayer_layout_idcontroller_layout_idを設定する

    <com.google.android.exoplayer2.ui.PlayerView
      android:id="@+id/player_view"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      app:player_layout_id="@layout/my_player_view"
      app:controller_layout_id="my_controller_view"
      />

exoplayer-uiを使ってない場合

すべてのUIを自分で作るため、特別な設定は必要ないです。

まとめ

以上がExoPlayerの簡単な使い方です。あまり複雑なものが必要ないなら、結構使いやすいLibraryです。また、Github上のdemoにはいろいろな複雑な機能を実装しています。とても勉強になります。

終わりに

GameWithアプリチームでは一緒にアプリをよくしていく仲間を募集中です! 興味がありましたら以下からご連絡をいただけるとありがたいです。

www.wantedly.com

毎年旧バージョンのiOSサポート打ち切り交渉するのが大変なので、iOSアプリ サポートOSバージョンルールを作った #GameWith #TechWith

こんばんは、ApexLegendsで物資調達中に崖から転落死した @peka3 です。

iOSは毎年メジャーバージョンアップが行われますね!

ずっと古いバージョンもサポートできればいいのですが、そうすると開発効率が落ちていくので、サポートバージョンを打ち切ることも大事だったりします。

そういうときはエンジニアとプロダクトオーナー間で交渉して、じゃあこのバージョンまではサポートを終了しましょう、となったりならなかったりします。

これが毎年の作業として入ってくるチームも多いのではないでしょうか!?

GameWithアプリでも先日iOS10のサポートを終了しました。

その際に「iOSアプリ サポートOSバージョンルール」を設け、今後はこのルールに沿いますということでプロダクトオーナーと合意を取ることにしました。

なぜ iOSアプリ サポートOSバージョンルール を決めたのか?

毎年iOS Xのサポートを打ち切るとどういうメリットがあって…などをまとめるのは非効率です。

そもそもサポートOSのバージョンを上げることのメリットはほとんど

  • 新機能が使えて開発効率や開発の幅が広がる
  • テストにかかる工数が削減できる

この2点に集約できるので毎回洗い出すほどではないと考えました。

よって、考えることを削減したい、コミュニケーションコストを削減したい、という目的でルールを決めました。

テスト工数削減について

ほとんどの開発において、各バージョンで動作確認するので、たとえばiOSの場合、i0S10, 11, 12 をサポートしようとすると、テストは3必要。

これが直2バージョンのみのサポートになれば、 iOS11, 12 だけでよくなり、テスト工数は 2/3 になります。

ものすごく単純計算で出しましたが、古いバージョンを打ち切ったらテスト工数が増えてしまう、ということはないでしょう。

古いOSではセキュリティリスクがある

iOSは基本的に最新のメジャーバージョンにしかセキュリティパッチが来ないので、iOS12が最新なら12未満を使ってるだけで、すでにセキュリティリスクがある状態で利用していることになります。

サポートOSバージョンを上げたとしてもサポート対象外のOSで使えないわけではない

打ち切られたOSであってもすぐに使えなくなるということはなく、AppStoreで対応していた最終版のアプリをDLもできます。

よって、サポートを打ち切られたバージョンの利用者が突如離脱につながる、ということはありません。


 

……前提のお話として、まずここまでプロダクトオーナーと認識を合わせました。

ここから具体的にどのラインを割ったらサポートを打ち切るかの交渉になるのですが、GameWithアプリでは以下のようにしました。

   

サポート打ち切りライン

iOS10はシェア3%を切ってからこの2ヶ月、2.5%〜2%前後で推移している。

バージョンアップに興味がない、したくない一部のユーザがずっと使い続けている状態であり、これ以下にはほとんど下がらないのでは?と推測できる。

よって今後も該当OSバージョンのシェアが3%未満 であればサポートを打ち切る。

……として、上記の内容でプロダクトオーナーと合意しました。

コミュニケーションコスト削減目的でもあるので、この数値を割ったらまずサポート打ち切る前提で話を進めることになります。

 

ユーザに告知する

サポートバージョン打ち切りはユーザの皆様にも理解していただかなくてはいけないので、きっちり告知をするところまで含めて行います。

gamewith.jp

   

まとめ

GameWithアプリではiOS10はこのようにしてサポート終了としました。

今後は交渉は特にせず、サポート終了をすることの確認と、ユーザへの告知記事作成だけで行ける想定です。

他のアプリでの交渉事例、シェア何%で打ち切るのかなども知りたいです!

もしよかったらコメントいただけると嬉しいです。


GameWithアプリチームでは一緒にアプリをよくしていく仲間を募集中です! 興味がありましたら以下からご連絡をいただけるとありがたいです。 www.wantedly.com

エンジニア公式ツイッターもはじめてます twitter.com

ユビキタス言語を発見するためにユーザーストーリーマッピングをやってみた #GameWith #TechWith

こんにちは、 最近はゼリー状の物体を四つ繋げて消すゲームと、三人一組で生き残るゲームをしている @peka3 です。

先日、GameWithアプリチーム内でユーザーストーリーマッピングを行ってみました。

今回はそれについてのレポートとなります。

ユーザーストーリーマッピングとは?

簡単にいうと、ユーザーの行動に対してどういう機能があればいいかを洗い出す作業になります。

ユーザーストーリーマッピングそのものについての説明は以下スライドが参考になります。

ユーザーストーリー駆動開発で行こう。

スライドより引用

f:id:peka3:20190228201035p:plain
ユーザーストーリーマッピング

きっかけ なぜユーザーストーリーマッピングをやろうとなったのか?

チーム内でユビキタス言語が設定できてないので、会話が難しい。ユビキタス言語を作りたい、というのがきっかけでした。

当初はDDDのイベントストーミングという手法を使おうとしていたのですが、チーム内にその手法に詳しい人がおらず、正しいやり方で行うのが難しそうだと断念しました。

そこで出てきたのがユーザーストーリーマッピングでした。

こちらは経験者もいて、これでもユビキタス言語は発見・設定できそうだということで、今回はユーザーストーリーマッピングを行うことになりました。

人数

今回は議論があまり活発になりすぎず、発散せず、短期間で仕上げられるように、ドメイン知識に詳しいプロダクトオーナー、デザイナー、エンジニア2人の合計4人でユーザーストーリーマッピングを行いました。

ペルソナの設定

f:id:peka3:20190304183505p:plain
ペルソナ T君

GameWithアプリにはすでにT君というペルソナがいるので、今回はこれを活用し、このT君がGameWithアプリを使ってゲームの攻略情報を探すまでの一連の動作を深掘りします。

大きなタイムラインを描く

タイムライン

タイムラインをざっくり抽出します。これは一人で一気に書き出してしまいました。

今回はアプリを使って攻略記事を読み、さらにそこから別の攻略記事を読みに行く、というタイムラインで考えることにしました。

それぞれのタイムラインで、ユーザーがどういう行動をとるか

次にユーザーのアクションを抽出していきます。

ここでは細かい機能の話はせずに、それぞれのタイムラインでユーザーはこういうことをする、ということを付箋に書き出します。

これも粒度がまちまちだと困るので、合意のもと一人で一気に付箋に書き出しました。

ユーザーのアクション

それぞれのアクションでユーザーは具体的に何ができるか?ストーリーの洗い出し

アクションが設定できたら次はストーリー(機能)を洗い出します。

たとえば「記事を探す」というアクションをユーザーがとるとき、どういった機能を使ってそれを行うのか?という視点で機能を出していきます。

これは全員で付箋に書いて貼っていく作業となります。

f:id:peka3:20190228191542p:plain
ストーリーの洗い出し

書いた内容を説明しながらホワイトボードに付箋を貼ります。

優先度順に並び替え、MVPの設定

最後は機能として出した付箋を優先度順に並び替えます。

ここは議論になりやすかったです。上手にファシリテートしないと時間が一気に消費されてしまいます。

さらに機能群の最上段に一本線を引き、ユーザーがアクションを行うために最低限必要な機能をその線より上に置きます。

この線より上にあるものが MVP(minimum viable product)の要件となります。

f:id:peka3:20190227190518p:plain
優先度順に並び替え

仕上げ

新規のプロダクトではないので、すでに実装がすんでいるものを洗い出し、上に持っていきます。

マスキングテープより上のものがすでに実装済みのものでした。

f:id:peka3:20190228174831p:plain
ユーザーストーリーマッピング

これでユーザーストーリーマッピングが完成しました。

しかし今回はこれで終わりではなく、ユビキタス言語の抽出を行います。

ユビキタス言語

付箋に出てきた言葉をユビキタス言語として命名していきます。(細長の黄色付箋)

他のものと混同してしまわないだろうか?というところを注意して命名していきました。

今後は会話の中でこのユビキタス言語を使っていくことになります。

f:id:peka3:20190228175702p:plain
ユビキタス言語

まとめ

ユーザーストーリーマッピングをやってみた個人的な感想なのですが、一連の操作に沿ってじっくり考えることができるので、どういう風にユーザーがアプリを使っているのかが具体的に想像しやすくなりました。

今後の見通しも立つのでユビキタス言語の発見はもちろん、技術的にもモデルを考えやすくなりました。

意見もたくさん出てきて、1テーブルでわいわい話せる人数だったのも良かったかもしれません。

かなりゆっくりすすめても、合計3時間ほどでできたので、一度みんなで認識合わせをするツールとして有効そうです。

皆さんもやってみてはいかがでしょうか!

GameWithアプリチームでは一緒にアプリをよくしていく仲間を募集中です! 興味がありましたら以下からご連絡をいただけるとありがたいです。 www.wantedly.com

以上です。

GameWith フロントエンド もくもく会 #8 開催しました #GameWith #TechWith #gamewith_moku2

はじめに

こんにちは。GameWithのエンジニアのtiwuです。

2月28日(木)にGameWith主催で第8回目のもくもく会を開催しました!

GameWith フロントエンド もくもく会 #8

gamewith.connpass.com

今回のテーマは僕自身が関心を高く持っているフロントエンドを採用しました。

当日は昼から豪雨が振るという悪天候でしたが、外部の参加者の方3名にお越しいただきつつ、GameWithのエンジニアは4名で参加しました。

もくもく会は最初に自己紹介と今日のもくもく内容を発表して、もくもくスタート!

僕はService WorkerについてQiitaを書いていました。

f:id:tiwu_gamewith:20190304151554j:plain

SUBWAYを食べながらもくもく・・・

2時間ほどもくもくしたら本日の進捗の発表をしました!

・・・

参加者はいろいろなフロントエンドの技術に触れていました!

  • Vue.jsの公式HPのチュートリアルを進める
  • Vue.jsでアプリが作れるNativeScriptについて調べる
  • phina.jsでモンスト風のブラウザゲームの開発

1口にフロントエンドと言っても純粋なWebフレームワークから、アプリ、ゲーム開発など幅広さを感じました。

GameWith フロントエンド もくもく会 #9

次回のもくもく会は 3月28日(木)に開催します!

次回のテーマもフロントエンドです!

gamewith.connpass.com

最後に

参加していただいた社外・社内エンジニアの皆様ありがとうございました!

GameWithは、フロントエンドが大好きで、新しい技術をどんどん使っていきたいという方を大募集中! Wantedly でもよいので是非お気軽にお声がけください!

www.wantedly.com

またGameWithのDeveloper向けTwitterアカウントも開設しました。
もくもく会の告知やブログの更新情報などを発信するので良かったらフォロー宜しくお願いします!

twitter.com

半年間輪読会を運営してみて #GameWith #TechWith

GameWithエンジニアのTです!

皆さん輪読会というのをご存知でしょうか?

輪読会とは複数人で1つの本を読み、内容に関する議論をしていくといったスタイルの読書会です。

GameWithでは社内勉強会の一環として輪読会を行っており、前回は「リーダブルコード」を輪読会していました!

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

  • 作者: Dustin Boswell,Trevor Foucher,須藤功平,角征典
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2012/06/23
  • メディア: 単行本(ソフトカバー)
  • 購入: 68人 クリック: 1,802回
  • この商品を含むブログ (140件) を見る

詳しくはこちらの記事をご覧ください。

tech.gamewith.co.jp

今回の輪読会

今回は「 エンジニアリング組織論への招待」を半年かけて輪読会をしました。

エンジニアリング組織論への招待 ~不確実性に向き合う思考と組織のリファクタリング

エンジニアリング組織論への招待 ~不確実性に向き合う思考と組織のリファクタリング

なぜ「 エンジニアリング組織論への招待」を選んだか

特定のプログラミング言語に関する本ではなく、GameWithのエンジニア・デザイナーが全員参加できる本というテーマで選びました。

DDDなどの開発手法を学ぶ本なども候補としてあがりましたが、社内で「 エンジニアリング組織論への招待」を実際に買って読んでいる最中の人もいたことから、今回は「 エンジニアリング組織論への招待」を選びました。

GameWithはこの1年間でエンジニア・デザイナーの数が増えてきており、チーム毎に分かれて業務を行うようになることでメンバー間の距離が遠くなり、コミュニケーションコストが増加しました。

また、各チーム内の開発で業務範囲が閉じてしまうので、他チームのエンジニア・デザイナーと交流しての業務知識・技術知識の研鑽がしにくくなってきました。

そのため、マネージャーだけでなく組織についてエンジニア・デザイナー1人1人が学ぶ必要性を感じ始めたのもこの本を選んだ一つの要因です。

輪読会のやり方

輪読会は毎週金曜日の15時から1時間実施しました。

発表者はローテーションで予め決めており、その週の発表者は輪読会の前に内容を要約して当日それを元に発表しディスカッションをする形式をとっていました。

また、ディスカッションは次の発表者が議事録を取っていました。

下記のように発表者が章ごとに要約をまとめていたので、途中参加のしやすさも心がけていました。

f:id:tiwu_gamewith:20190226121140p:plain

輪読会最終回 オープンスペーステクノロジー形式

輪読会の最終回はオープンスペーステクノロジー形式で行いました。

オープンスペーステクノロジー形式とは

各メンバーに過去に学んだテーマの中で特に最後に掘り下げて扱いたいテーマを選んでもらい、セッションを立ち上げディスカッションを行いました。

ディスカッション中は軽食も用意したのでとても盛り上がりました。

f:id:tiwu_gamewith:20190207112114j:plain

輪読会参加者の集め方

今回12,13人の参加者が集まりました。

過去にリーダブルコードの輪読会をやっていたため、その輪読会に参加していたメンバーがそのまま流れで参加したり、新規エンジニア・デザイナーにも声をかけ集めました。

みんなが興味あった本を選んだのも多くのメンバーが集まってくれた理由かもしれません。

輪読会の運営にあたり工夫したこと

前日にSlackの輪読会チャンネルで下記のようにリマインドを必ず行いました。

f:id:tiwu_gamewith:20190226131938p:plain

また、当日もリマインドを必ず行いました。

f:id:tiwu_gamewith:20190226131949p:plain

勉強会に関しては業務の一環として行って良いと許可をもらっており、それをメンバーに伝えることで参加への心理的安全性を高くしました。

また、メンバーが忙しく発表できないときは、うまくフォローをして、毎週の輪読会を途切れないようにしました。

ディスカッションの際にはファシリテーションをして、楽しい輪読会になるよう心がけました。

運営していて辛かったこと

毎回の発表者へのリマインドや、資料の進捗管理など単純なタスクではありましたが地味に手間がかかりました。

また、ディスカッション中のファシリテーションは基本的には自分が行っていましたが時には負担になることもあったため、発表者にファシリテーションを任せる方式にしてもよかったかもしれませんでした。

また、この輪読会は終了するまでに半年間かかりましたが、期間として長かった気もしました。

改善するなら or こうしておけばよかった

半年間は長い気がしたので、ディスカッションの時間を減らして、3ヶ月で終わるくらいのほうがよかったもしれません。

当初の目的としてGameWithのエンジニア・デザイナー内で輪読会という活動を広め、各人に参加してもらうことで、輪読会のナレッジ等を貯めるのも開催の意図としてあったので、もし次やるなら本のテーマを絞って人数を少なくしてもいいかもしれません(今回は12,13人いて少し多いと感じました)

また、今回は輪読会でしたが次回はハンズオン形式など輪読会以外にもエンジニアの志向に合わせた活動をしていきたいと考えています。

運営してみての感想

ディスカッションでメンバーがそれぞれいろんなエピソードや、意見を述べていて各人の考え方を知ることができて良かったです。

メンバー全員がモチベーション高いまま半年間輪読会を行えたのは良かったです。

また、エンジニアだけでなくデザイナーも参加してくれて嬉しかったです。

現在はフロントエンドに特化した輪読会なども開催されており、この輪読会という文化がエンジニア・デザイナーに浸透してきた思うので、運営した甲斐がありました!

最後に

参加していただいたエンジニア・デザイナーの皆様ありがとうございました!

GameWithは、ゲームが大好きで、新しい技術をどんどん使っていきたいという方を大募集中! Wantedly でもよいので是非お気軽にお声がけください!

www.wantedly.com

またGameWithのDeveloper向けTwitterアカウントも開設しました。
社内イベントの告知やブログの更新情報などを発信するので良かったらフォロー宜しくお願いします!

twitter.com