虎の穴開発室ブログ

虎の穴ラボ株式会社所属のエンジニアが書く技術ブログです

MENU

笑って泣いて、品質改善:新規開発プロダクトのローラーコースター #虎の穴ラボ Advent Calendar 2023

  • 本記事は 虎の穴ラボ Advent Calendar 2023 11日目の記事です。
  • 前回は後藤さんによる「Tween24.jsでアニメーションを実装してみたので解説」でした。
  • 次回は浜田さんによる「OpenAPIで試すスキーマ駆動開発」です。ご期待ください!

こんにちは、虎の穴ラボのtzです。
私はDXチーム所属でここ3年程度プロダクトの改善に取り組んで来たのですが、その事例の一部、得られた教訓についてお話ししたいと思います。

※本記事で言及している「新規開発プロダクト」とは、通販と比較して新規事業であるプロダクトのことです。

目次

DXチームで取り組んできたプロダクト改善

DXチームとは

とらのあなラボの組織における、エンジニアリング部署は大枠として「新規事業」と「とらのあな通販」があります。

DXチームは、この「新規事業」に属するチームのひとつです。

通販、とらコイン、Fantia、Creatiaといった大規模なプロダクトに含まれない、小規模なプロダクトを複数担当するチームだと思ってください。
※大半が虎の穴ラボ発足以前から存在するプロダクトです。

チーム発足の経緯、特色・特徴

2020/09に発足しました。
それまで散らばっていた小規模なプロダクトをとりまとめる形でチームが作られ、「DXチーム」と命名されました。
特徴としては、「担当範囲がとにかく広い」ことです。

弊チームにおいては以下の要因により、技術的負債が積もりに積もっていました。

  • 虎の穴ラボ発足以前からあるプロダクトでは、担当者は非技術者であることが多かった。
  • DXチームが引き継ぐまで、管理やメンテナンスが行われていないものもあった。
  • DXチームが引き継いだ後も、少人数のため、すぐには対処ができなかった。

次項からは、そんなチーム発足から今まで起きた事例をもとに、我々が学ぶべき教訓などをまとめていきたいと思います。

事例

事例1. ゼロ(Unitテスト全滅)から始める復興生活:プロダクトAでの事例

プロダクトAでは、Unitテストが全滅していました。(起動すらできませんでした)
ええっ!? この状態から始められるUnitテストがあるんですか!? と言いたくなるような状況になったのには理由があります。
(よくある話ではありますが……)

  1. プロダクトAは当初、他社のパッケージをもとに、他社が弊社向けにUnitテストを作り、開発が行われていました。
  2. 他社からの引き継ぎ、それに伴う度重なる根本的な要件変更、物理的なモデル名などの変更、リリース後の機能追加……などの結果が一切反映されずに、テストが放置された結果、実行不能な結果に陥りました。
どのように困ったか?
  1. Frameworkのアップデートの際に、発生しうる不具合を検出しづらくなった。(全打鍵すれば済む話ですが、だから余計にUnitテストが放置されがちになりました)
  2. 実装の際に画面上から細やかなテストを実施する必要性に迫られていた。(これも打鍵すれば済む話ではありますが、『だから』なんですよね……)
どのように修正したか?
  1. Model名を根こそぎ修正しました。
  2. (テストを消すという途もありましたが)敢えてテストを残し、仕様を辿りながらエラーの解消に努めました。
  3. テストデータの分離なども行いました。(SQLで登録されていたので、稀に良くテスト実行時に消えていました)
  4. 多言語対応を行っているプロダクトだったのですが、デフォルトの使用言語が変更されていたので、それに合わせてメッセージの期待結果も根こそぎ修正しました。
  5. 要件変更などにより使用されなくなったUnitテストを根こそぎ削除しました。
  6. 仕様変更によってエラーになっている(仕様がそもそも根底から変わっているレベルの)テストを、根こそぎ修正し、通るようにしました。
どの程度かかったか?

2年以上かかりました。
前述の仕様変更についてまともにドキュメントが残っておらず、経緯がGitHubのPRなどから推察しないと辿れなかったためです。

どのような教訓を得たか

