クラウド電子カルテを支えるテクノロジー

冨岡純氏(以下、冨岡):「クラウド電子カルテを支えるテクノロジーの光と闇」というタイトルで発表させていただきます。エムスリーの冨岡と申します。

電子カルテチームのリーダーをやっていて、Scalaや関数型プログラミングが好きです。あとは、「育休エヴァンジェリスト」というのを社内で勝手にやっていて、用もないのに育休を勧めるということをやっています。

来週からアメリカに2ヶ月ぐらい行くので、エムスリーにはずっといるんですけど、今日が(渡米前の)最終出社でした。

今、どこの会社もエンジニアを欲してると思いますが、エムスリーも欲しています。エムスリーではTech Blogというブログを書いています。

この前せっかく育休を取ったので、育休の知見を共有したかったというのと、よこしまな気持ちとしては、「(男性でも普通に)育休が取れるんだ、へぇー」みたいな感じで、エンジニアの働き方に興味のある人や、(働き方に)こだわりのあるエンジニアに伝わればいいなと思い、「育児休業を支えるあれこれ」というブログを書かせていただきました。

このブログは割とバズったと思うんですが、よく見るとカテゴリーが「暮らし」になっていて、すごく暖かみのあるコメントをいただきましたが、エンジニアに刺さったかはよくわからないという悲しいこともありました。

(会場笑)

今日は育休の話は全然関係なくて、電子カルテの話をします。

電子カルテとは何か?

電子カルテはあまり馴染みがないと思うので、簡単に説明すると、クリニックや病院に行った時、だいたいこんなフローになると思います。

最初に受付をして、保険証とかを出して、先生の診察があって、「このお薬を処方しますね」と言われて、最後に会計をすると思います。

電子カルテは診察の時に出てくるサービスです。

患者への医療行為、「この薬を出しました」とか、「この検査をしました」とかを記録するサービスです。

これと切っても切れない関係にあるのが、レセコン(レセプトコンピューター)で、これが会計の計算を行います。つまり、「この薬を出して、この検査をしたからいくらです」みたいなことを計算します。

ほとんどの方(が支払う医療費)は3割負担だと思うんですけど、残り7割は一時的に医療機関が負担していて、それを保険者に請求するという業務があって、それをやるのがレセコンです。ざっくり言うと、そんなイメージです。

クラウド電子カルテの現状

やっと本題に入りますが、「電子カルテを支えるイケてるモダンな光のテクノロジー」「電子カルテを支えるために、こうするしかなかった闇のテクノロジー」について話そうと思います。

今回は闇を話しすぎるとよくないので、なるべく光成分が多めになるように話そうと思います。闇の部分は懇親会で聞いていただけたらと思います。とは言え、闇も入ってるので安心してください。

まず、「クラウドって素晴らしいテクノロジーですよね」と。今さらそう言っても、「そりゃそうでしょ」みたいな感じだと思いますが、私たちの業界での導入率は低いです。

日本には約10万件のクリニックがあるんですけど、さっき言ったレセコンという会計のソフトウェアは、ほとんどのクリニックに入ってます。

電子カルテはどれぐらい入ってるかというと3割ぐらいで、だいたい3万件のクリニックに入っていると言われています。

さらに、その中でクラウド電子カルテはどれぐらいかと言うと、(グラフにすると)もう見えないぐらいです。

「電カル導入の5パーセント未満」ということで、全体の2パーセントしか、クラウド電子カルテは入っていない。こういうヤバイ業界なんです。

クラウド×医療は追い風

改めて考えると、「やっぱりクラウドはいいな」と思ったことがいくつかあります。

「更新が容易」とか、「どこからでもアクセスできます」とか。「AWSに乗っていると、Multi AZで対災害性があります」というふうに、いろんなサービスを利用できたり、コストメリットがあったり、いろいろいいところがあります。

最近、AWSは「日本の医療情報ガイドライン」を出しています。

これはなにかというと、電子カルテや医療情報を扱うサービスに対して、こう実装すべきとか、こう管理すべきみたいなガイドラインです。

その中でAWSを使っていると、「ここは(基準を)満たしていて、ここはあなたの責任です」みたいに、指針を示してくれるものを出していて、クラウドを使う人にとっては追い風な環境です。

クラウド電子カルテとレセコンを連携させる

ただし、良いことばかりではありません。クラウド電子カルテを導入している、ほとんどのクリニックでは、院内がすごくカオスになっています。PACSという画像を管理するソフトウェアだったり、レセコンだったり、その他の院内機器が、院内ネットワークの中に存在しています。

さっき(クラウド)電子カルテで保存したものを、レセコンで会計することが必要なんですが、ここをどうやって連携しようかという話になります。そこがとてもつらいです。

