Unity 開発体験向上の会

クラスター株式会社でSoftware Engineerをしている ねおりん (@noir_neo) です。 

この記事では、Unity を使った client app 開発において、 メンテナンス性を向上させつつ、開発を加速するためにクラスターで行っている取り組みのひとつを紹介します。

cluster の client app の開発には Unity を使っています。(モバイル版では Unity as a Library を用いており、ワールドに入室したあとの画面は Unity で開発しています)
この Unity の project は、4年以上運用と開発が続いています。現在では10人以上のメンバーが同時に開発をしており、そのコードベースはますます大きくなっています。

開発チームの規模が成長していく中にあっても、技術的負債に対して組織的・継続的に向き合うために、私たちは「unityproject 開発体験向上委員会」を発足しました。この会を運営して3ヶ月程経ったので、振り返りも兼ねて、その活動の内容を記事にしてみます。

unityproject 開発体験向上委員会 #とは

委員会は Unity の project で開発するメンバーのうち数名で組織されており、週次でミーティングを行っています。

ミーティングでは、新たな課題のタスク化や優先度の入れ替えなど backlog の修正を行い、次にやることを合意します。
backlog には例えば、「XXのリファクタリングをしたい」とか「XXをドキュメント化する」「XXのデバッグがしにくい」のようなものが並びます。

backlog

着手を決めたタスクは、会のメンバー自身が直接作業して消化することもあれば、チームに持ち帰って (Engineering Manager の承諾を得て) 他のメンバーにアサインし直すこともあります。
つまり、開発効率のためにやるべきことに優先度を付けて、 Engineering Manager と交渉して実行に移すことが会の責務となっています。

さて、ここからは、会を起点に行った改善の事例を3つ紹介します。

事例1: asmdef 整理計画

Unity の project ではアセンブリ定義ファイル (以下 asmdef) が設定されていることで、依存関係を明確にしやすくなります。またコードを変更した際のコンパイル時間の短縮も期待されますが、その恩恵を最大限受けるためには Auto Referenced も無効にしたいところです。そのためにも、すべてのコードは asmdef 下に置かれることが望ましいと考えています。

cluster の開発では途中から asmdef を導入していったため、比較的古くからあるコードの中には asmdef が切られていない箇所も残っていました。そういったコードの中にはそもそも設計思想が異なるものもあり、依存関係が複雑で、 asmdef を追加するのは一筋縄ではいきませんでした。その影響はコードを利用する側にも及び、 asmdef を導入できない、もしくは依存関係を歪めてがんばって使う、という状況が度々発生していました。

こうした問題に対して、意を決してすべてのコードに asmdef を切る計画をはじめました。変更によるプロダクトへの影響はないものの、作業はそれなりの大きさだったため、 epic のフローに乗せて進めました。

asmdef 整理計画

結果、 cluster の Unity project では、すべてのコードに asmdef が切られている状態になり、ほとんどの asmdef で Auto Referenced を無効にできました。

epic 振り返りのボードより (作業の大変さを物語っている)

事例2: エラー監視ツールの入れ替え

それまでエラーレポートは Unity Cloud Diagnostics に収集しており、バグ調査などの必要に応じて使用していました。 Unity Cloud Diagnostics は導入が非常に簡単な一方、通知のフィルタリングやタスク管理ツールとの連携の面で、私たちの用途には適さない場面も少なくはありませんでした。

そこで会では、ほかのツールを検討し、 Sentry の導入を進めました。

アラートの設定のおかげで、半ば"割れ窓"化していた Slack への通知 channel が機能するようになりつつある他、 Jira への起票が自動化されるなど、非常に便利になりました。

(大丈夫ではなかった)

事例3: 基盤コードのリファクタリング

API client (HTTP request のメソッド抽象) が共通で使う実装は UniRx で書かれていました。このコードには、エラー時のスタックトレースの追いづらさや、リトライ処理の複雑さなどいくつかの課題がありました。
以前より、新規に追加する API は UniTask で実装する方針を取っていたため、共通実装部まで async/await にすることのメリットは認識していました。しかし、基盤となる実装なのでそれほど頻繁に触る箇所でもないということもあり、これまで手を付けられずにいました。

これをリファクタリングしておきたいという提案があったので、会の backlog に乗せておいたところ、数週間後にPRが上がり、無事マージされました。コードがとてもシンプルになったので、いざというときに助かることと思います。

 LGTM

おわりに

cluster の開発を加速する「unityproject開発体験向上委員会」の取り組みについて紹介しました。

今回紹介した以外にも、この3ヶ月ほどで大小様々な改善を行っています。

Done items

機能開発の優先度はもちろん高いですが、それだけをしていると少しずつ効率が落ちていき、やがて人が増えても開発速度は上がらないチーム/コードベースになってしまいます。また誰かひとりだけで改善を推し進めるのは継続が難しいものです。
開発効率を上げる(ための工数を確保する)ことに責任を持つ会があることで、組織的に改善を継続できる体制になりました。
また、少し腰が重いようなリファクタリングに関して、その実行を是とする枠組みがあることで、タスクの隙間時間などにやる方向に力が働くことにも会の存在意義を感じています。

クラスターでは、共に斧を研ぎつつ爆速で木を伐りたい Software Engineer を募集しています!