スマフォアプリゲーム開発における問題と対策 その１

自分が関わっているスマフォゲーム開発で起こる様々な問題と、それをどのようなツールで解決しているのかを共有したいと思います。

同僚と話していたときに、他のチームがやっていて便利な事が共有されたらいいよねという話があったので、まず自分のチームのことから共有したいと思います。
pythonで開発していますが、どこでも起きうる一般的な問題が多いかなと思います。サーバのエンジニアをしているので若干サーバ視点です。

# 環境

* クライアントはcocos2d-x
* サーバは python 2.7 + Django 1.8
* クライアントはサーバにAPIで接続
* サーバとクライアント開発は別グループ (それぞれ5人くらいずつ)
* ソースコード管理はgit

# 問題と対策メニュー

| 問題 |対策 |
|:-----------|:------------|
|いつの間にか自分の書いたコードが意図しない形で変更されている|コードレビュー|
|レビューがコーディング規約違反の指摘でうめつくされる|コーディング規約に準拠した整形ツール|
|レビューしていいコードなのか、まだ途中なのかわからない|レビュータイトルに[WIP]を追加|
|開発環境デプロイ後にクライアントの方からサーバがエラーで繋げないと言われる|JenkinsでAPIテスト・結合テスト導入|
|マスターデータの頻繁な変更とデータの不整合|自動モデル作成とJenkinsでバリデーション|
|クライアントの方が、サーバが作成したAPIの仕様がわからない|APIドキュメント自動生成|
|APIを試しに叩いてみたいが、URLやポストパラメ設定が面倒|APIドキュメントでリクエスト発行|
|誰がどのタスクを現在やっているのかわからない|backlogで管理|
|将来やるタスクが忘れ去られてしまう|backlogで管理|
|クライアントからサーバにエラーが起きていると言われるがどのようなリクエストを投げたかわからない|リクエストの通信ログ取得|
|リリースされる前に、遅いAPIを洗い出しリリースされるのを防ぎたい|開発環境におけるNew Relicの導入|
|サーバの性能が出るか確かめたい|負荷試験|
|本番環境のユーザを開発環境に再現したい|管理画面でユーザexport/import|

# いつの間にか自分の書いたコードが意図しない形で変更されている

１人や２人くらいでコードを書いているときは常にお互いが連携できており、コミットログを追いやすいのでコードレビューを実施しなくても問題無い場合が多いのです。
しかし多人数（自分のチームだと６−７人）だと、他の人のコードをいじったり利用したりすることも多く、作成者の意図した使われ方をしないで負荷などが高まってしまったり、バグを出してしまいます。
また何より、１人だけがコードを理解している状態だと、障害発生時の対応が遅くなります。

上記の問題を解決するためにコードレビューを導入しています。
**Stash**を利用しておりStash内ではプルリクエストと呼ばれております。

以下のようにプルリクエストを機能ごとになげて、チームメンバーにレビューしてもらいます。