私たちはこう(解決)しましたということで、これが正解かどうかはわからないですけど、Socket.IOを使った双方向通信で、クラウド側からも干渉できるようにというのを、実現してやっています。

サーバーサイドはNode.jsで書かれていて、クライアント側はJavaで書かれています。こういうのが闇の部分です。

「クラウド良いよね」と言っていたのに、クラウドじゃないソフトウェアが入ってしまうと、「院内ネットワーク側のアップデートどうしよう」「なんかつながらないんです」ということになって、調査するのも厳しいです。

Javaだからというのもあって、JREをお客さんの環境に入れてもらってるんですけど、これは継続的にアップデートすることが必要で、これは誰がやるんだろうという問題もあります。なので、今はElectronへの移行を検討中です。

ただ全部クラウドになったら、こんなことを考えなくていいので、過渡期感はあるんですけど、現時点ではすごくつらいです。

(スライドを指して)クラウドのまとめです。

クラウドは最高です。みなさん普通に使っていると思うんですけど、「クラウドは最高だ」と言っておきます。はやく全部がクラウドの世界になって欲しいです。

なんかごめんなさい、こんな話を聞いていて楽しいですかね……。

(会場笑)

なるべくハキハキしゃべろうと思います。

避けては通れないレセコン機能

次はレセコンです。

さっき言っていた会計ソフトウェアなんですけど、これも電子カルテを作る上での闇と言うか、カルテの情報をレセコンと同期できないカルテは存在価値がないぐらいなので、レセコンと連携することが必須です。

レセコンは診療報酬の点数を計算したり、保険請求をしたりとか、なんか大変そうな感じがして、開発ハードルがすごく高いんです。

世の中にはレセコンをどうするかでやり方が2つあって、1つは連携型です。サードパーティのレセコンと連携します。これはUXが悪くなりますよね。ソフトウェアを2つ扱わなきゃいけないので、現場の学習コストは高いです。

ただ開発コストは中ぐらいかなと思っています。小じゃない理由は、キレイにAPIを提供しているレセコンもそんなにないので、こっちもがんばらなきゃいけない、というのがあります。

2つ目が一体型で、自社開発のレセコンです。レセコンとか電子カルテを、意識せずともスムーズに使えるやつで、もちろんUXはいいんですけど、開発コストはかなり高いです。

私たちはどうしたかと言うと、2015年に連携型として、ほかのレセコンに依存するかたちでローンチしました。同時にレセコン機能の先行調査を開始していて、去年ついに、一体型、レセコン単体機能をリリースしました。

複雑な業務知識に立ち向かう

複雑な処理をどうするかが問題になっていたんですが、3つのポイントがあると思っています。

Scalaと、Functional Programming、Clean Architectureを挙げました。

Scalaはオブジェクト指向と関数型がクロスしているような言語だと言っています。オブジェクト指向的に人間が理解しやすくて、しかも関数型の良さがあって堅牢です。

関数型は最高で、テストしやすいとか、再利用しやすいとか、そういうよさがあります。レセコンが主にやっている点数計算という処理は、基本的には巨大な関数で、患者の情報と、おこなった医療行為の情報を入力すると、点数が出てくる。すごく巨大な関数なので、関数型プログラミングの考え方は(課題解決と)すごく一致するなと思います。

Clean Architectureのエッセンスを採用

次に、「Clean Architectureのエッセンスを拝借」と言っていますが、あまり「これがClean Architectureだ」と言うと、すごい強い人に刺されそうな気がしたので、控えめに言ってます。

複雑な計算ルールと作用、つまりDBへのアクセスとか、副作用とかよく言いますけど、そういう作用を分離するのが、Clean Architectureにフィットしているんではないかと思います。

Clean Architectureって聞いたことない人も、もしかしたら居るかもしれないですけど、(スライドを指して)こういうもので、ビジネスルールのポリシーを(円の)1番真ん中に置いています。

これはどこにも依存していない、素晴らしい純粋な世界で存在しているもので、そこから順番に(円の)外に行くにしたがって、アプリケーションの具体的な話になっていきます。(Clean Architectureは)そこの依存関係を、はっきりさせようみたいなことだと思います。

EntitiesとUse Casesの層について話しますが、Entitiesはコアになるビジネスルールを表現します。今回の場合は、会計計算における実際の計算の処理だったり、保険請求用の集計をするんですけど、その集計の処理だったりを書きます。

これは関数型の良さかなと思いますが、純粋なコンポーネントのみで構成されていて、定数や不変オブジェクトのみを利用しているので、一度宣言したものが途中で変わるみたいなことがまったくない状態で書かれています。

