株式会社JMDC データ基盤開発部の樋口です。
JMDCでは「レセプト」「健診」等の様々な医療データをDWHとして構築しています。 事業展開に伴いデータの種類も増加しており、日々、新しい形式・種類のデータを取り込めるようシステム改善を重ねています。
昨今、厚生労働省は「医療と介護の一体的な改革」を掲げており、 JMDCでもこの度、新たに「介護保険」のデータを取込み、分析できるようにいたしました。 今回は「介護データ取込システム構築」プロジェクトの、システム改善の取り組みをご紹介しようと思います。
ストアドプロシージャのWebAPI化による開発効率UP
ビッグデータを扱うため、JMDCの取込システムはストアドプロシージャ(以下ストプロ)を多用しています。
「カナ変換」のような単純なものから、「取込データ正規化」のような業務ロジックが濃いものまで多岐にわたります。
今回、それらのストプロをWebAPIにすることで、開発効率化(および品質担保)を実現しました。
システムの現状と目指したい姿
JMDCは元々レセプト(医療保険)データの取込を得意としていました。
医療保険と介護保険では制度・データ形式で類似点が多いため、既存の医療保険システムの設計をある程度流用することにしました。
(要介護状態や介護事業所など、介護保険特有の仕様もあります)
単純にフレームワークごとコピーして移植&必要な部分だけ改修してもよいのですが、
- 既存システムは長年の運用によりコードが肥大化している
- 単純な移植だと開発チームの能力向上が望めない
というわけで、「業務ロジックは引き継ぎつつ、フレームワークは刷新して作り直す」ことにしました。
この構成の課題として、以下があります。
- 業務ロジックがDBレイヤに貼りついてしまい、アプリ層で構成管理が出来ないため管理・開発コストが高い。
- クライアントにDBの接続権限を与える必要がある。
- メンテナンス等で一部機能だけ利用停止するような制御ができない。
ポイントは以下です。
- 業務ロジックは出来る限りコンテナ(アプリケーション)側に持つ。
- WebAPIを間に挟むことで、DBをクライアントから隠蔽する。
- 業務ロジックをコンテナ上で提供することで、一部機能の停止等のメンテナンスをしやすくする。
やったこと
1. 移植元ストプロの棚卸
- その処理が何のためにあるのか?をあらためて考え直す。
- その処理は業務上本当に必要か。
- 不要なものを移植していないか。
- 現行踏襲、という単語は思考停止の兆候なので使わないようにする。(でも使ってしまいがちですよね…)
- その処理は業務上本当に必要か。
- その処理はどう実装すべきか。
- ストプロとして残すかWebAPIとして書き直すか。
- 今回の判断基準としては「他のSQLから呼び出される必要がある処理(カナ変換関数など)」のみをストプロとしてDBレイヤに残すことにした。
- その処理の粒度は適切か。他の処理と統合/分割すべきか。
- 移植元のストプロは「呼び出し側でトランザクション管理」「ストプロ内でトランザクション管理」するものが混在していた。
- APIをまたぐトランザクションは避けたいので、1つのAPI内でトランザクション完結させるよう、処理単位を見直す。
- 「どこまでを1つの処理とみなすべきか」「移植元の設計のうち、引き継ぐべきもの / 変えないといけないもの」をひたすら突き詰める。
- たぶんここが一番大変だった。
- やっている途中「これならストプロのまま移植した方が楽だったのでは?」とか「ただWebAPI化したいだけになっていないか?」と自問自答を繰り返す。
2. 棚卸結果に基づき、WebAPIのインターフェース設計
- 入力パラメータおよび出力結果は全てJSON形式に統一する。
- なるべくRESTfulなインターフェースを心がけた。
- システムの性格上、「データ受信」とか「週次データ確定」のような単一リソースに紐づかない処理も多いので、あまり徹底できてはいない。
- WebAPI仕様書をSwagger等で記述できるか検討したが、結局Excel管理にした。
- Swagger(OpenAPI形式)記法の学習・チーム教育コストが高いため、今回は断念。
- yaml形式だと画像やフキダシ等での注釈(設計意図)を挿入しにくい。
3. 移植元ストアドプロシージャをSQL文で書き直し
- そんなに苦労しなかったので省略。ただひたすら量をこなす。
4. WebAPIサーバをコンテナ化
- 既存システムではサーバスクリプトとしてPythonを使用していたため、Pythonで書けるフレームワーク何がいいかなーと検討
- FlaskとFastAPIで比較した結果、FastAPIを選定
5. 書き直したSQL文を、WebAPIサーバ(FastAPI)に組み込み
- 上に同じく、ただひたすら量をこなす。
最終的なプログラム本数は、以下のようになりました。
プログラム種別 | 移植元 | 移植先 |
---|---|---|
ストプロ(業務ロジック) | 45 | 0 |
ストプロ(ユーザ定義関数) | 30 | 19 |
シェル/Pythonスクリプト | 17 | 5 |
WebAPI | 0 | 35 |
移植元/移植先でシステム要件が異なるため単純な本数比較にあまり意味はないのですが、 業務ロジックをDBレイヤから完全に引きはがし、WebAPI(コンテナ)に移動できたのでよしとしましょう。
得られた効果
以上の取り組みにより、既存システムが抱えていた課題は解消できました。
課題 | 移植元 | 移植先 |
---|---|---|
業務ロジックの実装場所(層) | △:ストプロ(DB層) | 〇:WebAPIコンテナ(アプリ層)に移動できた |
利用者へのDB接続権限 | ×:必要 | 〇:WebAPI内にDB接続を隠蔽できた |
メンテナンス時の一部機能停止 | ×:不可 | 〇:コンテナ化したことで、必要な機能のみに絞って提供できるようになった |
また、副産物として、以下の効果もありました。(コレも狙いの一つではあった)
- リリース作業が大幅に楽になった。
- 開発環境で動作検証したコンテナをエクスポート&インポートで済む。
- テストがしやすくなった。
- インタフェースをWebAPIにしたことで、フレームワークの支援を得やすくなった。
- テストシナリオをHTTPリクエストとして保存しておくことで、CIテストがしやすくなった。
特に「テストがしやすくなった」のは本当に実感しました。
- ビッグデータを抱える基幹システムはなかなかモダンな開発を採用しにくく、テスト工程ではコマンド叩いてエビデンス取得して、というサイクルを手作業で行うことが多くなりがち。
- 今回、WebAPIのテストには Visual Studio Code + Thunder Client(拡張機能)を使用して、テスト効率化が実現できた。
- プロジェクト中、諸事情によりテスト工程に割ける人員が当初予定から半減してしまったが、Thunder Clientのおかげで当初想定より大きくテスト工数を圧縮できた。
- 設計の基本部分は既存システムを参考にできたが、やはり介護保険独自の仕様についてはどうしても試行錯誤して作りこんでいく必要があった。トライ&エラーを繰り返す中で、「他の実装済処理に悪影響がないこと」を担保できるのは精神衛生上助かった。
- コレがなかったらたぶんリリースできてなかったと思う。マジ偉大。
修正内容が安全か、単体テストで担保してます。
この画像だと1件Failしてますね…。(コードかテストケースのどちらかが正しくない)
開発期間3か月で、計45211回の自動テストを実行しました。
おわりに
今回ご紹介した介護保険データのように、JMDCでは日々、新しい形式のデータを取り込めるようシステム改善しています。
が、やはりリアルワールドなデータを扱う以上、日々新しい要求や課題に直面し続けるのが宿命です。今回構築したシステムも、きっと1年後、ひょっとしたら半年、1か月後には新たな課題に直面していることでしょう。
頭を抱えたくなることもありますが、自分が考えた対策がビシッとハマったときはヨシ!とひそかにガッツポーズをしています。
このような取り組みに興味を持たれた方がいらっしゃいましたら、ぜひカジュアル面談でお話ししましょう!
【ビッグデータ開発エンジニア募集中!】
https://hrmos.co/pages/jmdc/jobs/0000166hrmos.co