# サービス概要と立ち位置
らくらく健助は保険者向けの分析システムとなっており、事前に健保からいただいたレセプトデータを様々な条件で分析、可視化するシステムになります。
このチームではエンジニアリーダーとしての立ち位置で技術負債の解消を主業務に携わっています。
# ロード処理の改善
週末にデータの洗い替え処理を行っているのですが、データ量の増加とともに処理が36時間もかかるようになっていた。
- 原因
- データ量の増加とともに各SQLの遅延
- 32億をこえるレコードでも1つのinsert分で実行していた(処理時間は5時間越え)
- シェルスクリプトのみに実装されていて、SQLの取り回しなどがやりにくく、誰も改善しようとしてこなかった
- 対策
- DBチューニングを行ったが36時間が30時間程度になった
- 処理が12時間以内に終了したいのでさらにシェルスクリプトの脱却を提案
- シェルスクリプトからGoの実装に変更
- 重いinsert分は分割してinserを行うように変更
- 分割の仕方は固定ではなく、設定ファイルでチューニングできるように調整
- 分割したSQLは単体実行するのでなく並列実行を行った。
- 並列実行を要所要所で取り入れるためにGo言語を採用した
- 結果
- 36時間かかっていた処理が10時間に短縮
- 導入後1年近く経過し、データ量が当初より1.5倍に増加しているが現在も10時間で処理を終えている
# C#からGo言語の切り替えプロジェクト
現在多くの点で技術負債を多く抱えており、1つ1つ解消しようにも解消作業時に別の問題が発生することが当たり前になっている。
実装内容もあまりコントロールされてこなかったためから統一性がなく非常に読みにくくなっている。
既存のアプリからGo言語へのプログラム言語移行を提案し採用されました。
Go言語を選択した理由は、
- 今の問題点として大きいinsert処理を1つのSQLで済ませており、分割実行するなどで改善すること計画
- Go言語だと並列処理の実装が容易のため向いていると判断した
- DBにVerticaを採用しているためDB周りでは自作する必要性があるケースがおおく、接続周りではロード処理での実績が評価された。
- SQL頼みの実装が多いが、BE側での処理を取り入れようとしたときにデータ量が多いケースが考えられメモリ効率がいいGo言語を採用することで処理できる範囲を増やそうとした。
- 現在
アーキテクトにはクリーンアーキテクトを採用
開発手法には、ドメイン駆動開発に近い状態
- 既存仕様の把握
- 仕様の整理
- 複数のEPに行われているが本当に必要な処理かの検討
- パラメータ数の見直し
- ドメインに落とし込み工数見積もりを行い実装
- 実装とテストコード実装はセットで行い、見積もりもテストコードの実装を含むようにしている。
開発着手していてまだ大きい成果は出せていないが、処理が重くないログイン後からメイン画面での処理が半減させることに成功し、
Go言語へのリファクタリングのみでなく既存の仕様整理も行いながらパフォーマンスの改選を進めている。
# チーム開発のための意識改革
現在の部署ではエンジニアの平均在籍率が2年を下回る状態となっており、開発がチームより個人で行っている状態だった。
そこで以下の取り組みを導入にチームで開発できる体制づくりに努めた。
- PRサイズの見直し
- 背景
どんなに大きい開発案件でも1つのPRで済ませていることが常態化してしまっており、
レビューが難しくなっていた。
レビューで不具合が見つからずに、開発環境にデプロイして他部署の方が見れるようになった時に指摘されることが3,4件あることが常態化してしまっていて、リリースの延期にもつながってしまっていた。
- 対応
案件着手時に仕様整理とともに着手順をチームで決めるようにした。
着手順は、PR作成タイミング単位でフローを決めて細かくレビューできるルールを取り入れた。
その結果、レビューで見逃していて不具合がレビューで見つかるようになり、リリースの延期が起きにくくなった。
- テストコードの導入
- 背景
テストコードが1つもなくすべてを手作業で動作確認が必要な状態となっていた。
また、一部の仕様は複雑になっているためにすべての動作確認するのに膨大な確認時間を要してしまうようになってしまい、経験で一部のみを実施することとして運用してきた。
しかし、実態としては仕様追加や修正により関係がないとされた箇所で不具合が見つかることは珍しくなくスケジュールの見直しが頻繁に行われていて、開始直後に計画したスケジュール通りに進まず2か月ほど伸びてしまうことが当たり前の風潮になっていた。
- 対応
フロント、バックエンドともにテストコードを導入した。
- フロントエンド
フロントエンドは実装がテストコードを書くことが非常に困難になる作りになってしまっていたので、
フロントとバックエンド間の切り分けをできるようにAPIの処理周りの整備を優先して実装した。
APIの利用回りが想定通りに取得できているかを担保できるようにテストコードを用意したことで
フロントエンド内のデータ取りまわしがおかしいことに気づけやすくした。
また、e2eとしてCypressも導入して、リリース後の動作確認やリリース前の最終確認として実施できるようにしたことでリリース時のトラブルが激減し、スムーズなリリースも実施できるようになった。
- バックエンド
すべての仕様をカバーするテストコードを導入することは困難のため、
各APIに対応した基本的な仕様に対するテストコードを実装した。
サービスのテストコードといったレイヤー毎にテストコードを用意することは
元の実装がかなり密結合してしまっていたので見送ったが、
新しい実装する際は疎結合になるように実装し、テストコードも用意するようにルールを制定した。
守れているかはPRで確認するようにしており徐々にチームの認知も高まってきた。
まだまだ、仕様に対するカバー率が低いために効果が目に見えては来ていないが、
チームの意識は変わってきており、テストコードがあることでデグレがあることに気づけた報告は
朝会などであがっており実装の品質向上に一役買っている。