大前提として、時間がない場合はUnitテストの修正がおざなりになるのはしょうがないとして。
最低限保守する側から見て、やっておいた方が良い内容を列挙します。

  1. せめて仕様変更の履歴、経緯はドキュメントで残した方が良い。
    PRから辿っても、仕様変更の経緯が書かれていないので、とても苦労しました。せめて何を変更したのかと、経緯を書いた方が後々苦労しません。

  2. 不要なテストは消した方が良い。
    消すくらいであれば、そこまで工数かからないはずです。せめて消した方が良いです。
    何が困るかというと、前述の通り経緯が残ってない場合、「そのテストが本当に不要なのか」判断ができないのです。

  3. 修正すべき内容は、時間がないのであればコメントか何かにTODOで残しておいた方が良い。
    前述の通り、何が正しいのか、修正すべきなのかわかりません。
    せめてヒントになるような取っ掛かりを残した方が良いです。
    ※勿論、管理方法は人それぞれなので、Issueで管理するなり、ドキュメントで一覧として管理するなり色々方法はあると思います。

  4. そもそも実行不能な状態にしない方が良い。
    言わずもがなですが、テストが実行不能な状態になると、もう誰もテストを修正しようと思わなくなります。
    最低限、実行可能な状態にしておき、テスト全体の実行自体に失敗するようなことがないようにしておいた方が良いです。
    ※プロダクトAでは、テスト実行時の初期ロード処理でエラーになって失敗してしまっていました……。

事例2.依存性の激突! 仮想環境への移行

チーム発足当初、弊チーム担当プロダクトの開発環境は、PCに直接作ることになっていました。

しかし、

  • プロダクトB: ライブラリA ver 6が必要
  • プロダクトC: ライブラリA ver 7が必要

上記のように、必要なライブラリのバージョンが異なっていたため、当初はプロダクト開発のたびにライブラリを差し替えて対応していました。
しかし、いい加減それでは立ち行かなくなってきたため、開発用のDocker環境を作ることにしました。

どの程度かかったか?

半年程度かかりました。

どのような教訓を得たか
  1. 教訓というほどではないですが、やはり複数プロダクトの開発環境があるのに、ローカル環境に直建てするのは良くないです。最初からローカルを汚さないように作るのが良いです。

事例3.プロダクトを見通す! 一覧作成の話

前述の経緯があり、発足当初はプロダクトが多くてどこまでが担当範囲で何があるのか、イマイチよくわかりにくい部分がありました。 そのため、wikiに通販とFantiaも含めたプロダクト一覧を作り、どのチームがどのプロダクト担当なのか、明示しました。

どの程度かかったか?

1日程度

どのような教訓を得たか
  1. メンテナンス時における連携先は明確にしておくこと。
    リストにするとよくわかりますが、メンテナンスを実施する際に連携する先が不明瞭なプロダクトが多く、それを明確にする作業を実施しました。(利害関係者の洗い出し)
    ドキュメントに残しておかないと分からなくなるので、必ず明記しておくことを推奨します。

  2. 担当範囲は明確にしておくべき。
    当然のことですが、どこからどこまでが担当範囲なのかは必ず明確にしておくべきです。

事例4.見えない仕様! テストケース作成

大体の担当プロダクトでは、疎通確認のための標準テストケースがドキュメント化されていませんでした。
(あっても、個別のものか、古いものでした)

そのため、比較的大きなプロダクトにおいては、徐々にテストケースの整備を行いました。

標準テストケースを作成することで、FrameworkのUpdate時のテスト仕様作成工数を削減することができました。

どの程度かかったか?

1ヶ月程度かかりました。

どのような教訓を得たか
  1. 特にクリティカルな部分(決済など)については、疎通確認用のテスト仕様を作っておいた方が良いです。
    唐突なUpdate、再起動、メンテ後の疎通確認時にとても役に立ちます。(当たり前のことですが……)

  2. 機能一覧はあった方が良い。
    ないと、見逃しや漏れなどが発生しやすくなるため。
    プロダクトに対する機能一覧、テスト仕様などをまとめたドキュメントを作ると管理しやすいかもしれません。(もう仕様管理ドキュメントで良いのではないかとも思いますが)

