hacomono TECH BLOG

フィットネスクラブやスクールなどの顧客管理・予約・決済を行う、業界特化型SaaS「hacomono」を提供する会社のテックブログです!

プロダクトエンジニアがプロダクト基盤の改善に関わる意味

hacomono の会計決済グループでプロダクトエンジニアをやっている江口(@akagire)です。
これまで、 hacomono では スタートアップならではの Ruby on Rails の負債と向き合ってきました。

hacomono API Ruby 3.3 / Rails 7.1 へのアップデート - hacomono TECH BLOG
モノリスなRailsにモジュラーモノリスを導入した話 - hacomono TECH BLOG
hacomono Rails プロダクトの改善の取り組みの話 - hacomono TECH BLOG
モジュラーモノリス導入がもたらした功罪 - hacomono TECH BLOG

これらの取り組みにより、徐々に開発体験はよくなってきています。それと同時に、 hacomono の Ruby on Rails が採用している Clean Architecture 構造自体への見直しは、Modular Monolith の採用・運用を経て、徐々に活発に議論され始めました。
(Clean Architecture や Modular Monolith については、上記の参考記事ご覧ください)

一般的な Rails の構造に近いコードであれば、新たにジョインするメンバーがこれまでの Rails 経験をすぐに活かせたり、LLM も既存の知識やパターンを活用しやすくなります。一方で、 hacomono で採用している Clean Architecture は Rails の基本的なディレクトリ構成を使わずに実現しているため独自性が高く、調査や実装のたびにコードベース固有の前提を探索する必要があり、人間にとっても AI にとっても初動コストが高くなります。

AI を継続的に開発プロセスへ組み込むうえでは、生成量や探索量を抑え、より少ないコンテキストで正しく扱えるコード構造にしていくことが重要になってきています。
そこでいま hacomono が採用したのは Ruby on Rails に乗り直す (Rails way 化)という選択です。

この取り組みは RubyKaigi 2026 の hacomono ブースでも紹介していた、技術負債との向き合い方になります。一言で言えば、Rails → Rails のリプレース だと思っていただくのがイメージしやすいと思います。
具体的な移行方法や内容は、hacomono のアプリケーションレイヤーの改善を責務として組織されている、プロダクト基盤チームからのアウトプットに委ねたいと思います。

ただ、Rails way 化は、主担当であるプロダクト基盤チームにおまかせ・他チームはレビューするだけ、でいいような作業ではない、というのが現在の私の見解です。

特に、今回移行対象にした請求ドメインは、hacomono の料金計算の根幹を担う部分です。早いうちに Rails way 化し、不具合を出にくくし、今後の開発を進めやすくすることを狙い、プロダクト基盤部に続き、会計決済チームでも移行する判断をしました。

本記事では、Rails way 化の技術的な詳細そのものよりも、固有ドメイン(具体的には会計決済領域)を担当するプロダクトエンジニアの立場から、AI を活用した大規模リプレースにどう向き合ったか、そこで得た学びを中心に紹介します。

今回の経験から、AI 時代のリプレース作業において重要なのは、「AI に任せられる作業を増やすこと」と「人間が責任を持つべき判断を事前に明確にすること」の2点だと感じました。

Rails way 化とは何を指すのか

前提として、ここでいう Rails way 化とは、hacomono 独自の Clean Architecture 的な構造に分散していた手続きを、Rails の標準的な責務分担に寄せ直す取り組みを指します。具体的には、HTTP リクエストに対する手続きは controller に、状態や業務上の制約は Active Record model に寄せ、必要に応じて Concern や PORO に分離する、という方針です。

繰り返しになりますが、内容の詳細は今後のエントリに委ねます。

仕様移植を行う上で重要な「既存のテスト」

hacomono は大規模化したプロダクトなので、人力で全てリプレースを行うことは現実的ではありません。よって、AI を使ったコード生成をうまく使う必要があります。

一方、生成 AI の出力は非決定的であり、同じ入力から常に同じ結果が得られるとは限りません。そのため、生成されたコードが既存仕様を保っていることは、別の仕組みで確認する必要があります。

生成結果が仕様を変えていないことを機械的に確認するうえで、最も重要な拠り所になるのが既存のテスト群です。このテスト群も移植し、TDD のプロセスでコード生成をさせることで、先に適切な入力と出力を定義できれば、それが AI に対するハーネスとして振る舞い、テストコードという決定的仕組みの中で AI を使うことができます。

これは、地道に続けてきたテストコードの拡充が効いてきました。

さらに、QA チームが整備している自動リグレッションテストも非常に大きい武器になりました。

専任担当からチームに還してQA全員で取り組むテスト自動化 - Speaker Deck

ドメイン開発チームがリプレースでぶつかった壁

ここまで仕組みが整うと、一見、機械的なリプレース作業は AI とテストに任せられるようにも思えます。前述の通り、これまで培ってきた UT やリグレッションテストもあります。

しかし、実際にやってみると、今回移行した請求ドメインでは、それだけでは足りないことがよくわかりました。各エンジニアが Rails way に向き合い、学習する必要がある場面にも多く直面しました。

そもそも全員が Rails way に慣れていく必要がある

繰り返しになりますが、hacomono の Rails は、いわゆる Ruby on Rails 的な書き方ではありません。よって、Active Record の便利な機能に精通している人は多くなく、特にドメイン開発チームにはその知見が不足していました。