副作用、つまりDBIOとか非同期処理、Exceptionみたいな、割と実装の都合であらわれてしまうようなものはこの層にはあらわれず、全部純粋なコンポーネントなので、テストとか再利用がしやすいです。あと、パッと見たときに型だけ見れば、だいたい何をやっているのかわかるので、すごく理解しやすかったり、嬉しいことはいっぱいあります。

今回、ここが最も複雑なため、ここのテストを厚くしたいので、こういう作用を分離して、キレイに書くつもりでやりました。

(スライドを指して)これは例なんですけど、例えば、calculateFee。

点数や報酬を計算する際に、診療行為のリストや患者のリストを渡すと、「これは計算するには値しない入力です」みたいにエラーがでたり、もしくはちゃんと計算された値が返ってくる。そういう関数になります。

これは副作用がなくて、すごく純粋な関数なので素直にテストができます。この層で起こるエラーは、(ネットワークに)接続できないというような技術的な関心ごとのエラーじゃなくて、例えば、ビジネスルールとして「この組み合わせでは計算できません」とか、そういうエラーが表現されるべきなので、値としてモデリングします。

Use Casesを解説

次のUse Casesですが、永続化とかを含むアプリケーション要件みたいなのが出てくるのが、この層になっています。

ここに書いていますが、DBIOとかScalaだと非同期処理をFutureという型で表現するんですけど、Futureが出てくるのはこの層です。

これはScalaの良さであるfor式で、作用を直列に処理するのがすごく得意な式の表現です。これがあるとすごく嬉しくて、作用がどこで起こるのかが一目瞭然であったり、作用の失敗するケースとかを、あんまり考えずに実装できるのが良いところだと思います。

Tagless Finalについては、興味があったら聞いてください。

(スライドを指して)これは実際に動くコードではないんですけど、こんな雰囲気のコードになります。

まず最初に、ここで起こす作用の型を宣言します。宣言する必要はないんですけど、決めておきます。

今回の場合は非同期に返ってくるエラー、もしくは他のなにかという作用(EitherT[Future, CalculationUseCaseError, A])を考えます。

その作用を起こす処理、例えば、非同期に患者を取ってきて失敗するか、ちゃんと患者が返ってくるか。非同期に処置行為一覧を取ってきて失敗するか、もしくは処置行為一覧が返ってくるかみたいな、そういう処理を書いておきます。

これはキレイに書くなら、Interfaceに依存するようにします。例えば、「~Repository」みたいなInterfaceを作って、抽象的にしておいて、それをDBから取ってくるのか、ファイルから取ってくるのかを外から注入するようにすると、キレイになるかなと思います。

それをどう使うか。

ここでScalaのfor式が出てきて、使ったことある人は「ハイハイ」という感じだと思うんですけど、さっきのfetch(API)のようなハッピーなケース、1番良い状態で、キレイに取れたケースに関してだけ、次にいける。そういう式を書けます。

途中で起こる失敗とか、そこで早くリターンしようとか、そういうことは考えずにこういうことがキレイに書けます。

ここで「Entitiesの層の純粋な処理を利用する」というような依存関係になります。

もう1個いいところをあげるとすると、sbtのMulti project buildsというのがあって、要するに1つのファイルでサブプロジェクトをいっぱい作るみたいなやつなんですけど、それ(サブプロジェクト)同士の依存関係も明記することができます。

例えば、「UseCases層はEntities層に依存してますよ」とか、「Entities層にはDBアクセスライブラリは使いませんよ」とか、そういうサードパーティのライブラリを含めて、どういう依存を使っているのかを明示しておくことができます。

なので、Entities層から依存してないDBのコードは呼ぶことすらできない感じで、すごくキレイに書けるかなと思います。

レガシーな業界をクラウド化するために

結局どうなったかと言うと、こんな感じに現状はなっていて、最初は連携型で始まったので、連携型の世界があります。

見ると嫌ですよね。マジかみたいな。「本当にやってんの?」みたいな感じがしませんか。どうですか。

私は闇だと思うんですけど、みんなそうでもない……ですね。ありがとうございます。一体型の世界はめっちゃ普通ですよね。

Railsが受けて、後ろにScalaがいるみたいな。つまり、クラウド最高だなということです。

みなさんもクラウドの住人なので、素晴らしい世界で生きていると思うんですけど、我々のように、レガシー業界で遺産に向き合う必要があるところでは、「すべてがモダンにはならない過渡期」を、がんばってやっています。

まだクラウド電子カルテは2パーセント未満しか普及していないんですけど、がんばっています。とは言え、どうにかしないといけないので、モダンなテクノロジーとか設計手法とかを使って、少しずつ良くしているなと自負しています。

終わりです。ありがとうございます。

(会場拍手)