Akatsuki Hackers Lab | 株式会社アカツキ(Akatsuki Inc.)

Akatsuki Hackers Labは株式会社アカツキが運営しています。

サーバーサイドでのインターン(五月)の成果報告

まえがき

お初にお目にかかります。 株式会社アカツキさんで五月十一日〜五月二十二日の約二週間(実質十日間)、サーバーサイドの開発でインターンをいたしました、村上と申します。

本記事では、当該インターンにおける成果報告と感想を述べます。よろしくお願いいたします。

インターンの形態について

時期が時期の中行われたインターンですので、皆様に誤解を与えてしまわないよう、まずは本インターンの形態についてご説明いたします。

ご存知の通り、現在、世界中が感染症対策に追われています。日本も例外ではなく、具体的には、オフィスへの出勤を最小化しなければなりません。 ですので、アカツキさんも全面的にリモートワークを行なっています。そのため、今回のインターンは対面を一切廃したフルリモートで行われました。私は愛知県在住なので、東京とおよそ300kmのソーシャルディスタンスを確保した上での実施となります。

機材は事前に郵送いただき、手続き等も全てリモートで行われました。インターンに際して、感染症対策は徹底されていたという点を明記しておきます。

インターンで行ったこと

本インターンでは、大人気ソーシャルゲーム『八月のシンデレラナイン』、通称ハチナイのサーバーサイドの開発業務に携わりました。なお、サーバーにはRailsが用いられています。

10日間中は様々なタスクがありましたが、その中でもメインで行ったものは以下の三つです。

  • APIサーバー開発環境の改善
  • 敵チーム調整用管理画面の作成
  • デレスト編成中の選手をそのまま移籍・保管庫に移動させられる機能の実装

それぞれについて、詳しく述べていきます。

APIサーバー開発環境の改善

インターンを開始してまず手をつけたのが、この作業です。 当時のAPIサーバーの開発環境には以下の問題があり、環境構築におよそ半日ほどかかってしまっていました。

  • 開発用のMac上にそのままRailsやMySQLなどをインストールしていたため、依存するソフトウェアやライブラリのバージョンを適切に揃える必要がある
  • 環境についてのドキュメントが不足しており、構築する側がトライアンドエラーを繰り返して設定する必要がある

一度構築してしまえば問題ないとはいえ、今後入ってくる方にも同じ時間を強いてしまうのは勿体ないこと、さらに非サーバーサイド開発でも手軽にローカルで検証環境を立ち上げられるようにしたいということで、この改善に取り組むことにしました。

対応方針としては、DockerとDocker-Composeを用いて数コマンドで環境を立ち上げられるようにして、誰でも簡単に環境を作成・破棄できることを目指しました。 幸い、作りかけでしたが既にdocker-compose.ymlと関連ファイルが作成されたブランチがあったため、出ているエラーの調査(連携するその他のソフトウェアのメンテナの方からの聞き取り等含む)と修正をしたり、一部テストケースの改善をしたり、ドキュメントを整えたりといった細かな作業を行い、実作業二日間、計三日間でApproveをいただけました。

この改善による影響は大きく、半日かかっていた構築作業がおよそ20分で完了するようになりました。また、ゲームのクライアントを担当されている方と一緒に開発をする際、相手側で検証用サーバーを立ち上げてもらって開発を進める、といった手法も気軽にとることができるようになり、開発の体験が向上しました。 実際に「便利になったね!」といったフィードバックをいただけた時は、本当に嬉しかったものです。

敵チーム調整用管理画面の作成

次に対応できそうなタスクを探していると、『敵チームの調整を管理画面から行えるようにする』といったタスクのカードが目に留まりました。 詳しく話を聞いてみると、ゲームの調整を行う方からの運用改善として以下の課題が出ていたことが分かりました。

  • 試合の敵チームを作成するにあたって、現状は職人技で行なっているので、属人化してしまっている部分がある
  • 敵チーム調整のサイクルが一つの場所で完結しておらず、結果の予測も簡単ではないため、経験が浅いと調整に時間がかかってしまうのが原因
  • そのため、管理画面に敵チーム調整用の機能を追加し、管理画面の機能群だけで調整を完結させられないか

お話を伺う限り自分でも対応できそうだったので、そのまま着手することにしました。 具体的には、ActiveAdminで作られていた管理画面に敵チーム調整用のページを新設し、関連するパラメータも調整できるようにしました。

ActiveAdminの挙動で少し詰まったところはありましたが、それ以外はすんなり実装できたと思います。実装後に簡単なドキュメントも書いたのですが、良い勉強になりました。レビュー含め二日間ほどで終わったと思います。

デレスト編成中の選手をそのまま移籍・保管庫に移動させられる機能の実装