よって、AIによって生成された model が正しい業務ロジックを記述しているか、 controller に記された手続きが妥当か、複雑なロジックを外部化した抽象 model や PORO や Concern に切り出されたロジックや切り出し方は適切か、といった判断は、移行直後はなかなか難しいところがありました。

具体的には、複数のユースケースから共有されているサービスロジックを model に分離する際の粒度や、Concern に切り出すべき共通化なのか、たまたま似ているだけの業務ルールなのかの判断は、人間側の業務ロジックに対する深い理解が必要でした。

ですが、この学習コストは必要な投資だと考えています。

なぜなら、AI が移植したコードに対する責任は、私たちプロダクトエンジニアにあるからです。テストは通っているが、なぜその実装で既存の振る舞いを保てているのか説明できない状態では、既存の不具合が見つかった場合や機能追加をする際に、どのようなアプローチが正しい修正方法なのかをエンジニアが考えず、恒常的に AI に丸投げすることになってしまいます。
長期的にはそういう戦い方ができる時代が来るかもしれませんが、現在のAIの精度ではやはり難しいと思いますし、少なくとも現時点では、プロダクトに責任を持つエンジニアとして健全な状態とは言いづらいと感じています。

AI が出してきた提案や、作成した成果物のなかに埋め込まれた違和感…具体的には、拡張性に対する懸念、意図と異なるクラス名・メソッド名・変数名の採用、インタフェース設計の不備(特に Ruby の持つ表現力を活かしきれていない意味論の機微の差)などに気づき、フィードバックできるか、それができるための、必要な投資です。

テストでカバーしきれていないシナリオに気づく

大規模なプロダクトでは、既存テストが通っていても仕様差分が入り込む余地があります。そこで重要になるのは、そのドメイン・業務を理解している人間によるチェックです。

実際、会計領域の移行に伴って、一見問題なさそうだったが、人のレビューによって発見した不備は少なからずありました。

特に金額計算ロジックについては、単一の正常系だけでなく、契約期間・日割り・割引・退会・店舗変更などの条件が組み合わさります。既存テストが代表ケースを押さえていても、条件の組み合わせによっては仕様差分が表面化します。

そこで、業務上リスクの高い組み合わせを洗い出し、追加のテストケースとして落とし込むように検証パターンを増やしたところ、結果的に不具合を発見し修正につながった事例もありました。
本来であれば、この違和感を言語化できるのがあるべき姿ではありますが、仮に言語化できなかったとしても「あやしいな…」「違和感があるな…」という感覚を共有できるのが、ドメイン開発を行うチームがリプレース作業を行うメリットだと感じます。

もちろん、この検証設計でも AI は活用しました。たとえば、条件の組み合わせをどの粒度でテストケースに落とすべきかを AI に相談し、ペアワイズ法を使って重要な組み合わせを効率よくカバーする方針を取りました。

Rails way に移行して感じている効果

意識していなかった副次的な効果もありました。

代表的な効果として、従来の hacomono の Clean Architecture 的な構造では、Ruby LSP が適切に推論しづらい場面があり、参照元コードを頻繁に読む必要があったのですが、Rails way にした箇所は適切にサジェストされるようになり、手でコードを書く時のヒントが充実しました。これは AI にコーディングさせる際にも有効で、 Claude Code の LSP プラグインがヒント情報を利用できるようになり、コードベース固有の前提を探るための探索的なトークン消費を抑えられる可能性があります。

また、個々の usecase に分散していた業務ロジックが model に集約されたことで、ユースケースごとに仕様不整合の存在に気づけたということも大きいです。具体的な対策方針はこれから考えることになりますが、これまでのユースケース単位・コードオーナー制度のような仕組みでは気づけなかった新たな負債も見つかってきた(可視化された)のは、とても有意義な発見になると思います。

まとめ

hacomono ではこれまで、技術負債の返済に継続して取り組んできました。その多くは、テストコード拡充のようなドメイン特化組織ならではの取り組みを除くと、主に技術特化組織が先導してきました。

今回の Rails way へのリプレースは、もちろん引き続き技術特化組織が引っ張っていきますが、それに任せるのではなく、プロダクトエンジニアも関与度合いを高め、業務理解が必要な領域に対しても、プロダクトエンジニア自身が踏み込んでいく一つの大きな試金石になります。

ほかにも、不要なバッチを削減したり、監視体制を強化するといった、インフラ部門やSRE部門が牽引してきた領域についても、今の会計決済チームは積極的に取り組むことで、日々の運用負荷を下げ、新機能開発のためのケイパビリティを確保する取り組みも並行して行う方向性に舵を切っています。

専門チームがあるからこそ、わからないことを気軽に聞け、挑戦できる体制になっているのは非常に幸運です。プロダクトエンジニアとしての成長と、いち技術者としての幅を広げる成長の両方ができていると感じます。

そもそも、技術に明るいことはプロダクトの実装方針の幅を広げます。その結果、スケーラビリティや低い運用負荷といった非機能要件も実現しやすくなります。だからこそ、このような取り組みはロールにとらわれずに実践することが大切だと考えています。

これを hacomono での再現性ある取り組みとして展開できるように、今後も技術負債と向き合いつつ、プロダクトの成長を加速させていきます。