先日色々と思うことがあったので、Flutter Webで国立国会図書館の議事録検索APIを利用するアプリケーションを作ってみました。 アプリケーションはこちら。節度を守って遊んでね。
flutter-kokkai-gijiroku.web.app
コードはこちら。 MITライセンスで公開しています。
なお、利用した結果については、APIの規約をチェックしてください。 非商用利用であっても、出典を記載する必要があります。
アプリの特徴
概要としては、APIをリクエストするUIを組み立てているだけになります。 昨日までの日付(簡単に判定)を含んだリクエストの場合に、キャッシュ(簡単に作成)を持つ程度しか工夫していません。
国会図書館が提供しているアプリケーションと比較すると、
- より発言を検索しやすい
- 検索条件を共有しやすい(APIを共有しやすい)
- 何を入力できるのか、できないのか分かり易い
という点が優れているのかなと思います。 劣っている点でいえば、「この会議のアレを調べたい」という場合には向いていないかも、といったところです。
Flutter Web
SPAのフレームワークとして、Flutter Webを採用しました。 Reactと比べたとかではなく、最近使っているのがFlutter Webだったので採用しています。
また、Flutterのmasterチャンネルやriverpodのdevチャンネルを利用すると、知見が溜まって良さそうだなぁと、安定していないバージョンを採用しました。 要は慣れているツールで、より新しいものを触って遊びたい、ということです。
結果、副次的にMaterial Design 3を採用することができ、個人的に満足しています。 やっぱり、見た目が綺麗じゃないと、使っててモチベーション上がらないですよね。
検討していたこととしては、CanvasKitを有効にするかや、Webフォントを入れるかといったことがあります。 どちらもOffにする、つまりHTMLモードでデフォルトのフォントだけにすると、アプリサイズが1/4程度になります。 このため、美麗な印象をとるかスピードを取るかで悩みました。一旦「デスクトップモードなら、回線は高速だろう」でCanvasKitを有効にしていますが、どこかでHTMLに戻すかもしません。
Firebase Hosting
アプリケーションの公開には、Firebase Hostingを利用しました。 GitHub ActionsでGitのTagに反応してデリバリーする程度は、この後に整備しようかなと思っています。 そうすると、アップロードされているコードと公開されているページが一致しているのがわかりやすくなり、安心かなとも。
実装
riverpodとflutter_hooksを利用し、MVPで実装しています。 アプリケーションの性質的に、状態を管理しなければならない画面が少なくなります。 このため、設計方針はなんでも良さそうだったので、一番好みのものにしました。
開発していてつまったところとしては、 infinite_scroll_paginationとflutter_sticky_headerの組み合わせです。 infinite_scroll_paginationはCustomScrollViewを採用しているようで、実はしていないので組み合わせることができませんでした。 sticky_headersを採用すれば良いようなのですが、CustomScrollViewを利用したいので、時間のあるときにWidgetの作成にチャレンジしてみようと思っています。
色々と思ったこと
以下、今回の開発をした経緯や、思ったあれこれです。 思ったことの一部は、国立国会図書館へメール済みになります。
無関心であったことへの反省
検索用APIに仕様、読みにくくないでしょうか? というか、仕様書から読み取れない情報が多く、非常にダメな仕様書だと思います。
2点挙げるとすると closing
と updateTime
です。
closing
は、リクエストにおいては閉会中の会議のみを検索するか/のみの検索としないかを選択するクエリになります。
これは true
/ false
/ null
の3つのパターンがありこととなり、仕様書に明記されています。
では、このフラグはどのように返却されるでしょうか。
仕様書にはxml形式では <closing> 閉会中フラグ </closing>
、json形式では "closing": 閉会中フラグ ,
と書かれています。
そして、返却されるのは null
か 閉
です。
例えばですが、次のような指定でリクエストを送ると、閉会中の会議では 閉
が返却されることが想定通りであることがわかります。
なんだそれ。
以下は、とある検索結果の一部を抜き出したものです。
{ "speechID": "118915261X00120151111_000", "speechOrder": 0, "speaker": "会議録情報", "speakerYomi": null, "speakerGroup": null, "speakerPosition": null, "speakerRole": null, "speech": <略>, "startPage": 1, "createTime": "2019-09-05 05:23:55", "updateTime": "2019-09-05 14:54:51", "speechURL": "https://kokkai.ndl.go.jp/txt/118915261X00120151111/0" },
さて、このAPIは国立国会図書館のものであり、国会の議事録です。 しかし、だからと言って、Offsetをつけずに日付の返却を行うことは正しいのでしょうか?
仕様書には日付の形式も記述されていないため、もしかすると、意図せず解析中に日時がずれてしまうことがあり得ます。 少なくとも、仕様書に日付はJSTの表記である旨が記述されている必要があると、私は思います。
では、これらは単に「省庁のAPIはダメ」とクダを巻けば良い話なのでしょうか? 私は、我々がこういったAPIなどに無関心であったことをまず反省した上で、声を上げるべきなのではと考えています。
誰でもアクセスできることの重要性
今回の開発のきっかけは、友人が英国議会の検索APIについて困っていたことがきっかけでした。 そのときに見ていたページがこちらです。
少し調べてみると、次のようなドキュメントも公開されています。
では日本では、と調べてみると、PDFが公開されているようです。
https://cio.go.jp/sites/default/files/uploads/documents/1020_api_tecnical_guidebook.pdf
現在はデジタル庁に移行されているようですが、まだデジタル庁のサイトでは確認できていません。 *1
正直な話、あまりの差に言葉がありませんでした。 普段、日本のIT関連の遅れは、米国の先進的なIT企業と国内のIT企業との比較であったり、グローバルな組織とそうではない組織の文脈。 省庁との話であれば、国内の先進的なIT企業と、省庁との比較であるように思います。 しかし、今回の件で足元の中の足元であるAPI提供にここまで差があることに気付かされた、という感じです。
これは、当初はデジタル庁案件だろうなと「ここまで遅れてる〜」とツイートでもしようかなと。 ただ、それでは何も解決しません。 むしろ解決しないことが「当然」という風潮を作り、助長するように思えてきます。 APIを利用して、生の感想を取得し、フィードバックしなければこの状況は改善しません。
以上が、実のところのアプリケーション開発の理由です。 *2
「国会の議事録を検索できる」仕組みは、どう考えても、あらゆる意味で重要なものです。 しかし、その機能に予算や知見が割かれていない状態であること、そしてスポットライトが当たっていないことが、根本的な問題なのだと思います。
実際、アプリケーションを作って友人たち*3に遊んでもらったところ、下記のような検索をしてもらうことができました。 前者は「議事録に一回しか出てこない単語調べ」であり、後者は「面白い単語調べ」です。
https://flutter-kokkai-gijiroku.web.app/search/speech?any=ufo
これらは国会の議事録で"遊んで"いるわけですが、本質的なことを考えるのであれば、"遊べる"環境は必須なわけです。 議事録で遊べるような環境でなければ、それこそ小学生や中学生が議事録で遊べるような環境でなければ、議事録が広く一般に公開されている意味がないと私は思います。
そして、こういったものは1週間程度空き時間を確保すれば、作ることができるものです。 そういった遊びをしていないし、遊ぶことを考えていない怠惰さが、この問題の原点にあるのではないかと思います。
遊びでAPIを利用し、感想をフィードバックし、改善がされたら賞賛する。 そういったループを、もっと回さないといけないなと思っています。
今後
今回作ったアプリケーションは、ざっくりと作ったのでまだまだUI的に検討するところがあります。 このため、時間を見つけたら徐々に改善するつもりです。 FlutterのMaterial Design 3対応がされたら、Stableチャンネルに戻した方が良さそうにも思いますしネ。
時間があれば、APIを探してきて、利用してフィードバックしたいなと思います。 そういったことを繰り返し、日本のITの遅れが解消されればいいなと、心の底から思っています。