こちらは、ゲームのクライアント側でインターンをされていた方との共同作業になります。 ハチナイの試合やデレストにおいて、今までは以下の問題がありました。

  • 試合やデレストを進めていて選手所属数上限エラーとなった際、デレスト編成中の選手はそのまま移籍や保管庫に移動させることができず、いちいちデレストの画面から入れ替えを行う手間があった

そのため、サーバー側とクライアント側の両方に変更を加え、デレスト編成中の選手でもそのまま移籍・保管庫への移動を行えるように改善することになりました。 サーバー側の変更量自体はさほどだったのですが、変更の内容と影響範囲を考慮し、テストケースの修正と追加をメインに行いました。実際にテストを増やしてみると、実装中は気がつかなかったケアレスミスが発見できたりして、やはりテストを増やすのは正解だったなと実感しました。こちらもレビュー含め、三日間ほどで完了できました。

また、実装に際して、クライアント側のインターン生の方がとても優秀で頼もしかったです。 リモートで実装に関しての相談や打ち合わせを何度かしたのですが、毎回スッと意を汲んで対応していただけたので感謝しています。 円滑な開発を行う上で、コミュニケーション能力は本当に大事ですね。私も精進します。

学び

実質10日間という短い期間でしたが、インターンを通して学べたことは多くありました。

例として、分かっているはずだったものが、実際に手を動かしてみると頭からすっぽり抜け落ちてしまう、といった問題を認識できたことが挙げられます。 具体的には、実装における設計です。頭の片隅に置いてあったベストプラクティスのはずなのに、作業に集中していると目の前のことで一杯一杯になってしまい、後から改善点を指摘される、といったことがありました。 もちろんインターンというアウェーな環境というのもあるとは思うのですが、それ以上に自分の経験不足を感じたのが大きいです。頭をよく使ってから手を動かす、ということを繰り返すことで、どんな状況でもベストプラクティスが実践できるようにしていきたいものです。

また、これはいろんな場所で何度も言われていることだとは思うのですが、チーム開発においてコミュニケーションは重要だなと思いました。 アカツキさんの方々は皆さんお優しくて、Slack上でもいろいろなトピックで会話が弾んでいます。そのおかげで気軽に質問や発言ができましたし、結果的に円滑な作業に結びついていたと感じました。 これが、仮に最低限の会話しかないような状況だったとしたら、インターンというのも相まって、萎縮や虚無感で効率がガタ落ちだっただろうなと容易に想像できます。 リモート作業ではどうしても人との関係性が希薄になりがちで、恐らくこの状況はこれからもしばらく続くと予想されますが、こうしたコミュニケーションが効率という面を支えているということを忘れないようにしたいところです。

感想

インターンが始まるまでは、寝付けずにうなされるくらい、自分がやっていけるのかどうかが心配で仕方ありませんでした。 しかし、実際にサーバーサイドのチームに入って作業してみると、思っていたよりかはパフォーマンスが出せたので一安心です。とはいえこれで傲慢になるのではなく、学んだ点を糧に引き続き精進していきたいと思います。

また、仕事がとても楽しかったです。毎日十時〜十九時までが勤務時間だったのですが、十九時に業務が終わってすぐに次の日の朝が待ち遠しくなるほどでした。 自分でもこの感情には驚いたのですが、それだけアカツキさんが働きやすい環境だったのかなと思います。まさにハートドリブンですね。

さいごに

大変な情勢の中、就職活動の一環とはいえインターンの受け入れをしてくださり、お世話になったチームの皆さんやアカツキさんには大変感謝しております。 ありがとうございました。

【ハチナイ】Unityクライアントエンジニアインターン【9日間】

こんにちは。teppeiと申します。3月16日〜3月27日まで、祝日を挟んで9日間インターンをしました。「八月のシンデレラナイン」のプロジェクトでUI関連の機能を中心に開発に携わりました。本記事では今回のインターンで行なったタスクや、自分の感じたことなど書いていきたいと思います!

 

目次

 

自己紹介

私は機械&情報系の大学院一年生で、VRやヒューマンコンピュータインタラクションの研究をしています。普段はVTuberの配信システムを作る会社でバイトをしています。インタラクティブで新しいエンタメを作る仕事をしたいので、それが実現できそうな会社を探して就活中です。

 

 インターンに参加した経緯

私は去年夏にあったアカツキのゲームジャムに参加し、その後選考を進めてアカツキから内定を頂いていました。就職先を決めるにあたってもう少しインターンを経験して判断材料を増やしたかったので、今回のインターンに参加させていただきました。

 

 初日〜作業開始まで 

 初日に同時に入社した方々と一緒に、人事、ゲーム部門、労務のオリエンを受けました。それぞれの時間は短く、簡潔にまとめられていたので受けるのが楽で良かったです。オリエンの合間に業務用MacBook Proの環境構築を進めていました。

