フレームワーク移行のための取り組みを紹介します


目次

はじめに

こんにちは、ピクトリンク事業部開発部サーバサイド開発課のkitajimaです。弊社サービスピクトリンクは、システム再構築の一環としてフレームワークの移行を続けてきました。
本記事では、システム再構築の計画から作業まで、実際に関わっている1メンバー目線で紹介させていただこうと思います。

前提

ピクトリンクは長年Seasar2(以下S2)という既にEOLを迎えたフレームワークに依存しており、次なるフレームワークの移行先としてSpringを選択しました。 依存している箇所は、プレゼンテーション層、サービス層、永続化層と多岐に渡り、脱却の道のりは決して短いとは言えません。

今回紹介するのは、その中でもプレゼンテーション層移行の取り組みについてです。プレゼンテーション層ではS2のCubbyというフレームワークを使用しており、これをSpring MVCに移行していきます。
Cubbyのアクションクラス(HogeAction)を、Spring MVCのコントローラクラス(HogeController)に移行していくイメージです。

計画

マイルストーン

まず、クラス単位でタスクを立ててマイルストーンを引きました。チームでのタスク見積もりは後で行うのですが、ここでは知見のあるメンバーにおおよその規模感を考慮して引いてもらいました。
他に考慮すべき点として、施策との兼ね合いがあります。こういった再構築作業(「技術的負債の返済」とも言われます)は施策の後回しになってしまいがちで、なかなか進捗を生めないのが悩みどころです。かといって施策を完全ストップして再構築に時間を充てるわけにはいかず、並行して取り組む必要があります。
施策の繁忙期を考えて再構築のタスクを減らしたり、ポイントの小さいタスクに留めたりといった調整をしたため、コンスタントに進捗を生みだせています。

見積もり

次に各タスクについて、規模感をチームで見積もります。弊チームはプランニングポーカーという手法を用いて、タスクの相対見積もりをしています。
「“相対"見積もり」ですから、チームで「2ポイントとは、〇〇という実装を完了させる規模感である」という指標を共通認識として持ちながら見積もっているわけです。

同じアクションクラスといっても、0.5ポイントから5ポイントまで、クラスによって規模感はピンキリです。 チームで見積もりするので必ずではないのですが、結果的に以下のような見積もりになっていたという印象です。

  • 既に使われていない機能で、削除対応のみであるクラス…0.5pt
  • 1メソッドのみで、ロジックをほぼ含んでいない…0.5pt
  • 複数メソッドを持つがそれぞれは薄い処理で、機能テストも自動化されているので手動テスト実施が不要なクラス…1pt
  • 複数メソッドを持ち、プレゼンテーション層でロジックが多く含まれている(いわゆるファットコントローラ)ようなクラス…2pt
  • 上記に加え、自動化可能だが手動である機能テストを実施してきたクラス…3pt
  • 上記に加え、通信キャリアや決済に関わる機能を持ち、どうしてもスマートフォン実機での手動テストが必要なクラス…5pt

※“機能テスト"については、移行の例で詳しく説明させていただきます。

3ptの例で挙げたように、中には自動化可能にもかかわらず手動で機能テストを実施しているクラスもあります。対象の機能テストの必要性、コストに応じて、「自動化すべきか、手動実施のまま進めるか」といった整合も含めた上で見積もりをしています。
そう、システム再構築を通して、本来の目的であるフレームワークの移行のみならず機能テストの自動化率向上も見込めるのです!

最終的に見積もりも含めた上期のマイルストーンは以下のようになっています。上述したように施策との兼ね合いや各タスクの規模感を考慮しているため、一定の消化ペースではないことがお分かりいただけるかと思います。 全部で39クラスを、上期(3/28~9/23)の期間をかけて完了させていく見込みです。

また、執筆時点でマイルストーン通りに進んでおり、再構築はとても順調であることもお伝えします! (画像が小さくわかりにくいですが、チケットの左下に青い四角がついたものが「進行中」、赤い四角がついたものは「完了」です。)

移行の例

取り組みの内容をイメージしやすいよう、移行作業について簡単に一例を紹介させていただきます。

プロダクトコードの修正

実装を修正します。あわせて、実装を変更した箇所のユニットテストも修正します。

クラスレベル

移行前(Cubby)
@ActionClass
public class HogeAction {
    // action methods
}
移行後(Spring MVC)
@Controller
public class HogeController {
    // controller methods
}

メソッドレベル

