はじめまして!7 月 4 日から 7 月 22 日にかけて、株式会社アカツキゲームスのインターンシップにバックエンドエンジニアとして参加させて頂きました、菊池と申します。
本記事では、私がインターンシップの期間で取り組んだ課題を紹介すると共に、インターンシップを通じて感じたこと等を書いていきたいと思います。この記事がアカツキのインターンシップへの参加を検討している方の一助となれば幸いです!
インターンシップに参加するまで
インターンシップの参加が決まった後に事前の面談があり、メンターの方と取り組む課題について相談しました。インターンシップ参加の動機などを擦り合わせた結果として、以下の 2 つの課題を頂きました:
- 課題 1: ゲームの新規ミッションの実装
- 課題 2: ゲーム内文言の検証のための内部ツール制作
前者は、多種多様なミッションをカバーするために複雑化したコードベースを読み解く経験や、実際に書いたコードが直接ゲームの上で動いていることが確認できる面白さがある課題です。これは、私が「実際に大規模なゲームの開発に参加してみたい」という動機でインターンシップに参加したことから、用意していただいたものでした。
後者はチーム内で改善課題と上がっていた段階のものを切り分けて頂き、要望のあった方と要件を摺り合わせることや、実際に仕様を一から作成することが経験できる課題として用意して頂けました。
また、参加までの前準備として、プロダクトで使用されていた Ruby on Rails のチュートリアルをある程度進めておきました。
インターンシップで行ったこと
ミッションの新規追加
インターンシップ初日は開発に必要なアカウントの設定や開発環境のセットアップをしていたので、2 日目からこの課題に取り組み始めました。
まず、開発に使用しているタスク管理ツールにチケットを起票しました。次に、ミッションのコードベースを読み、ミッションが実行されるフローや他の既存ミッションを参考にしつつ、どこに新規ミッションのコードを追加すればよいか/どのように書けばよいかを検討しました。次に、実際にミッションのコードを追加し、ミッションが意図された挙動をしているかを確認するテストを書きました。ここで、このコードのプルリクエストを出し、レビューをして頂きました。ここでは、以下のような観点からの意見を頂きました:
- 異常系のテストが不十分
- ミッションを進捗させる部分がおかしく、関心が分離できていない
- テストに記したマジックナンバーに説明が欲しい
これを修正した後、プルリクエストを無事マージして頂くことができました!
この課題では実際に大規模なコードベースを触り、そこに対してプルリクエストを出すという経験をしました。実際にプロダクトとして動いているコードに新規の実装を加えるといったことの経験がなく、少しの変更といえど達成感のある課題でした。また、実際のゲームの裏で動いているソースコードを読み、それに自分のソースコードを加えるという経験は、いちゲーム好きとして素直にワクワクする体験となりました。
ゲーム内文言均一化ツールの開発
プルリクエストがマージされた後、2 週目からこの課題に取り組み始めました。この課題の概要を説明しましょう。例えば、「魔法攻撃力を 2 倍にする」というアイテムがあるとします。このアイテムの効果には「魔法攻撃力を 2 倍にする」という表現以外にも「MAT を倍にする」や「魔力x2」といった表現方法も存在するでしょう。従来はこういった表記ゆれを人が発見し、修正していました。これを自動化したいというのが、本課題の目標です。
この課題を解決するためには、仕様から策定しなければいけません。なので、まずは既存の文言を SQL で絞り込み、どのような文言が使用されているかを調査しました。その結果として、一定の構造を持っているものの、条件に応じて表現方法が変わっている文言などもあることがわかりました。このような状況の中、チェックのために必要な文言のルールを定義する方法を検討しました。結果として、
- 十分な表現力を持っていること
- エンジニアでない人でも学習が容易なこと
が要件として上がったため、独自 DSL を採用することとしました。これは一見オーバーエンジニアリングに見えますが、文言の表現にはプログラミング言語程度の複雑性を持ったものが必須であることや汎用のプログラミング言語の実行*1ではセキュリティ上の問題があること、自前で仕様を策定することで表現力と複雑性のバランスを取ることができることを理由に独自 DSL の採用は妥当だと判断しました。
この時点で、要望を出して頂いた方に仕様をお見せし、いくつか意見や改善案を頂きました。それを基に仕様をブラッシュアップし、エンジニアチームの方にレビューをして頂くことで仕様をある程度形にしました。レビューでは
- 言語の保守が容易か?
- 得る利益が実装の工数に見合っているか?
- 一部の文言だけ対応することで、チェッカーが走っていないものも走っていると思いこむといった事象が起きないか?
などの視点で意見を頂き、より自信が持てる仕様とすることができました。
結果として、最初に上げた「魔法攻撃力を 2 倍にする」という例は、"{{攻撃タイプリスト[タイプid]}}を {{倍率}} 倍にする"
というルールで表すことができることになりました。このように、プログラミングにおける配列の参照や関数呼出のような文法を使用できるようにしたことで、条件分岐等が込み入ったルールの表現も可能になっています。
その後、この言語のインタプリタを書きました。パーサは racc というパーサジェネレータを用いることで 40 行程度で書くことができ、その他の実行環境の実装と合わせても 300 行程度の実装となりました。また、これがチームにとって却ってドメイン知識的な負債にならないように、ドキュメンテーションも行いました。
この課題は、個人で取り組む時間の多い課題でした。しかし、この課題を通じてチーム開発における重要な観点を学ぶことができたと思っています。それは「『作成したアプリケーションがチーム内で第三者によって使用され、保守されていく』ことを意識する」という観点です。私は最初、この点を意識できていませんでした。そのため、アプリケーション使用者のペルソナとして私個人を無意識に置いていたり、保守に際して必要なドメイン知識を不要に増やしてしまうようなコードを書いたりしていました。今あるコードもこのような側面がないとは言えませんが、ドキュメントを書くといったことである程度のカバーはできたと考えています。この学びは今後の開発でも生かしていきたいと思っています。
また、自分の能力の過信から甘いスケジュールの見積もりをしてしまい、結果として仕様の策定に想像以上に時間を使ったことでスケジュールが押してしまったことも反省すべき点だと感じています。
その他
ゲームを触っている中で些細な不具合を発見したので報告したところ、修正予定の問題として起票されました。図らずとも普段は見ることのできない不具合報告からの修正の流れの一端を見ることができ、とても興味深い体験となりました。
感想
今回のインターンシップは、社会情勢が未だに良くならない中でほぼリモートでの参加となってしまいました。しかし、人事さんが興味のある分野の方とのランチを組んで下さったり、メンターさんがいつでも Zoom でお話ができるような環境を整えて下さったりしたため、リモート参加がインターンシップにあたって大きな障害となることはありませんでした。
また、与えられた課題はどれも興味深いものでしたが、他にも興味をそそられることをいくらでも見つけることができ、一日中ドキュメントを眺めていたくなるような気持ちにさせられることも多々ありました。
反省点としては、人に頼ることが苦手で一人で何でもこなそうとしてしまう性格から、もしかするとあったかもしれない学びや発見の機会を逃してしまっていたかもしれないと感じていることが挙げられます。もしこれからインターンシップに参加される方で自分のような性格の方がいるならば、意識的にいろいろな場面で人に頼ってみることを強くおすすめします!
改めて、本当に貴重かつ有意義な体験となるようにサポートしてくださったメンターの方やチームや人事の方々、このような環境を作ってくださった全ての関係者の方にこの場を借りて御礼を申し上げたいと思います。ありがとうございました!
*1:ruby の eval 等