二日目にメンターと開発プロデュサーの方と三人で、私が事前にゲームを遊んで気づいた改善点リストを見つつ、インターンで行うタスクを決めるミーティングをしました。タスクはすんなり決まり、ストーリーチャプターのレイアウトを自動で配置するUnityEditor拡張を作ることになりました。その日の午後から本格的に開発を始めることができました。

参加したチーム

「八月のシンデレラナイン」という、野球をする女子高生を育成するモバイルゲームを開発しているTSUBASAというチームでインターンさせていただきました!

ストーリーチャプター自動レイアウト機能の開発

方針の決定

ストーリーチャプターのアイコンはプランナーの方々がその都度位置を手打ちしているのですが、通常ステージではレイアウトが定型(波形など)のものも多いので、そういったレイアウトを自動化して手間を省けないかというのが今回のIssueでした。

まず最初に実際にレイアウト作業を行なっているプランナーの方々の席まで行って、現在のワークフローと、改善したい点を教えていただきました。

レイアウトの座標はUnity上でScriptableObjectに直接打ち込んでいるとのことだったので、同じくUnity上で作業ができるように、Unityのエディタ拡張で自動レイアウト機能を作っていく方針にしました。また、打ち込んだ座標が正しいかどうかはその都度ゲームを実行して確認しているとのことだったので、実行しなくても手軽に確認できるようにGUIを実装することにしました。

エディタ上でレイアウトを編集できる機能の実装

この前webで見かけたプレハブ編集画面を自分で作るというアプローチが良さそうだったので、ScriptableObjectに書かれたアイコンレイアウトの情報をSceneView上に表示して、GUIで編集・保存できるようにしようと考えました。

f:id:negitoro113:20200325144600p:plain

実際に作ったものの画面がこちら ↑ です。赤い四角がアイコンの位置を表しており、左上にあるGUIで数値を変更するとSin波や三角波の形状にアイコンが自動配置されるようになっています。

この機能がそれなりに動くようになった時点で実際に機能を使う方々に見せに行き、フィードバックを頂いて機能改善をしていきました。

三日目にはだいたい動くようになったので、プルリクを出してコードをレビューしていただきました。細かい部分まで丁寧にレビューコメントをいただきました。普段のバイトでは開発に携わる人数が少ないということもあり、そこまで細かくはレビューされないので、新鮮でいい経験になりました。

プレイ中に編集・保存を行えるように実装方針を変更

既存のコードやプランナーの方の要望への理解が深まっていくにつれ、もっと使いやすい設計が思い浮かんできました。

これまでの実装だとアイコンの位置が赤い四角で示されていましたが、実際の見た目で位置を調整するに越したことはありません。なので、実際の見た目でアイコン位置を調整してそのまま保存できるように、ゲームのプレイ中に自動レイアウトと保存ができるように仕様を変更することにしました。

f:id:negitoro113:20200325153631p:plain

できたものがこちら↑です。実際の見た目でレイアウトの保存・編集ができるようになりました。

実行中のゲームオブジェクトからエディタの機能を呼ぶのはUnityの仕様では基本的にできないのですが、Reflectionを使うなどして半ば無理矢理に実装しました。未経験の機能を使えて楽しかったです。

 

その他のタスク

上記のタスクを早めに終わらせることができたので、再びプログラマとプロデューサの方とミーティングして追加のタスクを決めました。不具合の修正や細かな改修をいくつか行いました。これらのタスクを通してコードの色々な箇所を見ることができ、勉強になりました!デバッグに思ったより時間がかかってしまったので、もっと効率的にデバッグができるようにならなければと反省しました…。

 

まとめ

靴を脱いで上がるオフィスや、リビングのような共有スペースがあり、非常に居心地のいいオフィスでした。また、一人一人の考えと行動で会社を良くしていくという文化が一貫していることが印象的でした。新しい事業や技術に挑戦している方も多くいらしゃいました。総じて、ストレスレスに楽しく働ける会社という印象を持ちました。

コロナの影響により多くの社員がリモートワークで会社にはいらっしゃらなかったですが、私の席の周りは結構人がいて寂しくはなく、それなりにコミュニケーションもとれたので良かったです。

今まで参加したインターンや仕事は、プロジェクトの立ち上げや開発初期段階のものがほとんどだったので、 既に数年サービスを継続しているプロジェクトで働いた経験は新鮮でとても勉強になりました。ありがとうございました!

脆弱性診断用に非ルート化端末でも動作するCUIのメモリ改ざんツール「apk-medit」を作った話

