10980_ext_01_0.jpg?753041ac4d0bc2ffa52059d1677fdd98

「Ameba Ownd」開発
“可読性”がGo言語採用の決め手

Ameba Owndプロジェクト
生沼 一公

Javaの置き換えでソースコードを半分に

サイバーエージェントに入社して最初の2年間は、アメーバピグの負荷対策を行っていました。その後、ブラウザゲームのサーバサイドの新規立ち上げに携わりました。アメーバ内でユーザー数の多いゲームを参考にして別のゲームを立ち上げる流れがあったのですが、そのままのシステム構成だとセキュリティ的な問題や開発効率が上がらないという懸念があったため、フレームワークをSpringMVCに置き換えました。SpringMVCにすることでソースコードの行数が半分になり、元のフレームワークが抱えていたセキュリティ上の問題も解消することができました。

その後、2014年の7月頃から、Webサイト無料制作サービス「Ameba Ownd」の立ち上げに関わり、2015年3月にリリース、現在は日々改善を行いながら運用しています。

ちょうどその当時、Go言語がインフラ界隈でトレンドが来ていて、主席エンジニアの名村と相談し検討した結果、「Ameba Ownd」 でGo言語を採用することにしました。

Java vs Node.js vs TypeScript vs Go

10980_ext_09_1.jpg?8439925648f31649bde9ba6391bc510b最初は、Go言語以外にNode.js+TypeScriptとJavaを検討していました。

まず、Node.jsについては社内でもノウハウがあり、実績もありましたが、「Ameba Ownd」が多機能、大規模になるだろうと、立ち上げ時に想定していたので、スクリプト言語だとソースの可読性の面で不安がありました。それを補う意味で静的型付けのTypeScriptも検討していましたが、当時はコンパイル速度が遅く実用には耐え難いと判断しました。現在はかなりコンパイル速度が速くなっているので次に技術選定の機会があればNode.js + TypeScriptを選択するかもしれません。

Go言語については、実際に簡単なアプリをGo言語で作ってみたところ、自分の感覚にフィットしたのが大きかったです。今回のプロジェクトの要件としては、静的型付き言語の方が良いと考え、Go言語で開発を進めることにしました。

決め手は可読性

Go言語を正式に採用した一番の決め手は可読性の高さです。今回のプロジェクトは大規模開発になることが想定されました。大規模開発になると、コードを書く時間よりも、他人のコードも含めコードを読む時間の方が長くなってきます。その時に、Go言語の可読性の高さは大きなメリットになると考えました。

Go言語はそもそも静的型付き言語なので、ある程度の可読性は確保されていることがわかっていました。そのため、実際に運用する際の予測を立てやすかったというのもありますね。

実際に「Ameba Ownd」の開発では、可読性の高さがプロジェクトに与える効果を実感できています。概ね「Ameba Ownd」では、Go言語を導入して良かったと思います。これまで私が実際に開発で使ってきたプログラミング言語の中でも、可読性は一番高いと感じています。

ただ、Go言語は他の言語とは異なる側面があり、特にJavaのようなオブジェクト指向言語の機能を期待すると痛い目にあいます。例えば、Goには継承という概念がなく、AとBという構造体があった場合、AのメソッドをBで使えるようにできますが、それは継承ではなくあくまで委譲です。

また、interfaceという仕組みを使えば継承を使わなくても「Aという構造体(型)にXYZというメソッドが定義されていて呼び出せるか」はチェックすることができます。継承は、多重継承した場合にクラスの階層構造が複雑になり、メソッド呼び出しの解決のルールも複雑になりますが、Goではそのようなことはありません。

フレームワークのメリットとデメリット

10980_ext_09_3.jpg?9bfec55a5d15575d42d50f509b96e278Go言語には標準で様々な機能が提供されているのが魅力の1つと言えます。ただし、それらの機能に対応していないフレームワークもあるので注意が必要です。

私のチームではRevelというフレームワークを採用しました。Revelでは、基本的にrevelというコマンドでサーバーを立ち上げるなど、フレームワークがGo言語の機能をラップしてくれています。そのため、Go言語のプロファイリングを行うツールがそのままでは使えないという問題もありました。このようにフレームワークによっては、Go言語のエコシステムを100%使えない場合があり、もどかしさを感じることがあります。

ただし、Revelはテスト機能が充実していて、「Ameba Ownd」のコード品質の向上には大いに貢献しています。具体的には、標準でサーバを立ち上げて、そのサーバに対してhttpクライアント経由でテストを行う仕組みがフレームワークに備わっています。例えば、リクエストを投げたら、JSONが返ってくるという感じで、APIサーバのエンドツーエンドのテストを簡単に実現することができます。

このRevelの仕組みがあったおかげで、「Ameba Ownd」では、新しい機能が次々と増えていますが、チーム全員がテストを書き続けることができています。これまでの開発に比べると、テストが書きやすいというフレームワークの特徴もありますが、実際に私自身は人生で一番テストを書いた気がしています。

また、今Go言語のフレームワークとして試してみたいのはgojiですね。net/httpパッケージをラップしているだけなので、Goのエコシステムをそのまま使うことができ、結果全体として開発効率は上がると思います。

ちなみに、「Ameba Ownd」はGo言語以外にもデプロイでPython、APIドキュメント生成でRubyを使っています。しかし、ほとんどはGo言語で実装しています。

次のバージョンのPythonにも期待

開発ではvim-goを使っているメンバーが多いですね。GitHub製のAtomでGoのプラグインを使って書いている人もいます。私自身はIntelliJを使っています。Go言語の場合、どのエディタでも同じ感覚で書けるのが特徴ですが、vimとEmacsはサポートが一番手厚いと感じています。

また、実際にサービスを立ち上げてGo言語の良さを感じているのは、スクリプト言語に比べてサーバ側のランタイムの消費メモリが少なく、パフォーマンスが良い点ですね。

特にバックエンドのサーバ部分では、Go言語がフィットしていると思います。普通にWebアプリケーションを作るのであれば、スクリプト言語の方が生産性は高いように感じますし、Go言語の場合ジェネリックスの機能がないので、そのような機能を求めるならJavaの方が適しているでしょう。やはりプログラミング言語の特徴にあわせて適材適所で使い分けていくのがいいと思います。

「Ameba Ownd」でGo言語を使ってみて、可読性やシンプルさ、標準のツールが充実しているという点で、非常に習得しやすいと感じました。ただ、Pythonの次のバージョンで静的型付き言語に近い機能をサポートする予定になっていて注目しています。そうなると今後Pythonも開発の選択肢に入ってくる可能性もあると考えています。