前置き
当時は現職であったが今は前職、当時と今で考え方に変化が生じたため一部改変しています
ここ一年、現職において0→1フェーズからすくすく育ってきたRailsプロジェクトのバックエンド全般を任されており、それなりに戦い方の感触を掴みつつある (と思っていた) ので当時の思い出の共有がてら自分なりの考えを書き殴っています。
(当時の)現状
- サービスのコアとなるドメインロジックが、いろいろな箇所で重複定義されいる
- テストコードが一切書かれていない
- テストを書かずに人力動作確認でリリースまで進めるが、高確率で予期せぬデグレが発生する
- リリース後しばらくは何らかのデグレ対応に追われるため、スムーズに次の開発へと移行できない
考察
テストがないことに起因した既存実装の考慮漏れによるリリース後のデグレに一番時間が割かれてしまうため、テストを書いてCIでデグレに気づけるようになるとリリース後のデグレ工数をかなり削減できそう
ただ、既存の実装のままだと、そのテストコードが書きづらいため、テストを実装していく前に、アプリケーションコードの設計改善が必要だと感じ、今のプロダクトの規模に合わせて、中規模以上でのRailsシステムにおけるテストが書きやすく、かつ変更容易な設計を模索していく必要があります。
どう戦っていくと良さそうか(当時の反省も踏まえて)
軽量DDD×クリーンアーキテクチャな構成を目指して、やれentityだのusecase層だのを生やしてみたが、Railsの思想とマッチしないためかえって混乱を招いてしまった。
Rails wayなMVCアーキテクチャをベースに複雑かつ再利用性の高いロジックのみをservice層に定義して手厚くテストを実装する くらいの運用が現実解なのではないかなと個人的には考えている。
Railsの場合、controllerにドメイン固有のロジックが書かれたとしても、IN/OUTのみに焦点を絞ったテストであれば(Rspecのrequest spec等)実装にはそこまで苦労しない(最初のテスト導入のハードルは低い)
→ その後にcontrollerからドメインのロジックを適宜modelやserviceクラスに移植していくことで単体テストの実装が行えるようになる
Rails wayから外れたアーキテクチャを考える前に、Railsエコシステムの中で解決策がないか先に探すことをおすすめします。
どちらの構成にせよ、テストの実装は円滑なサービスの運用、拡充に必要不可欠なのでここに費やすリソースを削ることは絶対にしてはいけないです(ここだけは断言)。
テストコード実装の開始時期も早ければ早いほど好ましい
まだまだサービスが大きくなるのであれば、Rails wayでの運用が破綻しない範囲の大きさに収まるように分割(マイクロサービス化)するか、最近であればRails→Golang等への移植の事例をだいぶ見かけるので、その流れに早めに乗っていくのがいいのではと思います。
移植に関しても、完全移植を目指すのではなく、変更頻度が高く質を担保したい部分のみに絞る みたいなスタンスがやりやすいな と感じています。
並行稼働することで、とっとと市場に出して反応を探りたいみたいな機能は、Railsでサクッと実装して出す みたいな柔軟が動きができるようになるのはかなりメリットなんじゃないかなと思っています。