こんにちは、セキュリティエンジニアの小竹 泰一(aka tkmru)です。 アカツキでは、Webアプリケーション、ゲームアプリに対する脆弱性診断や社内ネットワークに対するペネトレーションテスト、ツール開発/検証などを担当しています。

メモリ改ざんによるチートとは

UI上に表示されている値を端末のメモリ上から検索し、見つけた値を改ざんすることでチートを行うことができる場合があります。 これはゲームのチート方法の中で最も簡単な方法で、脆弱性診断の際にも実際にメモリ上のデータを改ざんをすることでチートできるかどうか確認しています。 対策としては、XOR等を使ってメモリ上ではエンコードされた状態で値を保持し、UI上に表示されている値を検索されても見つからないようにする方法があります。

作ったツール

apk-meditという脆弱性診断のためのAndroidアプリ向けメモリ改ざんツールを作成しました。 CUIで動作し、非ルート化端末でも動作するのが特徴です。また、Goで実装しているため、Android NDKに依存していません。

github.com

使い方

非ルート化端末でメモリを読むためには、run-asコマンドを使い、実行しているアプリの権限でシェルを動作させる必要があります。 run-asコマンドはdebuggableなアプリにしか使えないため、対象のアプリがdebuggableでなかった場合には、 AndroidManifest.xmlを開きapplication nodeに対して、以下のattributeを追加する必要があります。

android:debuggable="true"

対象のアプリの準備ができたら、adbコマンドで/data/local/tmp/以下に実行バイナリをpushしてください。

$ adb push medit /data/local/tmp/medit
medit: 1 file pushed. 29.0 MB/s (3135769 bytes in 0.103s)

run-asコマンドの引数にターゲットのアプリのパッケージ名を指定し実行したあとは、自動的にディレクトリが変更されます。 apk-meditの実行バイナリを/data/local/tmp/からコピーして、実行してください。

$ adb shell
$ pm list packages # パッケージ名を確認
$ run-as <target-package-name>
$ cp /data/local/tmp/medit ./medit
$ ./medit

apk-meditを実行すると、インタラクティブなプロンプトが立ちがります。 プロンプト上に実装されたfindコマンドやpatchコマンドを用いて以下のようにメモリを改ざんすることができます。

f:id:TAKEmaru:20200327153009g:plain
apk-meditを使ってメモリ改ざんする様子
f:id:TAKEmaru:20200327153127g:plain:w175
メモリ改ざん対象のゲームの様子

フィルタ機能

小さく、キリがいい値はメモリ上にいくつもあり、1回の検索で目的のアドレスを見つけることは困難です。 そこで前回の検索で見つけたアドレスの中から、指定した値に変化しているアドレスを見つけるfilterコマンドを実装しました。

> find 100
Search UTF-8 String...
Target Value: 100([49 48 48])
Found: 712!
------------------------
Search Word...
Target Value: 100([100 0])
Found: 6605!
> filter 94
Check previous results of searching UTF-8 string...
Target Value: 94([57 52])
Found: 0!!!
------------------------
Check previous results of searching word...
Target Value: 94([94 0])
Found: 1!!!
Address: 0xe7021f70
> patch 5
Successfully patched!

filterコマンドを繰り返し使って見つかるアドレスを絞っていくことで、目的の値に到達することができます。

実装

ここでは、Goを使って開発することの利点は何なのか、 どのようにしてメモリ上のデータを読み込んでいるのかについて解説します。

開発にGoを使うメリット

今回の開発にあたり、Goを使って感じたメリットは以下の4つです。

  • ARM向けにバイナリを用意するのが簡単
  • システムコールの呼び出しが簡単
  • 大きいバイト列から目的のバイト列を高速に検索するのが簡単
  • GitHub ActionsとGoReleaserのおかげでバイナリを配布するのが簡単

ARM環境向けにLinuxバイナリを用意するのが簡単

Goコンパイラはクロスコンパイルをサポートしており、環境変数GOARCHGOARMにアーキテクチャ名とバージョンを、 環境変数GOOSにOS名を指定するだけでARM環境で動くLinuxバイナリを作成できます。

$ GOOS=linux GOARCH=arm64 GOARM=7 go build -o medit

システムコールの呼び出しが簡単

Golangにはシステムコールをいいかんじにラップしてくれているunixパッケージがあり、 システムコールを簡単に呼び出せます。 ptraceシステムコールを用いてプロセスへのアタッチするコードをC言語の場合と見比べてみましょう。