viewを返したい場合の汎用的なメソッド移行は以下のようになります。 マッピングやリクエストパラメータの指定ができるアノテーションを移行していきます。

移行前(Cubby)
@Path("hoge")
@Accept(RequestMethod.GET)
public ActionResult hoge() {
    this.hogeObject = "__hoge__";
    return new Forward("hogeView");
}
移行後(Spring MVC)
@RequestMapping(value = "/hoge", method = RequestMethod.GET)
public ModelAndView hoge() {
    String hogeObject = "__hoge__";
    return new ModelAndView("hogeView")
        .addObject("hogeObject", hogeObject);
}

設定ファイルの修正

ここでは割愛しますが、web.xmlでマッピングの設定を修正し、今回の移行対象のパスが使用するサーブレットをSpring側になるようにします。
以下のようなイメージです。

機能テストの実施、自動化

ここでいう機能テストとは、ユニットテストとは区別した存在です。APIのレスポンスを検証したり、画面遷移の検証をしたりするものを指します。

移行対象のクラスに関連する機能テストを実施していきます。ピクトリンクの機能テストには自動テスト(webブラウザを自動操作するツールを使用して検証するもの)、手動テスト(PCや実機でブラウザを操作して検証するもの)が混在しています。
自動テストと違い、手動テストは人間が時間をかけて実施しなければならないのでとにかく大変です。手動テストを減らすため、可能な限りこのフェーズで自動化します。

リリース

移行したクラスを本番系にリリースします。これで移行完了です!弊チームでは、いくつかのクラスをまとめて定期的にリリースするという方針を採りました。

困難だった移行例

上で紹介した移行例は簡単なものですが、中には以下のように困難を極めるクラスもありました。

手動テストが膨大な機能

前述した通り、通信キャリアや決済に関わる機能を持っているクラスは必要な手動テストが多く、非常に苦労しました。
通信回線による課金遷移の出し分けを行っていたり、通信キャリアが提供する決済サービスでは二段階認証が挟まったりする関係上、スマートフォン実機操作とテーブル検証を行ったり来たりする必要がありました。
また、テストの方針が今とは異なる時代に作られた機能テストが混在していたため、実施が必要な機能テストを洗い出すだけでも一苦労でした。

フレームワークの挙動の違いによる不具合

CubbyとSpring MVCの振る舞いが違うことが原因で、プロダクトコードのロジック部分は変更していないにもかかわらず不具合が発生してしまうこともありました。 multipart/form-dataを取得する処理が、Springに置き換えると動かなくなってしまったのです。
解決として、従来はHttpServletRequestから直接取得していたデータを、リクエストオブジェクトを作成してMultipartFileにバインドして受け取るようにしました。

再現
public class HogeController {
    public ResponseEntity<Void> hoge(@ModelAttribute @Validated HogeRequest requestModel) {
        String mailData = requestModel.getMailDataString();
        // 後続処理
    }
}

public class HogeRequest {
    private MultipartFile multipartFile;
    public String getMailDataString() {
        // multipartFileからデータを返却
    }
}

移行作業では気づかなかった上に原因も全然分からず苦戦したのですが、後ほどチームメンバーが究明してくれました。また、同じような機能が別のクラスにもあり、そちらにも応用できました。チームメンバーに感謝します!🙏

おわりに

フレームワーク移行は、本来の目的だけではなく色々な恩恵があったと感じました。
機能テスト自動化率の向上、不要な機能の削除、リファクタリングなどはもちろん、新しいメンバーが取り組むのにちょうどいい粒度のタスクがあったことも大きかったと思います。
私自身、チームにジョインした直後にこの作業に取り組み、ペアでタスクを進めるというスタイルに慣れていったことを覚えています。
kitajimaはフレームワーク移行のおかげで仕事に慣れたと言ってもいいのではないでしょうか・・・!

執筆時点でプレゼンテーション層の移行はほぼ完了ですが、まだ他の層の移行が残っており、下期に向けて引き続き計画を立てていくフェーズです。 この取り組みの経過も、今後紹介できたらと思っております。
お読みいただきありがとうございました!

参考資料

フレームワーク移行の計画が始まった当時、フリュー社員だった方が発表された資料です。ピクトリンク独自の技術的な課題や内容が充実しているため紹介させていただきます。 https://www.slideshare.net/jyukutyo/seasar2-62265627
https://www.slideshare.net/jyukutyo/jjug-ccc-2017-spring-seasar2spring