10周年を迎えるモバイルゲームのフロント開発の軌跡

サイバーエージェントのゲーム・エンターテイメント事業部(SGE)に所属する株式会社QualiArtsでフロントエンドエンジニアをしている小阪です。本記事はQualiArtsの定期ブログ「QualiArts Tech Note」第11弾の記事となります。QualiArtsでは会社で使われている様々な技術の知見をブログで紹介しています。興味のある方は、QualiArtsとタグの付いている他の記事もチェックしてみてください。
QualiArts Tech Note

はじめに

ファーミー」というゲームをご存知でしょうか?今年の12月で10周年を迎えるQualiArtsが開発運営を行う農園ゲームです。実は10年続くゲームというのは業界でも稀で、古くからの根強いファンに愛されロングヒットをし続けるQualiArtsの主力ゲームタイトルの一つです。


「ファーミー」がリリースされた2011年、スマホはまだ20%程度しか普及しておらず、いわゆるガラケーがまだまだユーザーの大多数を占めていたので、「ファーミー」も当初はガラケー向けブラウザゲームとしてリリースされました。


そこから約10年、端末は驚くべきスピードで進化し、それに伴って画面で表現できることや 通信容量、処理スピードなどが大きく変わり開発の手法も大きく変化していきました。


今回はそんな「ファーミー」のフロント開発の歴史とともに開発手法がどのように変化していったかを振り返りながらご紹介いたします。


フェーズ1ガラケー時代

一部、リトルフェローズという「ファーミー」で人気がある動物のきせかえのようなコンテンツを例に話を進めていきます。(厳密にはリトルフェローズはガラケーにはなかったコンテンツなのであくまで例として捉えていただければと思います。)