C言語でptraceシステムコールを用いたプロセスへアタッチは、<sys/ptrace.h>をインクルードすることで以下のコードでできます。 ptrace()の第3引数はcaddr_t addr, 第4引数はint dataとなっており、それぞれに読み出しや書き込みの対象とするメモリのアドレス、 書き込むデータを指定できるのですが、第1引数にPTRACE_ATTACHを設定したときは第3引数、第4引数がともに無視されます。 そのため、プロセスへアタッチする際にはそれぞれにNULLを指定する必要があります。

ptrace(PTRACE_ATTACH, pid, NULL, NULL);

Goではunixパッケージを使うと、以下のようなコードでptraceシステムコールを用いてプロセスへのアタッチができます。 Goでは不要な引数を指定しなくていいように、利便性を考えてシステムコールをラップしており、アタッチに使う関数の引数はひとつだけです。

sys.PtraceAttach(pid)

このようにGoではC言語を使うより簡単にシステムコールを扱うことができます。 Goにおけるシステムコールの扱いについては、少し古いsyscallパッケージを使ったものになりますが以下の記事が詳しいです。

ascii.jp

apk-meditでは動きが激しいアプリの動作を止めるために、ptraceシステムコールによるアタッチをattachコマンドを使ってできるようにしていますが、 メモリの読み込み、メモリへの書き込みにはptraceシステムコールを使っていません。 どのようにして、メモリ上のデータを検索しているのかは後ほど、解説します。

大きいバイト列から目的のバイト列を高速に検索するのが簡単

Rabin-Karp string search algorithmという高速に文字列を検索するアルゴリズムが bytes.Index()の内部で使われています。 これによって、複雑なアルゴリズムを自前で実装することなく、bytes.Index()を使うだけで高速にメモリ上のデータを検索することができました。

ja.wikipedia.org

GitHub ActionsとGoReleaserのおかげでバイナリを配布するのが簡単

これはGoの仕様によるものではなく、Goを使った開発を便利にしてくれるツールのおかげですが、 GoReleaserというGithub Releasesにバイナリを登録してくれるツールを、 GitHub Actions上で動かすことで、リリースバイナリを簡単に配布することができました。 以下のようなymlファイルを.github/workflows/以下に配置するだけで、GitHubにtag付きのコミットがアップロードされた際に、 GitHub Actions上でビルドが走り、GoReleaserがGithub Releasesにバイナリを登録してくれます。

name: release
on:
  push:
    tags:
    - "v[0-9]+.[0-9]+.[0-9]+"
jobs:
  goreleaser:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v1
        with:
          fetch-depth: 1
      - name: Setup Go
        uses: actions/setup-go@v1
        with:
          go-version: 1.14
      - name: Run GoReleaser
        uses: goreleaser/goreleaser-action@v1
        with:
          version: latest
          args: release --rm-dist
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

どうやってメモリを読み込んでいるか

Linux系OSにおいて/proc/以下には、プロセスの情報にアクセスするための疑似ファイルが置かれています。 /proc/$pid/maps/proc/$pid/memを用いて、特定のプロセスのメモリマッピングを取得し、メモリを読み出す事が可能です。 /proc/$pid/mapsには以下のようなフォーマットでメモリマッピング情報が載っています。 ここには、pidで指定したプロセスがメモリのどの部分に書き込み権限、読み込み権限を持っているのかという情報が記載されています。

sargo:/data/data/jp.aktsk.tap1000000 $ cat /proc/11283/maps
12c00000-12d40000 rw-p 00000000 00:05 23292          /dev/ashmem/dalvik-main space (region space) (deleted)
12d40000-133c0000 ---p 00140000 00:05 23292          /dev/ashmem/dalvik-main space (region space) (deleted)
133c0000-13700000 ---p 007c0000 00:05 23292          /dev/ashmem/dalvik-main space (region space) (deleted)
13700000-13780000 rw-p 00b00000 00:05 23292          /dev/ashmem/dalvik-main space (region space) (deleted)
13780000-14140000 ---p 00b80000 00:05 23292          /dev/ashmem/dalvik-main space (region space) (deleted)
14140000-2ac00000 rw-p 01540000 00:05 23292          /dev/ashmem/dalvik-main space (region space) (deleted)
6f181000-6f3a6000 rw-p 00000000 fd:01 221            /data/dalvik-cache/arm/system@framework@boot.art
6f3a6000-6f3bc000 r--p 00225000 fd:01 221            /data/dalvik-cache/arm/system@framework@boot.art
6f3bc000-6f4b3000 rw-p 00000000 fd:01 229            /data/dalvik-cache/arm/system@framework@boot-core-libart.art
6f4b3000-6f4c5000 r--p 000f7000 fd:01 229            /data/dalvik-cache/arm/system@framework@boot-core-libart.art
6f4c5000-6f4f6000 rw-p 00000000 fd:01 232            /data/dalvik-cache/arm/system@framework@boot-conscrypt.art
6f4f6000-6f4f9000 r--p 00031000 fd:01 232            /data/dalvik-cache/arm/system@framework@boot-conscrypt.art
6f4f9000-6f526000 rw-p 00000000 fd:01 235            /data/dalvik-cache/arm/system@framework@boot-okhttp.art
6f526000-6f529000 r--p 0002d000 fd:01 235            /data/dalvik-cache/arm/system@framework@boot-okhttp.art
6f529000-6f57f000 rw-p 00000000 fd:01 240            /data/dalvik-cache/arm/system@framework@boot-bouncycastle.art
...

