10年放置されたレガシーコードをモダン化する

by shunsuke.sakai | March 04, 2021
Legacy | #Maya #Python #CMake

ゲーム事業部の酒井です。

今年DeNAのMobageは15周年を迎えます。同時にそれを支えてきた技術にも15年の歴史があることになります。サービスを構成しているさまざまな技術は、そのときどきの事情やトレンドによって適切に更新・メンテナンスしながら運用されてきました。

一方でサービスを構成する重要なコンポーネントであるにもかかわらず、多様な理由から長らくメンテナンスもされず、現場から忘れ去られてしまったものも存在します。実際Mobageのサービスのひとつ「アバター」にそのようなコンポーネントがあり、それがあることをきっかけにサービスの存続に関わる問題としてにわかに噴出するということがありました。

そのため該当コンポーネントのコードをアップグレードし、かつ今後は誰でもメンテナンスができるようビルド環境の再整備を行いました。今回はこの実例をもとに、レガシーコードをモダン化した試みを紹介します。

ことの発端と背景

問題となったコンポーネントとは、DCCツールMayaのプラグインでC++ APIを利用するものでした。これはMobageのサービス「アバター」のアセット制作※1で絶対に欠かせないツールなのですが、これがとある理由※2で将来の利用ができなくなると予想されたため、ソースから最新のMaya※3に合わせてビルドしなおす必要がありました。

本プラグインの開発は社外の協力会社によるもので、ビルドされたプラグインも先方から提供を受けていたようです。ところが困ったことに、その会社は事業譲渡や企業買収等によってアクセスすることが困難となっていました。

幸い、協力会社からはソースコードがCD-Rで納品されていました。ファイルのタイムスタンプから確認できたことは、納品から10年程度経過しており、その間社内では誰もこれらのコードをメンテナンスしてこなかった、ということでした。

そこでDCCツール開発やCG制作のワークフローを理解している筆者が、本件を担当することになったのです。※4

筆者は、たとえ10年放置されたコードでも丁寧に修正してメンテナブルな状態にすれば、問題が解決できると考えました。そのため本件を次の5つのステップに分解して進めていくことにしました。

  1. 法務確認
  2. レポジトリ作成とデータの整理
  3. テストの作成
  4. コード修正
  5. CMakeでビルド自動化

※1: アバターのアセット制作には3DCGが用いられている
※2: 2021年1月からオートデスク社のサブスクリプション契約で利用可能なバージョンのうち、古いバージョンのものが利用不可 になってしまうため
※3: C++ APIプラグインをビルドするには、使用するMayaのバージョンに適合したSDKが必要
※4: 筆者は2019年4月入社しプラットフォーム部所属(当時)で、筆者の入社前はDCCツールに詳しい社員が部内に一人もいなかった

1. 法務確認

納品されたコードは社外の協力会社が開発したものです。つまりビルドのためとはいえ勝手に修正すると、先方の権利を侵害してしまうおそれがあります。そこで、まずは当時の納品の経緯と契約内容を法務部のスタッフに確認してもらいました。

結果、やはり自社でソースコードに勝手に変更を加えるのは契約上NGだったことが判明しました。

そうであれば契約を改定してもらえるよう交渉する他はありません。先述の通り協力会社にはアクセスが難しい状況でしたが、関係者を巻き込んでなんとか良い方向に着地させることができました。これで堂々とコードに手を入れることができます。

2. レポジトリ作成とデータの整理

納品されたCD-Rには、コードの他には開発者のメモや、古いVisual Studioのプロジェクトファイル等がzipで固められていただけでした。当然バージョン管理もされていません。よってgitでバージョン管理ができるようレポジトリを作り、後からコミット履歴を追えるようにしておきます。

本プロジェクトは最終的にCMakeでビルドできるようにしたく、それに適した構造(ソースコードとそれ以外をディレクトリで分離するなど)に整理します。他には、なぜかASCIIファイルの文字コードがバラバラだったので、UTF-8に統一しておきます。問題があればgitで作業内容を確認できます。

開発者の方が残したメモも、分かりやすい場所へ移動しておきます。これとは別にREADME.mdも別途用意して、プロジェクトの経緯や詳細がわかるようにしておきます。

3. テストの作成

コードの本格的な修正を行う前に、テストを作ります。ここではブラックテスト的なもので、入力に対して出力が期待通りになっているかを確かめる程度のものです。

今回はPythonのunittestモジュールを利用することにし、テスト機能はプロジェクトからは独立した状態にします。理由としては、本プロジェクトはMayaで動くプラグインのため、Mayaを通してテスト実行する必要があるためです。Mayaをバッチモードで起動させてテストを実行するバッチファイルを作っておきます。こうして1クリックでテストが実行できるようになりました。

4. コード修正

やっとコード修正に入ります。とりあえず手元でビルドできるよう、必要なコンポーネントをインストールします。基本的にはプラグインを作りたいターゲットのMayaとSDK、Visual C++が必要になります。最後にソースコードをVisual Studioに追加したら、ビルドしてみます。

案の定、大量のエラーがコンソールに表示されます。ここで慌てず、1つ1つ丁寧に追っていきます。よくよくエラーの原因を突き詰めていくと、現在の状況に対応しない書き方をされているマクロだったり、Maya API側の変更だったりと、意外と単純なものが多いです。これらの修正を粛々と進めていきます。

そしてついに、ビルドが通ってMayaプラグインファイル(*.mll)が生成されました。意図通りの動作をしているか確認するため、テストを実行して入力に対して期待された結果がどうか確認します。ここで問題がなければ、コード修正は成功したと考えてよいでしょう。

5. CMakeでビルド自動化

最後にCMakeでビルドを自動化してみます。今後、新しくMayaのバージョンが上がるごとにプラグインをビルドする必要がありますが、正直Visual Studioの設定をちまちま変更するのは面倒だし、何より作業が属人化してしまいます。こうなれば誰もメンテナンスしなくなり、いずれ本件の最初の状態に戻ってしまうでしょう。

CMakeを使うと、CMakeLists.txtファイルの内容にしたがって依存関係を解決し、Visual Studioのプロジェクトを生成してくれます。またリリースビルドもコマンドから一発で実行できるので、コードの修正が発生しない限り、CLIだけでビルドが完結します。

Maya devkitの中にテンプレートとなるCMakeLists.txtが入っているので、そちらを参考になるかと思います。これによって、README程度の情報で自分以外のメンバーでも適切にビルドが行えるようになりました。

最後に

世の中を見渡すと、産業や金融分野では50年以上動いているコードもあると聞きます。それに比べると、10年前のコードなどレガシーと言えないかもしれません。また権利侵害や今後のメンテナンスを考えなければ、もっと少ない手数でビルドを実現できたかもしれません。しかしそれは職業人としてあってはならないことですし、今回のモダン化によってサービスのライフサイクルを伸ばすことに確実に貢献しました。そして個人的にも多方面で学びがありました。

現在、筆者はゲーム事業部へ異動しており本件からは完全に手を引いていますが、本コンポーネントはDCCツールやC++に詳しくないメンバーでも適切にメンテナンスされています。