フロント開発におけるスマートフォンとの大きな違いを4つ


  • テンキー十字キー操作のみ
  • 容量制限
  • JavaScriptが使えない
  • 非同期画面更新ができない

  • 一つずつ比較して見ていきましょう


    テンキーと十字キー操作のみ


    農園ゲームですので作物を植える場所を選んで、そこから植えたい種を選んで植えるという作業があります。スマホに最適化されたUIだと数タップで完了しますが、ガラケーの場合リストの位置次第でとんでもない回数のボタン操作が必要となります。図のように別のリンクなどが入り込むとその回数はさらに増えます。この操作性で苦労するのは開発側というよりどちらかといえばユーザー側でした。今こんな操作性のゲームをリリースしたらユーザーは絶対にすぐ離脱してしまうでしょうね。


    容量制限


    スマホになってから1ページのページの容量はそこまで気にする必要がありませんが、ガラケー時代には容量が大きすぎて突然画面が真っ赤になりそこから操作不能になることが頻繁に発生していました。

    1ページの容量だけでなくキャリアごとに仕様の異なるCSS、1バイトでも容量を削減させるためカタカナは全て半角文字に変換するなど涙ぐましい努力が必要でした。(いまだに「ファーミー」のアイテム名で半角カタカナの文字が存在するのはその名残です)

    また容量制限があるので画像も1ページに10枚も20枚も表示させることは難しい場合も多数存在し、そういったケースではページングを多用し対処していました。


    JavaScriptが使えない

    これがガラケーとスマホの最大の違いでしょうか。

    端末側で処理がほとんどできないので何かユーザー側で変更を加えるたびに、通信しなくてはならず、後述の非同期画面更新もできないため逐一ページ遷移または更新して再度ページ自体を読み込み直す必要がありました。

    例えばよくあるきせかえ機能を例に説明すると


    1.元の状態

    2.きせかえの仮状態で確認

    3.決定後きせかえ完了

    このように最低3ページが必要でした。


    スムーズに行けば3ページですが、一度適用してみたが、やはり別のものにしたいケースや、リストが多くてページング移動を挟んだ場合などでは、


    1.元の状態

    2.ページング移動

    3.きせかえの仮状態で確認

    4.元に戻す

    5.ページング移動

    6.きせかえの仮状態で確認

    7.決定後きせかえ完了


    と、用意するページもサーバー側での処理もユーザーの操作までもが混沌としていました。


    非同期画面更新ができない

    先程の着せ替えを例にするとスマホであれば、きせかえを一度試してやっぱり戻すという行動は、着せ替え情報をサーバーでセーブする必要がないので本来アクセスする必要がないのですが、状態を保持できず、画面の更新の場合、スマホであれば、以下のようにサーバーと通信する必要がなく、クライアントだけで状態を保持し、画面を更新して最後にようやくセーブするためにサーバーと通信すればいいので、サーバー処理もユーザー操作も非常に簡略化されます。


    また、画像の合成もガラケーの場合クライアントでは不可能でしたので、サーバー側で合成して保存するという面倒な処理も必要でした。

    (厳密にはJavaScriptではなくFLASHを使ってこれらの問題を一部解決していたのですがFLASHが終了した今ここでは割愛いたします。)

    以上のように様々なガラケーの制限に対応するためにサーバー、クライアントともに たくさんの手法と工数で対応していました。


    フェーズ2 ガラケースマホ移植

    スマホのシェアが半数近くになると、必然的にガラケーのサービスはユーザーが減ってしまいますので、サービスのスマホ対応が必須になります。しかし移行期だといきなりガラケー版をやめてスマホにシフトするわけにもいかず、ガラケーとスマホの両方に対応したサービスを展開しなければなりません。

    まず最初にとられた手法は、ガラケーで作られたページやディレクトリ構成をまるっとコピーしてスマホ版にデザインされたものに一つずつ置き換えていく方法です。すでにリリースされてから時間も経っているので、相当なページ数をまた一つずつ手作業で書き換えていく必要がありました。サーバー側はアクセス元のデバイスを見て出し分けるだけなのでそこまで作業コストはかかりませんが、フロントはここからガラケー版の終了まで常に両方のデバイスに対応するための修正を行い、追加ページの開発では常に2パターンのページを用意する必要がありました。

    CSSが自由に使えるようになったため表現の幅は広がったのですが、初期のスマホブラウザの仕様がまだまだお粗末なものでiOSのバージョン違い、Androidでは端末ごとに挙動が異なることが多く、主要な端末では全てチェックする必要がありました。

    またこの段階ではガラケーで表示していたものをただスマホサイズに変えてデザインを調整しただけで、JavaScriptもほとんど利用せず、非同期の画面更新もほとんどなく、本当の意味でのスマホ対応とはまだ程遠い状態でした。


    フェーズ3 jQuery時代

    スマホのブラウザの仕様が安定してくると、スマホで使えるJavaScriptのライブラリも数多く登場しました。今でも多くのサイトなどで使われるjQueryなどがその一つです。 jQueryを利用することで、通信しない画面更新と非同期通信(いわゆるajax)が可能になりました。ここでようやく、現在のスマホらしい、シームレスな着せ替えやスムーズなダイアログ確認だったりが表現できるようになりました。ただここでも問題点がありました。


    サーバーサイドも工数が激増

    このフェーズからガラケーが終了するまでサーバーサイドもスマホ用とガラケー用の両方のAPIを用意することになります。表現方法が異なるので同じAPIを共有できませんでした。


    MVCの非独立性

    ページのテンプレートに最初から変数が埋め込まれているのでそれを元にjs(jQuery)で画面操作しなければなりません。最初からjsを多用する前提で作ったページでは、問題なかったかもしれませんがガラケーのテンプレートから流用して作られたページでは、いわゆるMVC(ModelとViewとController)が全てテンプレート側に記載されてあり、一部分のControllerを強引に外だししているだけであまり綺麗な状態とは言えませんでした。


    とくに様々な条件で表示要素が多いマイページなどではガラケーっぽいテンプレートの変数だったり、強引に切り出したjQuery制御の部分だったりが混在していてリンクを一部修正するだけでも他の箇所への影響範囲が大きかったり、思わぬ場所に飛び火したりしていまいます。


    またテンプレートそのものにfor文やif文があるケースでも、似たようなスクリプトを何回も繰り返して書く必要があり、テンプレートとjsのソースがどんどん肥大化していきます。


    jQueryのデメリット

    直感的な書き方で人気を博したjQueryですが、HTMLの要素を取得するためにclass名やid名を使うことが多く、CSS用につけたclass名なのかjs用につけたclass名なのか把握しておかなければ修正するときに混乱を招いてしまいます。例えばページにあるキャラクターの名前を表示する要素があったとしてキャラクターは一つだけだったのでidをcharaNameとして作っていたが、後の改修でキャラクターの複数表示が必要になった場合を例に説明します

    <span id=”charaName”>キャラ名</span>
    
    #charaName{
    color:#FF0;
    }
    #(“#charaName”).click(function(){
    //hogehoge
    });

    こんな状態だったとします。この時は1ページ1キャラクターしか表示しない想定で作られています。

    改修によってキャラクターは複数表示可能になったとします。

    idは1ページに1個だけですのでこれをclassに変える必要があります。

    <span class=”charaNameList”>キャラ名1</span>
    <span class=”charaNameList”>キャラ名2</span>
    .charaNameList{
    color:#FF0;
    }
    #(“.charaNameList”).click(function(){
    //hogehoge
    });

    最初からidを使わないでclassで管理していれば問題ないかというとそうでもありません。

    例えばキャラクター追加と同時にキャラクターと一緒にペットを表示したい、ペットとキャラ名をクリックしたときの挙動を同じにしたい、別にしたいペット名は小さく表示したい、キャラクターのランキングを表示させたいランキング上位には冠マークをつけたい…というようにあとからたくさんの変更依頼が押し寄せてきます。

    本来jsだけcssだけの変更でよかったはずのものもそれぞれ相互に作用してしまいます。

    もちろんルールの徹底ができていたり、この例のような簡単なものであれば特に問題ないかもしれません。

    しかし10年も運用しているとフロント実装者自身も忘れてしまっていたり、担当者自体が変わっていたりして簡単な修正だったはずが作業量がおそろしく肥大してしまうリスクがあります。

    jQueryはcssの延長でUIをちょっとリッチに動かすのには最適最速なのですがmodelそのものを扱うには少し難しいのです。


    フェーズ4 Vue.jsリアクティブ時代(現在)

    2010年代の後半になってくるとjQueryによるDOMの操作は敬遠されがちになり、 AngularJs ReactJs,VueJsといった変数をリアクティブに管理するライブラリが登場しました。jQuery時代と比べてユーザー視点では見た目や操作性にはそこまで変化はありませんが 開発スピードが格段に上がったと思います。

    「ファーミー」も現在新規ページやコンテンツにはVue.jsを用いています。

    新規のゲームやモバイルアプリをSPAで作るとすれば違う選択肢があったかもしれませんが(その場合有力候補としてはやはりReact.jsでしょうか)ページ単位で導入するしないを選べ、学習コストも低いVue.jsが選定されました。


    Vue.jsのメリット1

    テンプレート側のルールを覚えなくて良い。


    「ファーミー」 はサーバーがJavaで開発されておりテンプレートエンジンはftlというものを使っているのですが、新規でプロジェクトに携わるフロントエンジニアさんの中にはこのftl構文を知らない方もいます。(ftl自体もそんなに難しくはないのですが)Vue.jsを導入したページにはVue.jsのルールそのままに記載してテンプレートの言語には ほぼ依存しません。変数となる情報は後からajaxでJSONを取得してあとはリアクティブ変数に渡しVue.jsにレンダリングを全て任せています。そのためサーバー側の開発言語がJavaでもPHPでもNode.jsでも関係なくフロント側のコードを書くことができます。Vue.jsのお作法さえ覚えていればほとんど引き継ぎしなくてもフロントエンジニアが作業に入ることができます。

    Vue.jsのメリット2

    リアクティブ更新と様々なトリガー

    リアクティブでない変数で管理している場合、一つの変数が変わると影響する範囲全てを考慮し多数のメソッドを呼び出す必要がありました。 Vue.jsを用いるとこれらはモデルを更新するだけですべて置き換わります。filtersを使ってよく使うカンマ足しや四捨五入なども簡単に導入することができます。 値が変わったことをトリガーにするアニメーションなどもwatchを使って簡単に実装することができます。

    Vue.jsのメリット3

    サーバー側と同時開発ができる。


    以前の開発手法だと、

    サーバー側とクライアント側の両方ができるエンジニアが一人で組み上げる。

    または、

    サーバー側のテンプレート実装を待ってから装飾部分をクライアントが実装する。

    という二択でした。

    テンプレートに変数が埋め込まれてる仕様の場合どの変数がどの形、名前でテンプレートに埋め込まれているか確認するには仕様書を見返すかテンプレートで実際レンダリングしてみるほかなく、かなり時間が掛かっていました。

    Vue.jsではテンプレートからデータを切り離したことにより、サーバー側が未実装でも静的な仮のJSONファイルを作ることにより先にフロントから開発を始めることも可能になりました。また、この仮のJSONファイルがそのままAPIの仕様になるので、フロントとサーバーの仕様共有ができ、あとから見返しても、どの変数がどの形で渡されているか把握するのにも一役買っています。(実際「ファーミー」ではJSONではなくサンプルのyamlを記載しそれをJSONに変換しています。)

    これにより、サーバーとの連携がかなりスムーズになりました。

    Vue.jsのメリット4

    引き継ぎが楽


    Vue.jsお作法を守ってコードを書いていれば誰がコードを書いたとしても、そこまで差異は出なかったり、出たとしてもどこでどんな処理をしているのかが非常に分かりやすい状態です。これはVue.jsに限った事でなはいですがフレームワークを限定するとコードが属人化しにくいです。(これに関してはReact.jsにも同じことが言えると思います。)


    フェーズ5 今後について

    フェーズ3から4で得た教訓として

  • テンプレートに変数を埋め込まず、非同期で取得。
  • 変数はリアクティブで管理して変数更新後の処理は極力減らす。
  • というのが大事だと考えます。

    今後も新たなフレームワークが登場し、そちらにリプレイスする可能性もゼロではないでしょう、この2点だけを守ればスムーズに、移行できるのではないかと考えています。


    最後に

    正直どのような設計でフロントのコードが書かれていようともユーザー体験としてはほとんど差異はありません。なのでどんな書き方をしていても正常に表示されれば問題ないのです。


    しかし長い期間サービスを続けると、


  • エンジニアも飽きてしまって新しいフレームワークに手を出す。
  • 担当が変わってコードの書き方が少し異なる。
  • 想定していなかった強引な仕様変更で仕方なくトリッキーな書き方で修正。
  • 端末が進化して新しい表現が可能になったので試してみたい。

  • 理由はさまざまですが、これらが積み重なって徐々にルールが壊れていき、結果開発スピードが低下していきます。

    根本となる概念と設計さえ共有できればこのスピード低下は回避できると思います。


    「ファーミー」でもVue.jsを用いているのはここ数年開発された新規のページだけで、既存のページは従来のテンプレート変数&jQueryの方式で書かれたままのところがたくさんあり、これらのページの改修を行う際はやはり従来の方式に合わせる必要があります。他にもVue.jsのメリットの一つであるコンポーネント化などはまだできていない部分があり 全部作り替えてしまえば管理も楽なのですが、開発リソースが有限なため既存ソースのリファクタリングと新規の開発を同時に行う余裕はないのが実情です。そのため、せめてここ数年で作られた機能だけでも開発の効率化スピード化を意識した作りにしていきたいと考えています。


    改修に改修を繰り返して自然と難読化されてしまったソースからたった一行の修正箇所を探すのに小一時間かかるような悲劇を繰り返さぬよう願いながら。



    LINEで送る
    Pocket

    おすすめ記事