/proc/$pid/memを使って、pidで指定したプロセスが持つメモリを読むことができます。 よくある誤解として、ptraceシステムコールを使ってターゲットのプロセスにアタッチ(PTRACE_ATTACH)し、 プロセスを止めないとメモリを読めないというのがありますが、 最近のLinuxカーネルではアタッチしなくとも、システムコールのopen()、read()、lseek() を使ってメモリを読み出すことが可能です。 apk-meditでは、open()、read()、lseek()を直接は使っていませんが、 内部でそれぞれのシステムコールを使用しているio.NewSectionReaderFile.WriteAtを使って、読み込み、書き込みを行っています。 メモリマッピング情報から読み込み、書き込みが共にできる部分がどこなのかを得て、/proc/$pid/memを使ってメモリを読み出し、ターゲットの値を検索しています。

おわりに

apk-meditが脆弱性診断に従事するエンジニアに広く使われるよう育てていきたいと思っています。 ぜひ、気づいたことがあればフィードバックしてもらえるとうれしいです。みなさまからのIssueやプルリクエストをお待ちしております。

RSGT2020へのスポンサーをしました

f:id:yusi:20200131145917p:plain

アカツキとRSGT2020

アカツキでエンジニアリングマネージャをしている島村です。

去る2020年1月8−10日に「Regional Scrum Gathering Tokyo 2020」(以下 RSGT2020)が開催されましたが、昨年に引き続きスポンサーをさせていただきました!

Regional Scrum Gathering Tokyoとは

  • スクラムを実践する人が集い垣根を超えて語り合う場を提供するという目的によりコミットしています。

参加した方はわかると思いますが、通常のカンファレンスとは違い、Gatheringの名を示すように寄り合い所のような雰囲気が強くあり、セッションも深く考えさせられるようなものが多いです。

またセッション中に隣の人と語りあう時間をあえて用意するスピーカーもおり、そのような空気を一体となって作ってくれていました。
廊下やロビーのソファーなどで活発に意見交換がされているのも印象的でした。
まさに垣根を超えて語りあう場が形成されていたのです。

f:id:yusi:20200110121939j:plain
私達アカツキはこの理念に共感し2年連続でRSGT2020にスポンサーしています。*1

スポンサーをすることによりこのような素敵な場が毎年継続されればと思いますが、副次的にはRSGT2020に訪れる方々と出会い、さらに一緒に仕事ができるよう機会を得られればという面もあります。

参加してみて

筆者の私はというと1日目は丸々仕事で出れず、2日目も午前中は参加できませんでした。調整能力の低さを露呈してしまいお恥ずかしい限りです。

直接の参加はできなかったもののSNS上での盛り上がりは見ていました。

基調講演でのJames Coplien氏の「The Ten Bulls of the Scrum Patterns」の話は興味深く、スクラムと十牛図の語りには強く興味をもっています。
スクラムの本質を改めて考えさせられる場だったようで、参加できた同僚から改めて聞きたいと思います。

また二日目の基調講演のSahotaさんの「Lost in Translation: The Manager’s Role in Agile」も二日目の流れの源流になったとのことでSNS上で盛り上がっていました。
気になったワードは「ヒエラルキーをひっくり返す」「XY理論」「No One Gets Left Behind
一つ一つのキーワードが深く考えさせられるものです。

私は午後から参加したのですが、Sahotaさんからの流れのから組織変革とリーダーシップ、自立したチームとその価値観、マネージャの関わり方などのセッションが多くあり、一つ一つのセッションだけでなく、連続で聞いたときにより効果がでるようなセッションプログラムでした。
*2

いくつか印象的だったセッションの感想を。

キャッチーなタイトルなので興味本位で参加させてもらったが、会社単位でこの改革をしたことに脱帽です。

たしかにマトリクス組織よりチーム主体にしたときの方が小さく最適化はしやすいのは経験上あります。が、ここまで権限委譲をしたことはなく、チームがクリエイティブなところに集中できるようにマネージャ(部長)に権限と役割をもたせていました。「人員配置」や「予算」までも委譲することは考えたことがなかったです。