![pr.png](https://qiita-image-store.s3.amazonaws.com/0/30079/551636f7-e6d0-2878-f0f7-d6d9eaa40d16.png "pr.png")

いつマージできるかのタイミングですが、自分のチームでは、レビュワーが2人以上承認したらプルリクエストした本人がマージできるようにしております。
全員がレビュー承認すると、承認までの時間がかかりすぎているのでそのようにしています。

ただ、承認するというプロセス自体に、プルリクエストを投げた人に待ち時間が発生するのは確かなので、小さな変更などはレビューしないでマージできる約束になってます。

以前みた海外のブログでコードレビューはマージした後にしているというのもあり、確かにそういう方法もあるなと思ったのですが、ここらへんはチームの状況によるかなと思います。

# レビューがコーディング規約違反の指摘でうめつくされる

チームではPEP8に準拠するようにしております。

その上で、コードレビューを始めると問題点になるのが、コーディング規約に違反していますというレビュー指摘です。
この指摘自体はまっとうなのですが、するほうもされるほうも、時間の無駄の感じがあり不毛です。

**レビューする前**にコーディング規約に違反していないプルリクエストを上げれば問題は回避できます。

上記を達成するには以下の方法が考えられます。

1. gitでコミット時にhookをかけてチェックする
2. Stash側でプルリクエストが行われる前に、コーディングチェックを走らせ、違反したものは弾く
3. エディタでPEP8違反を自動でチェックしてくれるプラグインを入れる

1番と3番の方法をチーム内では推奨しております。
1番を実施するには、autopep8でコミットした後に、コミットされたファイルでコーディング違反のあるものを自動で修正してくれるようにします。
細かいやり方は別の記事で書きます。

# レビューしていいコードなのか、まだ途中なのかわからない

初期のころは、コードレビュー時のプルリクエスト一覧を見た際に、レビューしていいものなのか、一時的にレビュー前にあげたものなのかが、タイトルではわかりませんでした。

これを解消するために、レビューしていいものには[Review]、まだレビューしてほしくないやつには[WIP]とつけるようにしました。
WIPはWork in Progressの略です。

# 開発環境デプロイ後にクライアントの方からサーバがエラーで繋げないと言われる

コードレビューをしても、バグは入り込むものです。これを防ぐために、マージ後にJenkinsでテストが走ってOKなら開発サーバにデプロイするようになっています。

以下の環境で社内に別マシンのMac上でJenkinsをたてて、Stashでのdevelopブランチの変更をポーリングして、15分おきにデプロイしてます。StashからWeb Hookで変更されたらすぐにテストを走らせたいのですが、セキュリティ上やコストの関係で社内にあるので、ポーリングしています。

![server_pptx.png](https://qiita-image-store.s3.amazonaws.com/0/30079/edec1af6-019a-d780-0d41-045065f862a1.png "server_pptx.png")

テストは以下のテストをpy.testで走らせてます。

* **APIテスト**: クライアントに公開されているAPIをテストする。サーバエンジニアは新しいAPIを作ったら必ず疎通確認以上のAPIテストを作成してもらってます。 数分で終わるようなテストです。
* **結合テスト**: MVCで言う、Model以下などロジック部分をテストしてます。項目が多いのと、py.testでDjangoをテストするといちいちデータを消去してからテストするので40分以上かかってます。並列化する必要がありますがまだしてません。

結合テストは時間がかかりすぎるので、APIテストが通ったら開発サーバにデプロイしてます。

# マスターデータの頻繁な変更とデータの不整合

ゲームのマスターデータというのはユニットのパラメータだったりクエストのパラメータだったりするデータです。
もとのファイルはExcelですが諸事情により複雑になっています。以下が概要となっております。

![masterdata.png](https://qiita-image-store.s3.amazonaws.com/0/30079/eb6aea62-c31b-e2be-0538-d4dad0131136.png "masterdata.png")

サーバコードがマスターデータを読み込み、コード上で使うようになっております。
いちいち更新されるたびに、手動でサーバコードを更新しているのは時間の無駄なので、Jenkinsで自動で更新するようになってます。

マスターデータで他に、問題となるのは、頻繁に、マスターデータにカラムが増えたりする事です。例えば、ユニットのマスターデータにスキルがつきスキルIDが増えたみたいな感じです。
対策として、サーバ側では、１つのマスターデータに１つのモデルソースコードを対応させており、機能拡張する場合はそれをラップしてメソッドを書くようにしてます。

例えば以下のような形です。

    application/module/unit/models/unit.py  # ユニットマスターデータ用のモデル(Unit)
    application/module/unit/models/unit_wrapper.py  # ユニットモデルのラッパ(UnitWrapper)
    application/module/unit/models/__init__.py 

__init__.pyは以下のように定義します

    # -*- coding:utf-8 -*-
    from __future__ import absolute_import
    from __future__ import unicode_literals
    from .unit import UnitWrapper as Unit

そうすると、外部から参照するときに、以下のようにすれば、UnitWrapperがあたかもUnitとして読み込めます。

    from module.unit.models import Unit 

このunit.pyの部分はスクリプトを走らせれば自動で作ってくれるようになっているのでマスターデータの更新に煩わされる事はありません。
この部分はJenkinsで自動化はさせてませんが、もちろん自動化も出来ます。

# クライアントの方が、サーバが作成したAPIの仕様がわからない

サーバ側がAPIつくってその仕様(リクエストパラメータやレスポンスパラメータ)が確認できないと困ります。
Confluenceなどに書くパターンもありますが、常に更新されていないと意味をなさないので、ソースコードと連動していることが好ましいです。

Swaggerなどがありますが、自分のチームでは、自前で管理画面上で実現しています。

APIが一覧表示されています。新しいAPIを作ると自動で追加されます。
![api_1.png](https://qiita-image-store.s3.amazonaws.com/0/30079/ea78faa2-c1c0-8524-2c2f-62a58b6d6c53.png "api_1.png")

player/signupのAPIドキュメント例

![api_2.png](https://qiita-image-store.s3.amazonaws.com/0/30079/8a5c91a3-c972-f5d1-af5d-2a7f57e7940f.png "api_2.png")

![api_3.png](https://qiita-image-store.s3.amazonaws.com/0/30079/7ab003f6-2e1c-63ad-7852-2709187ae168.png "api_3.png")

上記のように、リクエストとレスポンスがわかるものはチームメンバーが作ってくれました。

# APIを試しに叩いてみたいが、URLやポストパラメ設定が面倒

開発している際にAPIを叩いてレスポンスを確認したいときがあります。
ChromeのプラグインでAdvanced REST Clientなどがありますが、日々APIが追加されていくなかでメンテナスするのも大変です。

![arc.png](https://qiita-image-store.s3.amazonaws.com/0/30079/81fae3ea-fff4-1502-803a-ce500484cde4.png "arc.png")

さきほどあった管理画面のAPI一覧でリクエスト発行もできるようになっております。

![api_4.png](https://qiita-image-store.s3.amazonaws.com/0/30079/8651c367-1b72-bb51-19a8-9bfc80424495.png "api_4.png")

新しいAPIが加わったときも自動で追加されます。さらにパラメータ候補も５つまで保存できるので異なったパラメを試したいときも重宝します。一度設定したらブラウザに自動保存されます。
複数のパラメを試せる部分はメンバーが追加開発してくれました。


ながくなってしまったので「その２」を書いていきます。