事例5.Framework Upgrade! 水底に潜む危険

Framework……弊チームでは主にRailsを使っていますが、これをUpgradeする時のチェック観点をまとめて、チェック漏れがないようにしました。
(作るまでは、各自の観点の違いからそれなりに漏れがありました)

弊チームでは、以下のように観点を作りました。

事前調査
・事前に動作確認を実施して、Deprecatedログが出たら潰す。
・RSpec、Rubocopの実行ログは事前に取っておく。(Update後の差異比較のため)
・staging-production間設定差異については、予め見ておくこと。※Update時に手を入れることになりますが、差異が妥当であるか予め確認しておくことで、後からの調査をやりやすくする。
 参考:(社内資料につき略)
・Rails diffを確認して、差分を確認しておくこと
 https://railsdiff.org/6.0.0/6.1.7.3
 ↑対象バージョンを指定してください

Update作業
・Gemfileは極力標準Gemによせる。(目的:Update時のエラー発生率を減らす。次回Update時の差分比較を容易にする)
・Upgradeガイド読んで修正が必要そうなところは潰す。
 https://railsguides.jp/upgrading_ruby_on_rails.html#rails-6-0%E3%81%8B%E3%82%89rails-6-1%E3%81%B8%E3%81%AE%E3%82%A2%E3%83%83%E3%83%97%E3%82%B0%E3%83%AC%E3%83%BC%E3%83%89
・app:update → 試行錯誤して実行できるようにし、動作確認などを行っていく。(「確認観点」シート参照)
・app:update後、configの精査も必要
 参考①:(社内資料につき略)
 参考②:(略)
 app:updateすると、移行後に変更がある設定内容について、自動生成される(new_framework_defaults_x_x.rb)
 最終的には、精査しきって、このnew_framework_defaults_x_x.rbを消せる状態まで持っていく。
 config.load_defaultsのバージョンも上げること。

Update時に可能であればやった方がいい内容
・Update後のバージョンにおいて、非推奨なやり方になっているものは直す。
・各Gemを精査して、不要そうなものは削除(目的:依存性を簡易にしていく)
 精査例:(略)
 ※これはRuby Update時のものですが

・現環境に適合しないGemもUpdateする。(例:推奨バージョンにアップデート対象のバージョンが入っていないなど)
 ※なるべくドキュメントベースで確認すること。
 (現行バージョンでの挙動に問題がなくても、Rails(またはRuby)で新しいバージョン対応版が用意されている場合があり、
  そちらにアップデートした方がトラブルを未然に防げる場合がある)
  バージョンを上げる場合には、アップグレードガイドが用意されている場合があるので、必ずCHANGELOGを確認すること。
・標準Gemfileに記載されている内容と、そうでない内容は分けて書く(目的:今後のUpdate時に差分比較を容易にするため)

最終的に、以下を全て確認する。
・Dockerイメージ再作成&構築確認
・db:migrate:resetができる
・Railsの起動
・bin/rails cでコンソールを開いて、ActiveRecordでの検索が実行できるか(例:User.all
・assets precompileができるか(bin/rails assets:precompile)
・RSpec実行→エラー数確認
・Rubocop実行→警告数確認
・ローカルでの全打鍵確認
・デプロイ可能であるか(対象のバージョンも切り替わっているか)
どの程度かかったか?

2日程度かかりました。

どのような教訓を得たか
  1. 当たり前ですが、基準を作らないと皆自分の基準でやってしまうので、漏れが発生します。
    基準を作ってUpgradeに臨むことが重要です。

まとめ

月並みな内容の教訓が並んでいますが、やはりそう言ったことの積み重ねこそが大切なのだと、この3年間で感じました。
誰かのプロジェクト管理、改善に活かしていただければ幸いです。

▼とらラボの connpass ページ yumenosora.connpass.com

採用情報

虎の穴ラボでは一緒に働く仲間を募集中です! (※DXチームのメンバーは、対外向けには募集されてません。しかし、もし弊チームに配属された時には一緒に頑張りましょう。よろしくお願いいたします)
この記事を読んで、興味を持っていただけた方はぜひ弊社の採用情報をご覧ください。
toranoana-lab.co.jp