デメリットに1on1の実施が減っているということが記されていたので、やはり管理周りが弱くなる課題はあるようです。

また人材もチームや個人に裁量があり、体験入部制度で社内の流動性が高まる方向にあったようだが「メンバーの固定化」が弱くなることへの影響も気になりました。異動する個人を見ればモチベートにはなるので一長一短なのでしょう。

さらにマネージャ(部長)のチーム化した組織運営チームの例はとても興味深かく。職能の部長が本部全体を見るようになるので視座もあがりキャリア形成には良いかとおもいますが、「チームをまたがるところ」に課題があったようで、この組織運営チームがどこまで関与できるのか、上記の課題にどこまで関与できるのかポイントになってくるのでしょうか。

 チームで転職した及部さん(@TAKAKING22)の話しは興味があったので楽しみに参加しました。
冒頭から「チームの死とは」という疑問を会場に投げかけ、プロダクトに依存しない「Team-Based TEAM」を提唱していました。
ずっと会社員で働いてきた自分としては「会社・組織」「作るべきもの」が大前提で、それに最適化したチームやメンバー、作り方を考えることがあたり前という概念があり、プロジェクトが終われば「チームの解散(死)」は当たり前にくるものと思っていいて考えたことがなかったです。

タックマンモデルが、その通りに状態遷移するチームは2%であることが、改めてチームの継続は難しいこと考えさせられました。ただそれ以上にプロダクトが終わってもチームを死なせなかったこのチームの想いの強さには尊敬します。

また安定したチームにするには人材の固定ではなく、学習できるチームであることと説明があり、本質は「生物における新陳代謝をチームに実装する」入れていくとのこと。
チームで学習するというのはとても難しく様々な前提条件が必要になることもあるが、改めて自分のチームの一つの方向性を知ることができたのは大きいことでした。

 

他にも刺激的なセッションは多く、全体的には自分たちの組織とマネージャ、チームのあり方、またその中でどうやってチームで価値を創出していくかを考えさせられた1日でした。

最後に

f:id:yusi:20200203103505j:plain

アカツキでは、アカツキらしいプロジェクトマネジメント(≒チーム開発)を探求するメンバーの集まるコミュニティ four *3 があります。

今回のRSGT2020にはfourメンバーが多く参加し、現場に各々が持ち帰ってきており今後が楽しみです。
今年の開催中に発表された、来年のRSGT2021のチケットも既に多くのメンバーが購入済みの状態です。

ぜひ一緒にハートドリブンな世界を実現するエンジニアリングマネージャ、組織の成長、課題解決に取り組んでくれる仲間を募集しています。興味のある方はぜひ連絡をください。

hrmos.co

*1:2019年はシルバースポンサー、2020年はロゴスポンサーとなっています

*2:きっと運営の意図した流れだったのでしょう。熟練した運営はここまで考慮できることに驚きます。

*3:名前の由来は
1. 価値を出すために
2. 開発メンバーのために
3. アカツキのために
4. 自分たちのマネージメント力の強化のために
この4つの価値観を大切にするということからです。

モブプログラミングワークショップを社内向けに開催しました

f:id:yusi:20200121000011p:plain
アカツキでエンジニアリングマネージャをしている島村です。
普段はソーシャルゲームアプリの開発やエンジニア組織への取り組みなどをしています。

さて今回は自分のチームのエンジニアを対象にモブプログラミング(以下モブプロ)のワークショップを開催したのでその取り組みについて紹介させていただきます。

モブプログラミングワークショップ開催について

今回の講師として、日本のモブプロの先導者として著名な及部さん(@TAKAKING22)にお願いしました。

モブプロを知らない方に端的に説明すると、モブプロとは「チーム全員で、同じ仕事を、同じ時間に、同じ場所で、同じコンピュータですること」とのことです。

今回、及部さんにお願いした経緯としては、ゆのん(@yunon_phys)との1on1時にチームのスキルトランスファーがうまく進まないと相談していた時に、「及部さんにモブプロのワークショップでもやってもらう?」と案をもらったのでお願いすることに。
早速Messengerで連絡をとり快諾をいただき、1回の顔合わせとリモートのMTGを得て開催の運びとなりました。

みなさんも気軽に相談してみてはいかがでしょうか。

モブプログラミングの準備

当日までに準備したこと
  • メンバーの対象者選定とチーム分け
  • ワークショップの課題選定(自販機)
  • スプリントプランニングに「モブプロ研修 4時間」を組み込む。

対象者はC++エンジニア10名とRubyエンジニア3名の13名。
これを3チームに分けました。

  • C++エンジニア 5名 * 2
  • Rubyエンジニア 3名

