開発効率化への道は一日にしてならず

CyberAgent エンジニア Advent Calendar 2014の8日目です。

7日目はoinumeさんによるGoLangでJavaのenumっぽいライブラリ作った話 - おいぬま日報 でした(弊社もGoがだいぶきてますねぇ)。

サイバーエージェントの技術本部に所属している@stormcat24です。特定のプロジェクトにはジョインしてなくて、技術的な支援とか特命的ミッションをしています(簡単に言うと雑用)。サービスに関わらせてもらう日は来るのでしょうか。

さて、この時期では自分のミッションの一つである開発効率化というテーマで書きたいとおもいます。思えばこの1年半くらい様々な取り組みをしてきたような気がします。

Vagrant

Vagrantは仮想環境の構築を支援するツールで、ChefやAnsibleによって定義したミドルウェアやツールの構成管理をVagrantで構築したVM上に一発で用意しましょうってやつです。

組織としてのVagrantの導入目的として以下のようなものがありました。

  • 本番環境と限りなく近いローカル環境で開発できるようにする
  • 開発環境をプログラマブルに定義する
  • 環境の差異に起因する鬱陶しい問題がおこらないようにする
  • 新たにジョインしたメンバーの、スタートアップまでの時間を削減する

実際、導入したことによってこの目的自体はだいたい果たせたような気がしていますが、うまく運用するにはまた違う課題が浮き彫りになりました。

トラブル時の対応

まず簡単に構成について紹介してしておきましょう。

  • Vagrantでミドルウェアやツールをプロビジョニング
  • それに加えフロントエンジニアには、サーバサイドのコードをビルドしてVM上のAPサーバ(Jetty等)にディプロイ
  • フロントエンドのコードはVagrantの共有ディレクトリの機能を使ってVM間で共有してつなぎ込みをする

この構成ではVagrantやアプリ全般に精通したメンバーならばあまり問題にはなりませんが、逆に言えば問題が発生した際に何が原因なのか?というのは全貌を把握した人でないと厳しいことになります。Vagrant起因なのかVirtualBoxなのかネットワークなのか、またDBなのかアプリ自体なのか。フロントエンジニアからVagrant推進担当に問い合わせが来て、調べてきたけども普通にアプリの問題だったとかよくありました。

また、このような問題を減らし常にアプリが動く状態にしておくにはDBマイグレーションの仕組みをちゃんと用意しておくとか、それなりの運用レベルを持っていることが求められます。

理想を追いすぎず、適当に妥協する

例えば、長く運用してきて重量級になってしまったJavaプロジェクトで同じことをやろうとすると、JVMが大量にメモリ専有してVMに4GB割り当てないとどうにもならないとか、ものすごく良くない意味で富豪的になってしまいました。プロジェクトによって妥当な線を狙って、適当に妥協するのが良いでしょうね(ミドルウェアだけ入れるとか)。 Vagrantはレガシーなプロジェクトには決して優しくないってことを頭の隅にでも置いておいてもらえればと思います。

Aeromock

Vagrantで環境を簡単につくることができるようになりましたが、フロントエンジニアにとってはエラーで開発が止まるという状況を改善することができません。そんなわけで自分が勝手に作ってプロジェクトに投入したのがこのツール。

フロントエンドがサーバサイドに依存せずに開発することができるモックサーバです。最初はゲームのJavaプロジェクトで徐々に導入していきましたが、最近は大小問わず導入20プロジェクトくらい超えたでしょうか。

フロントエンドを救い、それぞれの専門領域に専念させる

僕がこのAeromockを作った目的はJava系プロジェクトで分業された体制の開発において、特定のチームに偏りがちなパワーバランスを是正することでした。これまではサーバサイドが無いと開発が始まらないということが多く、フロントエンドにとってはアイドルしてしまう時間が多くなり自らのリソースを有効活用できないことにありました。

そのような状況であるにもかかわらず、スマートフォンアプリ開発においてフロントエンドに求められるクオリティはシビアです。しかもフロントエンドはここ数年で異常なまでのスピードで高度化してきたため、その専門領域に注力できる状況にないというのはリスクでしかないのです。Aeromockはフロントエンドを救い、かつ遊ばせないためのツールです。

意識的なインタフェースベースの開発を

Aeromockを使った理想的な開発は、サーバサイドとフロントエンドが目的のインタフェースに向かってそれぞれが独立して開発することにあります。新規や初期段階からAeromockを使ってくれたプロジェクトはこれができていますが、導入時点でかなりの資産(負債も)があったプロジェクトは、どうしてもフロントオンリーで動かすことだけが目的になってしまいがちなのでインタフェースベースの開発からはちょっと遠ざかりがちです。

動かすためにデータファイルを作るのではなく、仕様としてデータファイルに落とすことが重要。ウチのようにサーバサイドとフロントエンドが分業されている開発においては、両者を取り持つデータ仕様は何事にも代えがたい資産なので、このスタイルで開発していけるように教育的指導が必要だなと思います。

(この辺の話は今夏のDevLOVE甲子園でもしたので、そちらのスライドを参照されたし)

ネイティブ開発も支える?

このAeromock、最近では重い腰を上げてProtocol Buffersにも対応しました。スマホアプリのパフォーマンスは本当にシビアで、特にUnityなんかではJSONパースが絶望的に遅いため、Protocol Buffersやmessagepackといった軽量フォーマットを採用することが多いです。これでProtocol BuffersのUnityプロジェクトであればサーバサイド無しで開発が可能ですね(・∀・)。

Docker

これはまだ組織的にはまだまだですが、Dockerを開発に利用するユーザーが増えています。かつてVagrantの組織的導入を始めたあった自分ですが、最近自分はVagrantまったく使わずDockerで開発していますw

当方、Mac環境なのでboot2dockerで1枚かませなきゃいけないですが、MySQLとかRedisとかCassandraとかモンゴ(ryとかのミドルウェア郡を少ないリソースで構築することが出来ます。複数コンテナ使うことが普通なので、Figでコンテナ管理すると良い感じです。

Dockerといえば、最近流行りのCIツール(CircleCIwercker)ではDockerがサポートされています。CircleCIの方は組織的な導入を検討中です。

何のための効率化か?

効率化ミッションをやる者にとって注意しなくてはいけないのは、効率化が何のためのものであるか?ということを意識すべきだろうということです。

「迅速にユーザーへクオリティの高いサービスを届けるため」

「開発における余計なコストを削減するため」

「ボトルネックを抱えている開発者を助けるため」

「長期的に運用する上で、誰が見てもわかりやすく、保守しやすい状態にするため」

色々あります。技術を試すだけの試みになってしまうのはあまりにも惜しいし、純粋なコスト削減だけのためになるのも勿体無い。多角的に見て、一つでも多くのステークホルダーが幸せになる道を模索するべきだと思います。

「開発効率化への道は一日にしてならず」ですね。

さて、明日9日目は若手の有望株であるhorimislimeがやります!