はじめに
この記事はHacobu Advent Calendar 2024の24日目の記事です。
こんにちは、Hacobuでバックエンドエンジニアをしている イワカミと申します。普段は MOVO Fleetという動態管理プロダクトの開発をしています。MOVO Fleetについては8日目の記事 で使用している技術が垣間が見えるかなと思います。また、チーム開発については 15日目の記事(私が書きました) にあります。
ちょうど1年前から取り組んでいたバックエンドの生産性や開発者体験向上のために行った改善について書かせていただきます。なお、私だけじゃなく同僚が行った取り組みも含まれています 🙇
依存関係のリファクタリング
過去にチームで作成したライブラリが多数存在しており、メンテナンスが十分に行われていませんでした。具体的には、Goのバージョンや依存しているライブラリ(例:aws-sdk-go)、Linterが古いまま使われていたり、そもそもライブラリの役割が把握されていないという状況がありました。また、弊チームではモノレポではなく、ライブラリやAPI、サービスごとにリポジトリが分かれているため、管理が複雑化していました。
まず、これらを一気に図として書き出し、現状を可視化しました。その過程で多くの発見がありました。例えば、存在すら知らなかったリポジトリや、Go 1.81のまま放置されているリポジトリが見つかりました。現在は基本的にGo 1.21を使用しています。
特に難しかったのは、複数のサービスの共通部分をライブラリとして切り出した結果、ライブラリの数が増えすぎるという問題でした。このため、真に必要な共通ライブラリを再設計し、小さなライブラリを統合する作業を進めました。また、1つのサービスでしか使用されていないライブラリについては利用元にコードを移し、不要なリポジトリを削除しました。これにより、開発環境の管理が大幅に改善しました。
gRPC リポジトリを廃止
私たちのプロダクトは、API → gRPCを利用するサービスという構成になっています。従来は、API → gRPC(protoファイル集) ← サービスというリポジトリ構成でしたが、開発中のgRPC変更頻度が高く、複数人での開発ではビルドエラーやコンフリクトが頻発していました。
そこで、gRPCとサービスを統合する方針に変更しました。この結果、API → サービスという依存関係となり、gRPC変更時の煩雑さが解消されました。また、PRの数が減り、開発効率が大幅に向上しました。
と、自分の手柄みたいに書いてますが、gRPCサービスにまとめたいねって言ってたら、同僚がスッと検証してくれてそんな大変じゃないですよとやってくれた。仮説検証へのフットワークが軽く、サクッと検証して簡単にできそうだったんでやりましたみたいな仕草は見習いたいと思っている。
gRPCのバリデーションを廃止
従来、gRPCのprotoファイルで proto-gen-validate を使用していましたが、以下の理由から廃止することにしました:
- ルールが曖昧で、バリデーションが記述されたりされなかったりしていた。
- エラー防止効果が薄く、エラーメッセージが曖昧でユーザー体験が悪かった。
- ツールの対応状況がバラバラで、開発効率が低下していた。
今後はサービス層でバリデーションを実施する方針に変更しました。これにより、エラーメッセージのカスタマイズ性が向上し、ユーザー体験の改善が期待できます。
CIの高速化
当社で使用しているCircleCIの実行時間を8分から4分半程度に短縮しました。タスクを単体テスト、DB利用テスト、結合テストなどに分割し、並列実行することで処理時間を短縮しました。同僚が主導して進めてくれたこの取り組みは、スケール性の高い解決策でした。
また、並列化によるビルドキャッシュの課題にも対応しました。各タスクでキャッシュの保存と復元を明示的に設定することで、問題を解決しました。ただし、CircleCIのストレージコストが増加するというトレードオフも発生しました。
そのほかの取り組み
- 同僚がGoのホットリロードツールAirを導入してくれました。コードを変更したときも手動で再起動ボタンを押す手間が省け、開発者体験が爆上がりました!
- 開発前にテスト観点レビューを始めました!エッジケースや考慮漏れが減少しました。テストパターンができているとはいえその期待値は絶対ではなく、開発してからも期待値を修正しましょうというようにコミュニケーションが楽になりました。
- ダークローンチが高度化され、毎週リリースをスリップすることがなくなりました。
- schemaspy を導入しました。
- samber/lo を普段使いするようになりコードがスッキリするようになりました。
まとめ
個人的には、これらの改善を、毎週のリリースや機能開発プロジェクトの合間を縫って実施した点がいいなと思っています。特定の日を改善する日として設けたり、リファクタリングにXX週間くださいと調整することなくです。当社のバリューである「Spark Ownership」ってこういうことかなと思いました。