課題は、言語が違うチームになるので共通で「自販機」としました。

当日の準備
  • 机3つと人数分の椅子
  • モニター3台
  • ホワイトボード3枚
  • 人数分の付箋とペン
  • お菓子

スケジュールとしては以下の流れで全行程4時間。

  • 15:00-15:30 Head Firstモブプログラミング
  • 15:30-15:40 ワークショップ準備
  • 15:40-16:40 モブプログラミングワークショップ 1
  • 16:40-16:50 中間ふりかえり&質疑応答&休憩
  • 16:50-17:50 モブプログラミングワークショップ 2
  • 17:50-18:20 成果共有&ふりかえり
  • 18:20-19:00 現場でのモブプログラミング

及部さんから事前に「初めてモブやると疲れるから研修おわったらそのまま帰れるようにしたほうがいいですよ」とのことで定時の19時に終わるように設定しました。

ワークショップの内容について

及部さんよりモブプロの歴史や事例を交えつつ注意点など説明いただき、その後、課題やワークショップのルールなど進行の説明があり、ワークショップの実施という流れです。

進めるにあたった以下を強く意識して実施してもらいました。

f:id:yusi:20200118020128p:plain
「HRTの原則」はアカツキでも大事にしていることです。

ルールは「テストすること」だけ。
RubyチームもC++チームも普段から単体テストは書いていたのでここは特に抵抗なく進めることができました。

ワークショップのスライドは公開の許可を頂いているのでぜひスライドを参照していただければです。

drive.google.com

モブプロ実施

f:id:yusi:20200114155635j:plain

モブプロ中は真剣に話す場面や笑顔で意見を交わす場面など見られました。時折「やったー」という声が聞こえてきます。
普段一緒に仕事しているメンバーなのでチームビルディングが必要のない分スムーズに始められた印象です。

一つのモニターを一人がタイピングして、周りに立ちながらアドバイスする姿は、障害対応しているときの姿に近いですね。一つのタスクを複数人数で取り組むときは自然とこの形になるのですね。

休憩を挟んだ2回のモブプロの時間を終え、お互いのチームの成果を報告し振り返りを実施しました。

以下はあるチームのふりかえり結果です。どのチームも「疲れた」は出ていましね(笑
f:id:yusi:20200114182827j:plain

その後、ふりかえりででた参加者からの疑問や疑念に対するクエスチョン(を、最後の及部さんからのまとめプレゼンでアンサー*1 する形となりました。
 

開催場所が社内のカフェのあるラウンジで開催したこともあり、他チームのエンジニアがフラッと見に来て興味深そうに見学していきました。そういう所から波及もしてくれるとうれしいですね。

感想

気になったことは「モビングの重要なポイント」として話された以下のところ。

f:id:yusi:20200118023948p:plain

リソース効率とフロー効率に関しては@i2keyさんの以下の資料がわかりやすいですね。

自分たちのプロジェクトを見返すとリソース効率に傾倒しているので改めてチームで話し合ってみるのもおもしろいと思いました。

またOutcomeについては最近よく話されるようになりました。
スクラムで進めているのであればPOとユーザストーリーにより担保されている部分もあるのでしょうけど、スクラムでないチームでも成果物(Output)とそれに関するOutcomeを話すのはとても有効と感じます。先日のRSGT2020でもギルドワークスの中村洋さん(@yohhatu)がその観点からの話もされていました。
speakerdeck.com

暗黙知のくだりもSECIモデルをベースに話されており、価値観としてはスクラムと通じるところがあることがわかります。

今回の悩みであったスキルトランスファーの課題にも効果があることが伺えますし、メンバーからもその点は感触を掴めたという感想がありました。

まとめ

今回、実施前はメンバーからはモブによるワークが非効率に感じていると声がありましたが、最終的には全員ポジティブな結果が返ってきました。
実施した2日後にはモブを試すチームも出てきており、小さな変化は起きている感じがします。

及部さんの資料にもありましたが「モブプログラミングを現場に導入するか どうかは正直どうでもいいことです。 」で「(分担作業とモビングを)仕事の質やチームの状況に合わせて 使い分けられる方がチームとして強い」ということが大事に思います。

分担開発(リソース効率)とモビング(フロー効率)の使い分けを柔軟に選択できるチームは強そう。

本質は、チームが生み出す価値を最大化するために何ができるか、何をすべきかをチームで考える。そのためにシンプルなコミュニケーションの機会を増やし、チームで判断し続けることが重要であることを知ることができました!

最後に

アカツキでは 一緒にハートドリブンな世界を実現するエンジニアや、組織の成長、課題解決に取り組んでくれる仲間を募集しています!

aktsk.jp