開発の現場では「手法よりも問題解決」が現実

開発の現場で、「手法」を議論する機会が減ってきているように思う。もちろん、自分の身の回りのことが全てではないので、偶然かもしれないが、ブログ等での話題でも、あまり見られなくなっている気がする。以前だと、例えばMVCがどうとか言った話題が華やかだった記憶がある。そして、古くからのさまざまな手法のどれがいいのかと言った話題や、特定の手法をどのように理解すればいいのかといったことが議論された。サイエンス的に考えれば、原理原則があり、それに則った手法は、成功する確率が高くなるということから、以前は手法やアーキテクチャ中心的な考え方もあっただろうし、もちろん、今もそれはなくなってはいない。

現実はどうだろうか? 色々な手法や原理原則は、1人1人がしっかり学習して現場適用するということも必要なことかもしれないが、「良い手法」はそのものが、すっかりパッケージ化されている。ソフトウェア開発で言えば、フレームワークやライブラリ、あるいは開発ツールで、そうした過去の蓄積が完全にパッケージされており、手法を深く理解しなくても開発を進める上ではあまり問題はない。ともかく、ある「やり方」を採用すれば、難しい原理原則はもちろん、手法の適用までができてしまうのである。Webのサーバーサイドフレームワークは典型的な例だろう。ほとんどのフレームワークはMVC(正確にはJavaEEでのMVC2パターン)であり、よほど変なことしない限りはMVCに基づく役割分担が自然に作り込まれるし、レイヤー化についても気がついたらそうなっているのが一般的だ。もちろん、実装の良し悪しはあるとしても、現場で働く側としては「○○フレームワークでよろしく」の一言で済んでしまう。

そうなると、現場でもっとも注目されるのは何だろうか? システム開発の現場と、サービスアプリケーションでは色々違うとしても、結果的に、「問題点は何か」ということに注目することが常に行われているのではないだろうか。開発の枠組みは使用フレームワークをはじめとして、結果的に決まってしまうことが多い。要求工学では手段は後から決めるというのが基本ではあるが、現実にはそうでもない。そして、そこではどんな手法を採用するかも概ね決まっている。スタッフが持つ経験をベースに、進行の可能性を検討し、誰かが問題なく進められる部分は、特にフォーカスされない結果となる。一方、誰も作ったことがない仕組み、誰も経験したことがフレームワーク、ある領域で実現できそうにない非機能要求など、「できるかどうか分からない」所に開発タスクとしては目を向けることになる。

では、できないことを、原理原則からボトムアップして、手法を求めるかと言うと、そう言う側面が問題解決に集中しているときはあるかもしれないが、その結果、あるライブラリを使うことで十分に解決されるなら、「ライブラリを使います」と言うことで集約され、問題がさらに絞られる。「チーム全員で手法をまずは勉強します」という結果はかなりハードルが高い。結果的に、問題から始めて、パッケージ化された解決手段で概ね解決し、さらに違う問題にたどり着き、それを繰り返す。問題がほぼなくなれば、一定時間後に完成に進めるということだ。

問題点の解決が現場での主要な話題になり、系統的な手法が議論される素地はほぼない。もちろん、結局のところアジャイルということなのかもしれないが、小さなプロセスでも、大きなプロセスでも同様に言えることではないだろうか。良い悪いはあるとしても、そのように進んでいる。その中で、基本や原理を叫んでも、誰も耳を傾けない。問題を解決する糸口は、まさに原理原則に立ち返ることで手にできるとも言えるのだが、「良い素材はないだろうか」が糸口になってしまうのである。

普段は小規模な開発に関わる機会が多いので、仕様書が渡されないような発注は普通にある。もちろん、大きな会社の発注では仕様書があるものの、非常に高い割合で「仕様書書いている」と言う証拠のためだけの紙の塊でしかないようなことも感じる。設計に役に立たないわけではないが、中身が実装作業に遠いのである。わかり切ったことは簡単に書き、問題点を記述して共有すれば、仕様書はより役に立つのではないだろうか? サイエンスなので、原理原則があって、それを踏まえた手法があるのは間違い無いのだが、いっそうのこと現実に合わせて「問題解決」にフォーカスした手法に目を向けるべきだと考える。とはいえ、そう言う「手法」を作っても意味はない。手法を否定する手法というのは存在に無理がある。その意味では、アジャイル宣言のように、どんなマインドで対峙すべきなのかをうまく表現しないといけないだろう。ということで、表題のように「手法よりも問題解決」と言ってみた次第だ。今やそういうやり方が一般的というスタンスで、メリットと注意点を検討すべきではないだろうか。

自動運転の実用化に違う方向性はないのだろうか?

次世代の自動運転技術に注目が集まっている。機械学習さらには人工知能の研究を強く牽引する期待が大きく、現実になればより安全な社会が実現するかもしれない。自動車業界は競争状態に入った自動運転技術を捨てるわけには行かないのかもしれないが、色々な業界がこぞって自動運転に目を向けている。一方で、新技術を危険視する向きもあり、自動運転で事故、あるいは死亡事故が発生すると、否定論が強まるなど、世論の関心も強く集めている。

技術そのものについて、「できない」と言ってしまうと、全く前に進めない。ところが「できる」とも言い切れないというのは、そこで「競争に負けた」と思われてしまうということもある。そして技術競争は熾烈になり、「あと何年で実用化」みたいな話はまことしやかに語られる。人工知能の世界でも、シンギュラリティという概念が既知のものであるのと同様、自動運転は近々実用化することになっているのが現在である。一方で、安全をどう確保するのかも大きな問題となっている。

自動運転の死亡事故をきっかけに一瞬、そうした議論が盛り上がったが、今回のアクシデントは偶発的なものと思いたい人たちと、ともかく「怖い」という漠然とした感覚から逃れられない人たちが大勢あることは改めて確認できたと思われる。事故が教訓になっていない漢字はちょっと怖いことでもある。どうすればいいという議論が進まないという点でもある意味怖い。この事故をきっかけに、何か安全性を高める方法はないだろうかと考えた。

自動運転の議論であまり出てこないと思うのが「社会インフラと連動した安全性の確保」だと以前より感じていた。現在、自動車をはじめとして色々な乗り物や人間が公道を安全に移動することができるには「信号」と言ったインフラがあるからだと考えられる。正確には、交通法規が根底にあるのだが、ともかく信号があるから安全でかつ、交通がスムーズに流れることは疑いの余地がない。自動運転にも、こうした社会インフラと連動したことができないだろうかと考えた結果、1つのアイデアが浮かんだ。それは、「舗装道路をスマート化」するということだ。

道路の舗装には、小石を含んだ砂利を利用していると思われるが、小石程度の大きさのIoTデバイスを開発し、一定の密度で舗装道路に含める。もちろん、様々なセンサーを持ち、結果は通行中のデバイスに送られる。熱に強いとか、すごく小さいとか、この『スマート砂利』には技術的な難しさは色々あるだろうが、自動運転よりはるかに容易だと想像できる。こうしたスマート砂利による舗装道路では、進路上に人間が歩いているなどのセンシングを、自動車の前の画像やセンサー等で見つける以上に正確にできることが期待できる。角を曲がった先の道路の状況が分かるかもしれない。

スマート砂利の道路は自動運転でより安全に走れるとしたら、自治体は極力スマート砂利を使った道路工事に切り替えるだろう。なんだか建築・土木系の利権を復活させるような雰囲気はちょっとげんなりするけども、自動運転について、自動車以外のことに目を向けてもいいのではないかとも思う。

JavaScriptの通信がPendingとなった理由は通信の問題ではなかった

JavaScriptとPHPで構築しているINTER-Mediatorで、分かりにくいバグに遭遇してしまったので、記録の意味も含めてここに書いておく。そもそも発端は、Ver.5.6-RC2を入れて動かしていたアプリケーションで、そろそろVer.5.7もリリース近いので、入れ替えるかと思って入れ替えたのが直接の原因なのだが、その瞬間にバグが顕在化したのならまだしも、ある程度時間が経過してから顕在化したので、根本的な原因を突き止めるのに非常に労力が消費されてしまった。

不具合が発生したのは、勤務先の業務システムで、スタッフ向けのページはかなり重たい動作のものある。全てのページで問題が出ないで、一部の「重たいと思われる」ページでのみで不具合が顕在化した。ここで、まず判断を狂わせることになる。システムは、サクラVPSで運用している。ここ数ヶ月、徐々にレスポンスが悪くなっている感じもあったので、プロバイダやネットワークをまずは疑ってしまった。不具合による結果は、ページを表示しようにもページ自体がフリーズしてしまうのである。ログインパネルはちゃんと出るが、正しいユーザ名とパスワードを入れると、フリーズする。これに気づいたのは2018年2月の上旬だ。

当然ながら、まずやることはデバッガでの確認だ。すると、以下のように、Statusが(Pending)となている。サーバーのログを追ったところ、Apache2はステータス200でデータを全部出し切っている。クライアント側で通信に入ったものの、一切のデータ受信ができない結果になっている。色々観察した結果、ページごとにPendingになるタイミングやこのページでの行番号は違うのもの、同一ページでは常に同じタイミングで発生した。ちなみに、Chromeだとこれが発生すると高い確率でそのタブを閉じることができず、他のタブは利用できる状態であるにも関わらず、Chromeの強制終了が必要になる。

今まで動いていたという気持ちがあると、当然ながら、アプリケーション側に問題はないとまずは考えてしまう。これも、後から考えれば間違いなのだが、エンジニアの皆さんはとりあえず人のせいにしてしまう気持ちはよく分かると思う。折しも、色々探すと、サクラのサポート情報で、「さくらのVPSで回線速度が遅くアクセスに時間がかかります。」というのがあった。ページのフリーズと、遅くなるのは違うのではあるが、こういう時には楽観的に物事を見てしまう。なんだ、原因分かっているんだと思いつつ、「さくらのVPSにおいて、不特定のVPS収容ホストとクライアント環境(プロバイダ等)の組み合わせにより、 さくらのVPSからのダウンロード方向の通信に遅延が発生する場合があります。」という記述をみて、ネットワークの問題があるということに意識がかなり振られてしまった。

当然ながら、ここにある対処をしたのだが、結果は同じだった。むしろ、どのページも遅くなったので、仮にうまくいっても恒常的な対処にはならない。しかしながら、「ネットワークに問題がある」というところで判断がスタックしてしまった。もし、ネットワークに問題があるとしたら、プロバイダを変えるか、職場のネットワーク内にサーバーを立てるしかない。GMOクラウドのVPSは無料で試せるので、ともかく移動して動かして見た。結果は同じだ。同じページで、同じようにフリーズする。GMOではネットワークの問題は解決しないとしたら、一度、自宅のサーバーにセットアップして、自宅内でアクセスするとどうなるかをチェックして見た。なんと、同じようにフリーズする。また、別の軽いページを改良している時にも、フリーズが発生した。つまり、「ネットワーク」「重いページ」はどうも原因ではないという結論になった。

しかし、なんでPendingになるのか?色々検索すると、Ajaxがデッドロックしたみたいな書き込みがあった。しかし、それへの回答でも、JavaScriptはユーザープログラムは絶対に並列的に動作しないで、処理を1つずつしかしないのだから、他の言語等で発生する問題が同じように発生する可能性は低いと書かれている。もっともだ。しかも、INTER-Mediatorのこのバージョンは、Ajaxを非同期では利用せず、同期通信しているため、フレームワーク内で複数の通信が発生することはない。なお、次のバージョンでは完全に非同期通信を行うようになる。

前述のChromeのデバッガを見ると、CSSの通信がPendingになっている唯一、並列的に通信が発生するとしたら、CSSのサーバーからの取得と、INTER-Mediatorのデータベースアクセスの通信が並列にはなりうる。ちなみに、CSS自体もサーバーで生成しているので、URLは.phpになっている。そこで、フレームワークをいじってCSSアクセスのlinkタグを突っ込まないようにして見た。それでも同じところでフリーズする。やはりこれも原因ではない。

ここで、根本的な原因が全くわからない状態になった。ネットワークでも通信でもないということで、フレームワークに問題があることはほぼ明白になった。そして、2017年9月のVer.5.6.1に戻して見たところ、問題なく動いた。これで、INTER-Mediator側に問題があることが確実となった。INTER-MediatorはGitHubのレポジトリにコードが残っている。そこで、どのコミットでバグが発生したかを突き止めることにした。大雑把に2分割をしながら、2018年1月のあるコミットであるところまで突き止めた。コードを見ても、明らかに通信ではない。通信に問題があるが、原因は通信でないということはさらに明白になった。

しかし、見当がつかない状態と、ここまで絞りきれても原因の特定まではできない。このコミットでファイルは4つ変更されているが、1つはメタデータで処理には関係ないので、そのうちの3つのどれかである。そこで、ファイルを1つずつ、前のコミットに戻すことで、INTER-Mediator-Calc.jsに問題があることが分かった。diffの結果はあれこれあるが、setUndefinedToAllValuesにメソッドしか変更していないので、問題はここにある。何れにしても、計算式の処理部分に問題があることが分かったのである。

ここで腹を括って、地道にステップ動作をさせて見たところ、ついに問題の根本が分かった。325〜335行のdoループが、ある条件の場合だけ、無限ループしている。つまり、ここのループ処理にバグがあったのだが、ポップアップメニューのタグ要素に計算式の結果を適用する場合だけ、無限ループし、その他のタグ要素の場合には無限ループにならず、間違えたコードだが正しい結果が得られているという状況になっていたのである。直したところ、えらく時間がかかるようになったので、処理を効率化して高速化する必要もあったものの、ともかく修正ができて、Pendingは出なくなった。原因追及から修正完了まで、1日かかってしまった。

結論は明らかだ。ページがフリーズしたら無限ループを疑えということになる。だが、なんで、こんな処理が入っているのかという点もあって、モデルをさらに改良してここで問題になったコードは取り除く予定ではあるものの、「動いている」つもりになっていたので、後回しになってしまっているのである。テストでクリアできないかということもあると思うが、ページ展開していないとテストのしようがない部分であり、単体テストではカバーできていなかった。現在、Seleniumベースでの統合テストを組み込んでいるところであり、そこで、計算式のテストページに、ポップアップメニューに計算式を仕込んだものも作っておいた。やはり、見つけにくいバグは、テストから漏れている箇所に存在するということだ。

なんとも当たり前なことの確認に、ひどく時間がかかってしまったのではあるが、自戒の意味も含めてブログに記録する。

2018年頭の近況報告

気がついたら全然記事を書いていませんでした。最後に書いたのは昨年の5月、ちょうどFileMaker 16がリリースされたのですが、新機能であるREAST APIのためのクラスを作るなど、そこそこコミットしたので、いくつか記事はありましたが、すっかりご無沙汰になりました。仕事を一生懸命していたのと、INTER-Mediatorの開発をがっつりやっていたのが理由です。

開発プロセスの話も、2017年2月で以降に記載がありません。かなり詳細化したのですが、詳細化し過ぎかもしれません。INTER-Mediatorでアプリケーションを作る話に持ち込みたかったのですが、むしろフレームワークを作る上での分析の方向に行ってしまった感があります。とは言え、報告はしませんでいたが、色々な角度での検討は断続的に続けていました。古い書籍ですが Object Modeling and User Interface Design あたりで、オブジェクト指向的にユーザーインタフェースを設計する方法があり、モデリングの方法として参考になるものでした。加えて、データベースをどう設計するかということも問題点としてはあるわけですが、こちらもオブジェクト指向の世界での解決策は2000年前後に一定の成果を出しており、久しぶりにそのあたりの書籍を調べて、10月にINTER-Mediatorの勉強会でワークショップをやってみたりしました。さらに、最近はプロジェクトマネジメントの世界でも注目されてきたアジャイルということもあり、現在の開発における問題点を解決に向かわせる手法として注目されており、そうしたことを全てひっくるめての「開発手法」に行きつきたいということもあって、次の方針を模索中だったりします。

2017年度から、大学の非常勤の仕事を多めに入れたのですが、初年度はやっぱり教材の仕込みが大変でした。NIIの仕事が2017年から週に3日になったので、開発の仕事は大きなことができなくなることが予想されたので、細切れな仕事が中心になりましたが、それでも、断続的には開発の仕事も続けました。ということで、余裕のない忙しさがずっと続いていたので、研究を進めるのがかなり困難でした。もっとも、研究員としてNIIで雇用されているのですが、実際の仕事はトップエスイーのシステムや運営関連のことなのでNIIの業務時間内で研究をする時間は全くありません。今年、2018年は、もう少し余裕を持って色々なことに当たれるようになりたいなとは思っていますが、今年はまあそういう状況に持ち込めない感じです。とは言え、INTER-Mediatorの方は、最優先で進めているので、進行は色々あると思います。今年もよろしくお願いします。

FileMaker Server 16のREST APIをmacOS上で試用する場合

FileMaker Server 16をまずは手元のMacにインストールして使ってみようという方も多いだろう。ここで、FileMaker Data API(REST API)を使用する場合にPHPのcurlライブラリを使うと、「SSL: CA certificate set, but certificate verification is disabled」というエラーメッセージが返ってくる。httpsでの通信が推奨され、証明書が検証できないと通信をしないということが当然となって来ているが、とはいえ、試用なので自己署名証明書で運用できないかとPHPの様々なパラメータを触ってみたところで、上記のエラーないしは別のエラーが出る。ということで、色々調べてみると、macOSに入っているopensslのバグで、サーバー検証をしないという設定ができないということらしい。homebrewから入れ直す方法など、色々紹介されているが、何をとっても大事になってしまう。

というところで、早速、FileMakerホスティングで有名なエミックの松尾さんが、ルータとなるスクリプトを公開された(一部、修正したい箇所があったので、筆者がフォークしたものもある)。FileMaker ServerのREST APIは、httpで接続してもhttpsにリダイレクトされるが、その背後のNode.jsが開いている3000ポートを目指して接続することで、httpでも処理が進められる。ただ、ヘッダをうまく使って同じホストからの接続しかできないような仕掛けがあるため、「直接3000番ポートに接続する」よりも、ルータスクリプトを使う方が楽である。

ルータは、WebアプリケーションとFileMaker Serverの中間に位置しており、WebアプリケーションがFileMaker ServerへのRESTコールを行う代わりに、ルーターに対して呼び出しを行う。ルーターはhttpsを使わずにFileMaker Serverを呼び出し結果を得て、それをWebアプリケーションに返す。動作としては「プロキシ」であるが、名前がrouterなので、ルーターと呼ぶことにする。

ルーターを利用できるようにするには、ダウンロードしたファイルrouter.phpを、以下のようなコマンドで起動する。ファイルがある場所をカレントディレクトリにして、コマンドを入力する。

php -S 127.0.0.1:8090 router.php

ここで、127.0.0.1は自分自身に接続するIPアドレスであり、コロンに続いてサーバーが利用するポート番号を指定する。他のプロセスが使っていない番号を使う必要がある。なお、使用を止めたい場合は、Terminalの画面でcontrol+Cキーを押す。

筆者が作ったAPIを利用するためのクラスFMDataAPIでルーターを利用したい場合、利用方法のサンプルを示したFMDataAPI_Sample.phpであれば、最初の方にあるインスタンス化している部分を記載のように修正する。パラメータを2つ追加して、8090ポートを使うことと、httpプロトコルを使うように設定すれば良い。他は変更が必要ない。もちろん、8090はルーターを起動する時に指定したポート番号を使う。IPアドレスも、基本的に起動時に設定したものを指定する。

修正前:
$fmdb = new FMDataAPI("TestDB", "web", "password", "127.0.0.1");

修正後:
$fmdb = new FMDataAPI("TestDB", "web", "password", "127.0.0.1", 8090, "http");

一方、FMDataAPITrialにあるスクリプトは、まず、lib.phpファイルにある以下の関数の返り値に、ルータ側のポート番号を指定する。

function targetHost()
{
    return "127.0.0.1:8090";
}

そして、Test2.php以降、プログラムの中のhttpsの記述をhttpに切り替える。callAPI関数の最初の引数が全てhttpsになっているので、httpに書き換える。

$host = targetHost();
$result = callAPI(
    "http://{$host}/fmi/rest/api/auth/TestDB",
    null,
    json_encode(array(
        "user" => "web",
        "password" => "password",
        "layout" => "person_layout",
    )),
    "POST");
resultOutput($result);

なお、phpコマンドで、router.phpを起動する時、127.0.0.1ではなく、localhostで指定した場合、上記の修正箇所のIPアドレスは、全てlocalhostで記述する。127.0.0.1では稼働しないので注意する必要がある。phpコマンドで起動する時に127.0.0.1を指定すると、Webアプリケーション側の設定は、127.0.0.1でもlocalhostでもどちらでも良いようだ。FileMaker Serverはかなり以前からIPv6ベースで動いているのだが、localhostとした場合、どこかで127.0.0.1ではないIPv6のアドレスとして識別しているのではないかと想像できるのだが、詳細は分からない。

ちなみに、FMDataAPIを使ったシステムを運用する時、原則としては正しい証明書でhttpsで運用することが原則だ。もちろん、盗聴されないためというのが大きな理由であるが、ホストを偽ってデータを収集されたり嘘の情報を流されることも防ぐ必要がある。httpsでの運用は、Let’s Encryptで無償で利用できるなど、年々手軽になってきているので、面倒がらずに対応すべきだというのが1つの結論である。

では、PHPを稼働させるWebサーバーとFileMaker Serverが同一のホストであれば、盗聴の心配はないのではないかと言うことになる。Firewallでポートを塞げば、それでいいのではないかと言う話もなくはない。ただ、FileMaker Data APIだけにWebサーバーを使うと言うことはあまりないと思われるので、Firewallの設定はちょっと面倒ではないだろうか。絶対に外部からFileMaker Data APIは利用しないで、サーバー内部に限るのであれば、httpでの運用でも問題はないかもしれないが、必ずサーバーの内部からの利用しかしないと言うことを管理者が人手で保証しないといけなくなる。通常、httpsで運用する手順を踏む方が楽なのではないだろうか。

自己署名証明書の問題も同様だ。サーバー内部に限るのなら、詐称のしようもないと考えることができる。これも、「絶対にサーバーの内部からの利用しかしないと言うことを管理者が人手で保証する」と言うモデルであり、むしろ、そういった人的な縛りよりもhttpsでの運用をする方が問題が発生しにく状況であると言えなくないだろうか?

そう言うことで、httpや自己署名証明書での運用は自己責任が大きいので、FileMaker Data APIでアプリケーションを開発したら、本番はhttpsでの運用を目指すようにすべきである。

なお、筆者の作ったFMDataAPIクラスは、デフォルトは証明書の検証をしない状態で稼働するので、そちらは開発中での利用を想定している。実際に正しい証明書が用意できれば、以下のメソッドを呼び出す。そうすれば、証明書の検証を行うようになる。自己署名でないこと、期限、アクセスしているサーバ名と同一なのかが検証される。

$fm->setCertValidating(true);

すなわち、FMDataAPIクラスは、証明書の検証もメソッドでコントロールできるようになっている。

FileMakerデータベースをOAuth認証で利用する

一部に間違いがあり、修正しました。修正箇所は青字で記載してあります。(2017-06-17)

FileMaker 16の大きな機能アップの1つは、OAuth対応だ。GoogleのアカウントでFieMakerデータベースへのログイン認証ができるようになったのである。OAuthの大きな特徴は、1度パスワードを入れれば、その後に認証されたことが異なるサービスに対しても継続されることである。これは「パスワードを覚えていて、その都度送り出す」のではなく、認証した事実を別のサーバーにうまく伝達を行うことで、サービスをまたいだ認証の継続を実現している。パスワードのやりとりは最初のログイン時だけになるので、概してより安全な認証方法と言うべきだろう。FileMakerがOAuthにどのように対応したのかを、データベースログインをGoogleアカウントでログインできるようにするための設定を通じて説明する。

FileMakerデータベースへのログイン

FileMakerデータベースをFileMaker Serverで公開したとする。以下はINTER-MediatorのサンプルデータベースをプライベートネットワークにあるFileMaker Server 16で公開した結果を示す。上記のサンプルで改変した点は本文途中で示す。

公開したデータベースをFileMaker Pro/Advancedで開こうとすると、次のようなダイアログボックスが表示され、そして、アカウント名とパスワードを入力して、「サインイン」ボタンをクリックする。

ここで、FileMaker Server 16で、Googleを認証サーバーとして利用するような設定を行い、加えてデータベース側にそのGoogleのアカウントを追加設定すると、サインインのダイアログボックスがでは以下のように、「Google」のボタンが下部に追加される。このダイアログボックスが表示された時には、「Google」ボタンをクリックするだけでOKである。アカウント名やパスワードのテキストフィールドに、Googleのユーザー名やパスワードを入力することは不要である。

そうすると、デフォルトのブラウザが開き、Googleアカウントのログインの「アカウントの選択」の画面になる。ちなみに筆者が複数のGoogleアカウントでログインをしているのでアカウントの選択になるのだが、アカウントが単独の場合には何も出ないかもしれない。あるいはまだログインをしていないのなら、さらにパスワードの入力や場合によってはアカウントの入力も必要だろう。何れにしても、サインインのダイアログボックスで「Google」ボタンをクリックすると、Webブラウザを利用してGoogleでの認証結果を確認する。その時に、Googleのアカウントでログインしていなければログインをするが、ログインして入ればそのまま処理が継続される。

ログインが成功するか、ログインされて入れば、次の図のようなダイアログボックスが表示される。これは認証が成功したことを示しており、データベースを利用するには「FileMaker Pro Advancedを開く」(もちろん、Proの場合もある)ボタンをクリックする。なお、「開かない」にしたら、何もしないので、ここでは必ず「〜を開く」ボタンをクリックする必要がある。

そうすれば、データベースが開かれる。この時、Get(アカウント名)等の取得関数の結果もデータビューアで示したが、ログインしているGoogleアカウントのアカウント名がそのまま見えている。

以上のように全てがうまく設定された状態だと、ログインパネルで、Googleボタンをクリックすることで、パスワードをその場では入力することなく、自動的にデータベースを開き、データベースではGoogleアカウントで誰が使っているのかを識別できる状態になる。あらかじめGoogleアカウントでログインしていれば、何も追加作業は必要ないか、あるいはアカウントの選択の作業が必要になる。 ログインしていなければ、Webブラウザでログイン作業を行う。

OAuthで利用するためのデータベース

FileMakerのデータベースは、ProないしはAdvancedで管理者でログインをして、「ファイル」メニューの「管理」にある「セキュリティ」を選択する。認証を行なったのちに、アカウントの追加をまずは行う。「アカウントの認証方法」の部分には、「Amazon」「Google」「Microsoft Asure AD」の3つの選択肢が増えている。利用するOAuthサービスを選択した上で、ユーザー名は、そのサービスのユーザー名をそのまま指定する。このように、Googleであれば、Googleのユーザー名を指定したアカウントを作っておかなければならない。もし、作っていない場合は、たとえGoogle側のログインが成功していてもデータベースの利用はできなくなっている。一見すると、他のこの種のサービスのように自由にログインできないのは不便と思われるかもしれないが、登録しないと利用できないようにするのがセキュリティ確保の基本である。誰でもログインできる状態というのは、多くのFileMakerデータベースには望まれていない。

アカウントが実際に利用できるようになるには、「アクセス権セット」を選択する必要がある。ここでは既定の「データ入力のみ」を選択しているが、もちろん、このアクセス権セットに、fmappつまり「FileMakerネットワークによるデータベースアクセス」の拡張アクセス権が設定されている必要がある。これは従来からと同様で、FileMaker Serverで公開するデータベースでは必須の設定である。なお、INTER-Mediatorのサンプルデータベースでは、「データ入力のみ」のアクセス権セットには、fmappはチェックが入っていないので、サンプルをそのまま使う場合には注意していただきたい。

アカウントの一覧には、Googleがタイプの項目が増えており、アカウントの列ではGoogleのユーザー名がそのまま見えている。

FileMaker Serverでの設定

FileMakerのAdmin Consoleで作業をする。ログイン後、左側で「データベースサーバー」を選択し、右側で「セキュリティ」のタブを選択する。そこにあるポップアップメニューで「FileMakerと外部サーバーアカウント」を選択する。すると、Amazon、Google、Microsoftの3つの項目が表示されるので、右側のギアのアイコンをクリックして、作業を進める。ここでは、Googleを例にとって説明する。

Googleのギアアイコンをクリックすると、次のようなパネルが表示される。結果的には、ここでGoogle側で得られた2つのコードを入力することになるが、それは、この後に説明する。簡単なようで難しい問題もあるので、それも併せてこの後に説明する。ともかく、2つのコードが得られたら、「保存」ボタンをクリックする。

ちなみに、Microsoftを選択すると、少し違うダイアログボックスが表示される。これらはサービスごとに得られるデータが少しずつ違うと言うことだ。なお、これら3つ以外のサービスはプラグインとして追加は可能となっているが、基本的にはメジャーなサービスの場合はFileMaker社による機能追加を待つことになるだろう。自社でOAuthサーバーを立てているなら、プラグインの開発をしたくなるところだろうが、こちらはFileMaker社による情報待ちの状態だ。

設定終了後、次のようなメッセージがでかでかと表示される。つまり、FileMaker Serverのサービスを再起動すると言うことだ。もちろん、コンピューター自体を再起動してもいいが、macOS、Windowsでの作業方法が、こちらのページに記載されている。

Googleのコードの取得

Admin Consoleで設定をするには、Google側から与えられるコードを取得しなければならない。そのコードは、Google APIのところで取得を行う。以下の手順で「利用規約の更新」が出てくる場合には、もちろん、そこで対応をして進める。

Googleの場合、Admin Consoleの「データベース」のセキュリティ設定のところで出てきた「Google API Console」をクリックすると、以下のような英語のOAuth 2.0のページが出てくる。実際作業は、このページの本文の2パラグラフ目にある「Google API Console」をクリックして進める。

Google API Consoleをクリックすると、以下のページに移動する。こちらを直接開くには、Google Developer Consoleのページにジャンプすれば良い。なお、このページ内容は、それまでにこの機能を使ったかどうかによって大きく違っている。全く初めて使う場合の作業手順も併せて説明しよう。ポイントは、上部に「Google APIs」というバーが出ている点である。

Google APIsと書かれた右側の部分では、初めて使う場合には「プロジェクトを選択」と表示されるので、それをクリックする。すでに何かで利用してプロジェクトが存在する場合には、とにかくプロジェクト名が見えているのでそれをクリックする。すると、以下のように、プロジェクトの一覧パネルが表示される。パネル右上の「+」をクリックすると、プロジェクトが新たに作成される。ここで、FileMaker Server向けにプロジェクトを1つ作っておく。

プロジェクトの作成時に必要なことは、プロジェクトの名前を設定することである。名前は適当に設定する。なお、プロジェクトIDはこの後は特には使用しない。

プロジェクトを作成すると、そのプロジェクト名がGoogle APIsの右に見えていることを確認して、左側で「認証情報」を選択する。すると、「認証情報を作成」というボタンが見える。ここで、ボタンをクリックして「OAuthクライアントID」という項目を選択する。

なお、ここで以下のようにメッセージが見えているGoogleアカウントでは、必要なコードを生成する権限が与えられていない。例えば、組織で作成されたアカウントではコード生成が許可されていない場合があるので、その場合は個人でアカウントをするなどして、コード発行を行う必要がある。組織のアカウントの場合は、その組織の管理者が、クライアントIDの発行を制限していることが一般的な原因だろう。

 「OAuthクライアントID」を選択した後、同意画面の作成を促す表示が出てくれば、それに従って以下のページで必要な情報を入力する。本来はこの「同意画面」がユーザーに示されて、そしてサービスを利用できるようにするという流れをOAuthでは採用している。しかしながら、FileMakerではこの同意画面を利用していないようで、「ユーザーに表示するサービス名」だけを設定して「保存」ボタンで保存すれば良い。

その後にアプリケーションの種類を選択するページが表示される。ここでは、「ウェブアプリケーション」を選択する。すると、名前などを入力する項目が表示される。ここで、名前は適当に設定するとして、もう1つは「承認済みのリダイレクトURI」を入力しなければならない。このURLは、例えば、FileMaker Serverに接続するためのホスト名が「fmstest.msyk.net」ならば、「https://fmstest.msyk.net/oauth/redirect」を指定する。ホスト名の部分だけがサーバーによって違い、他の部分はどのサーバーでも同様だ。なお、:443はあってもなくても良い。ちなみに、ここにmacOSの共有名(Macintosh.local)や、IPアドレスではうまく動作しない。ドメインを含む利用可能なホスト名をきちんと設定し、そのホスト名でサーバーに接続できる環境になっていなければならない。

「作成」ボタンをクリックすると、生成されたコードがパネルに表示される。こちらからコピーして、Admin Consoleの該当するフィールドにペーストすれば良い。なお、コードは後からでも参照は可能である。

うまくいかない場合の対処

手順は以上の通りだが、FileMakerのドキュメントにも書いてある通り、FileMaker Serverを、きちんとしたドメイン名のURLのホストで公開する必要がある。macOSの共有名の場合、ブラウザからのアクセスが正しくできない場合もある。IPアドレスだけではhttpsでアクセスしているはずはないので、Googleの側で登録が進まない。自分でドメインを持っている方は、何らかのテスト項目を作るなどしてともかくドメイン名を含むホスト名を用意する。

例えば、サインインのダイアログボックスで、Googleボタンをクリックした場合に次のようなページが出たとする。ここで詳細を表示すると、redirect_uriに見えるように、https://MacBookPro.localというホストにアクセスしようとしている。もちろん、この名前は共有名である。ブラウザでは共有名でもOKのはずなのにと思うかもしれないが、単にそのURLにブラウザからアクセスするのではなく、裏ではもっと色々複雑なことを行なっている。筆者の場合には、msyk.netというドメインを所有しているので、fmstest.msyk.netが利用できるようして、検証を行なった。IPアドレスは、実は10.0.1.102というプライベートアドレスだが、自宅環境ではそれで運用可能なので問題はない。

ここで、上記のrequest_uriのURIがどのように自動生成されるのか分からず、対処がなかなかできなかった。実際には、FileMaker Pro/Advancedがrequest_uriを「サーバーへ接続した時に使うホスト名」から生成しているようだ。macOSの場合、自動的にBonjour名が左側に出てきてアクセスをしがちであるが、それだと、上記のrequest_uriには共有名が含まれてしまう。サーバーのドメイン名(つまりFQDN)で接続するサーバーを選択できるように、例えば、お気に入りのホストにドメイン名を登録して、そこからデータベースを選択して開くようにすれば良い。以下の図のように、fmstest.msyk.netでデータベース選択ができるように、お気に入りのホストの登録を行なった。もちろん、自動的に識別される名前がホスト名であれば、それを選択すればOKである。

OAuth対応をどう考えるか

以上のように、Google側の使いこなしが必要になるものの、OAuth対応は確かに便利だろう。アカウントそのものの管理を外部に任せることができるのである。ただし、社員全員がGoogle Appsなどでアカウントを持っていれば便利は便利なのだが、データベース個別にそれぞれのアカウントを登録しなければならない。これは、テキストファイルで読み込みはできないため、自動化のスクリプトなどを使用することになると思われる。ともかく、Googleにアカウントを作ればデータベース側を変更しなくても新しいアカウントから使えるようになる…と言う状況は作れない。機能としては素晴らしいが、運用を考えた時に、手間になる部分も見えてくる。ログインしたアカウントのドメイン名がある名前であれば、自動的に登録されて定義されたアクセス権セットを利用するような仕組みがあることで、管理負荷を軽減できると考えられる。

FileMaker Data APIもOAuth対応している。その意味ではWeb対応しているのだが、WebDirect経由ではOAuth対応はなされていないこれは先のバージョンを待つしかないだろう。WebDirectについては当初は対応していないと記載していたが、GOからのアクセスも含めて対応はしている。エミックの松尾さんに指摘をいただいたが、恐らく正しい証明書であればHTTPSであればOAuth認証ができ、自己署名の証明書であればできないということではないかと思われる。なお、http://…だと、Googleで登録ができなかった。この件、簡単に検証ができないのではあるが、手元で検証した時の違いとなると署名書の違いしか考えられない。

FileMaker Data APIを使えるようにする

FileMaker Server 16に搭載されたFileMaker Data APIについて、実際に利用できるようになるまでの手順を紹介しよう。FileMakerでのWeb開発やFileMaker Data APIの意義については、「FileMaker 16より搭載のFileMaker Data APIとは」を参照していただきたい。

FileMaker ServerのインストールとAdmin Console

FileMaker Data APIの有無に関わらず、FileMaker Serverをインストーラを使って通常通りインストールを行う。展開アシスタントの「Web公開」のところで「FileMaker Data API」のチェックを入れる必要がある。このチェックに相当する機能は、アシスタント利用後でも設定できるが、使用することが分かっているのなら、インストール時にセットするのが手軽だろう。

FileMaker Serverのセットアップ後、「ステータス」のページでは、「FileMaker Data API」の状態を表示する領域が見えており、機能が動作しているかどうや接続数が参照できるようになっている。ここでは詳細な設定はない。

細かい設定は左側で「Web公開」を選択し、上部のタブで「FileMaker Data API」を選択することで表示できる。こちらでは、機能の有効/無効とログについての設定が可能である。

左側で「ログビューア」を選択してログを見るとき、「ログ」ボタンをクリックしてログの選択する箇所で「FileMaker Data API」についてのチェックボックスが表示される。こちらをオンにするとログを参照でき、アクセスするごとに1項目ずつ追加され、日時やURLのパス、クライアントIP、エラーの様子などが記録されていることが確認できる。

FileMaker Data APIに応答するデータベース

データベース自体にも、FileMaker Data APIの利用の可否を指定する部分がある。XML共有やFileMaker Serverへの接続等でも指定した「拡張アクセス権」の設定が必要である。FileMaker 16では、「fmrest」というキーワードのFileMaker Data APIを利用する拡張アクセス権が存在している。データベースを開いて、「ファイル」メニューの「管理」から「セキュリティ」を選択して表示されるダイアログボックスで「拡張アクセス権」のタブをクリックして確認できる。

データベースに設定されたアカウント、あるいは外部のアカウントは、「アクセス権セット」のいずれかの項目に結びつけられる。そのアクセス権セットの設定で、fmrestにチェックが入っている必要がある。このアクセス権セットを選択しているアカウントが、FileMaker Data APIを利用できる。

FileMaker Data APIのマニュアル

FileMaker Serverをインストールしたホストの16001番ポートを開くと、「FileMaker Server 16 開始ページ」が開く。そのページの「Web公開リソース」にある「FileMaker Data API マニュアル」をクリックすると、マニュアルが参照できる。このマニュアルはまだ日本語版は存在していない。日本語のマニュアルは同じ開始ページの「FileMaker 16 Data API ガイド」を辿れば参照できる。

例えば、FileMaker Data API マニュアルにあるREST APIの記述を見てみよう。

REST APIは、簡単に言えば、Webブラウザのアドレスバーに入れるようなURLをサーバーに遅れば結果が返ってくる仕組みだ。ならばSafariやChromeでちょっと試そうかと思うかもしれないが、原則、返って難しい。ちなみに、こうしたREST APIを試す開発ツールとして「PAW」などがすでにあり、APIの利用が成熟していることの現れであるとも言える。

このGet RecordはrecordIdを与えてデータベースの1レコードを得るものである。/fmi/rest…という部分はURLのパスとして与えるものである。その中の「:solution」はデータベース名に置き換えるが、:は含めない。ちなみに、このコロンはNode.jsでのプログラミング経験者にとっては見覚えがある表記だろう。例えば、TestDB.fmp12のpostalcodeレイアウトにあるrecordIdが25のレコードを得るには、FileMaker Serverと同じホスト上でAPIにアクセスするとしたら、

https://localhost/fmi/rest/api/record/TestDB/layout/25

というURLにアクセスする。ここで、パスの上に緑のボックスで「GET」と書いてあり、通常のWebブラウザでのアドレス手入力と同じくGETメソッドでアクセスすれば良いということになる。他にPOSTだけでなく、PUTやDELETEメソッドも使うAPIもある。POSTやPUTではURL以外にリクエストのボディ部にどんなJSONデータを指定するのかが記載されている。

Headerの項目を見て欲しいが、ここの記述は、リクエストのヘッダに、

FM-Data-token: XXXXXXXXXXXXXXX

といった形式のデータを追加しないといけない。従って、WebブラウザでURLを入れれば済むと言う話ではなくなるわけだ。このヘッダの値は、事前に呼び出したLogin APIの結果を入れる。こうした点は詳細には書かれてはいないが、APIドキュメント全体を読むとそうした事実もわかる。

ページの下の方には、どんなデータが返されるのかが記載されているが、「Success-Response:」をクリックすると、ある程度具体的なデータ例が記述されている。「Success 200」はHTTPのステータスコードが200、つまり通信が成功した時のJSONの応答に含まれているデータのキーと値についての説明となっている。なお、ちらっとOptional query parameterに書かれてあることは、解釈は決して簡単ではないが、レイアウトに含まれるポータル内にあるデータを制限する方法が記述されている。具体的には「Example query with portal」のところに書かれている「?porta=」の部分をURLに繋いで指定するのだが、これも1回読んで理解するのはほとんど無理かもしれない。

FileMaker Data APIを実際に使ってみる

ちなみに上記URLはhttpsとしたが、httpとしたらどうなるだろうか? サーバーはhttpsのURLへリダイレクトする応答を返す。つまり、httpでは処理をしないのである。リダイレクトにどう対処するかよりも、httpsと最初から指定すれば良い。

httpsで運用することになると、サーバ証明書の問題が発生する。通常は、既定値で自己署名の証明書がインストールされているが、最近は通信時に自己署名ではエラーになる場合もあり、適切なパラメータを指定しないといけなくなることもある。もちろん、本番の運用は、自己署名ではなく、正しい証明書を利用することが前提である。

/fmi/restの処理をFileMaker ServerのApacheの設定で追ったところ、Node.jsのサーバーにたどり着いた。つまり、デフォルトの3000番ポートが全てのネットワークポートに対して開かれていることから、別途、Node.jsのプログラムを動かす場合には注意が必要になる。FileMaker 16 Data API ガイドによると、8989ポートも開かれているようだが、こちらはlocalhostに対してのみ開かれている。ちなみに、Node.js内でどのようにしてFileMakerデータベースへアクセスしているかと言えば、Javaのプログラムをリモートコールするようなクラスを利用している。つまり、Node.jsの先は公開されていないJavaのAPIを利用している模様だ。この辺りも解析すると何かわかるかもしれないが、ざっと見た範囲では、FileMaker Data APIの範囲を超える仕組みを組み込むことは期待できない感じであった。

これらのAPIを解説してもいいのだが、アプリケーションの利用を考えた時、毎度URLを組み立ててリクエストとレスポンスするのはちょっと効率が悪い。すでに別の記事で紹介したように、PHPで使えるクラス「FMDataAPI」を開発しておりPHPでFileMaker Data APIを使用したいなら、このクラスを使うことが早道である。なお、他の言語でも同様により容易に利用できるライブラリの登場が待望される。引続く記事では、FMDataAPIを使いながら、得られるデータの活用方法などを解説しよう。

FileMaker Server 16より搭載のFileMaker Data APIとは?

FileMaker Data APIは、データベースへの読み書きの処理を、Web APIあるいはREST形式のAPIで利用できるものである。FileMakerデータベースを他のシステムと統合したり、Webアプリケーションのバックエンドとして使う場合には様々なフレームワークや言語と組み合わせ利用しやすい形態がREST APIと言える。FileMakerのREST APIについては、すでにアナウンスされていたとは言うものの、FileMaker Data APIがFileMaker Server 16で初めて製品としてリリースされ、利用できるようになった。本来はFileMaker Cloudに搭載されるものと思われていたが、Ver.16が先になったので、次のCloudのリリースには確実に搭載されるのだろう。REST APIはすでにサードパーティ製品はあるものの、FileMaker本体に搭載されたことは今後の製品を予測する上でも大きな出来事と考える。

FileMakerデータベースのWeb利用

FileMaker Pro/GOをクライアントとして利用するソリューションのバックエンドとして、FileMaker Serverを利用し、データの共有をスムーズにできるようにすると言うのがFileMakerのもっともメジャーな利用形態だ。一方、Webの発展が著しいのは言うまでもないが、FileMaker Serverに蓄積したデータをWebつまりWebブラウザーをクライアントとして利用できるようにするニーズもある。

FileMakerは20年近く前からWeb利用に取り組んでいる。初期のHTML拡張によるCDMLによるデータベース連動ページ作成はVer.4で搭載され、当初はかなり期待されたものの、簡単なソリューションで更新処理が複雑でない程度のものでないとかえって開発が難しく、Ver.7の時点で廃止された。Ver.7からしばらくはXSLTをベースにしたWebページ開発ができたが、こちらもVer.11までの搭載となり廃止された。標準技術をベースにしているとは言うものの、他のWeb開発とあまりに手法が違いすぎた。一方、Ver.5より搭載された初期のXML共有は現在ではCustom Web Publishing(CWP)として若干の機能更新はあるものの、現在のFileMaker Serverまで継続している。その後、PHPのクラスライブラリとして提供されたFileMaker PHP APIやそのバックエンドとしてのXML共有の拡張を経て、これらの機能は現在も利用できる。これに加えて、FileMaker Data APIが登場したのである。データの蓄積や取り出しだけを担うサーバー機能としては以上のような経緯があるものの、FileMaker Server 16では、CWPとFileMaker Data APIと言う過去からの全ての仕組みが搭載されていることになる。CloudではCWPは搭載されず、FileMaker Data APIのみとなっている。

FileMaker Pro/Advancedで作ったレイアウトをそのままWebブラウザーで表示するといった仕組みのWeb対応もなされてきた。Instant Web Publishing(IWP)は若干の改良はされてきたもののVer.12で終了となり、Ver.13以降はWebDirectとして、完成度を高めてきており、Ver.15では動きもスムーズになり、システム開発の1つの手法として実運用可能な状況になっている。ただし、Ver.13でGOからの接続がコネクション数に応じたライセンス体系を取るようになると同時に、WebDirectもライセンスが必要となった。従来のIWPは任意の接続は可能であったが、パフォーマンスの問題で数十程度のクライアントの同時接続までとなっていた。

Webアプリケーションに繋がる手法としては、Ver.15では接続数に応じたライセンスが必要となるWebDirectと、サーバーのパフォーマンス次第で接続ライセンスの不要なCWPの両方が組み込まれている。FileMakerのレイアウトがそのままWebブラウザで見えて利用できるのがメリットかデメリットかは簡単には結論は出せない。ソリューションの設計と運用によるものである。HTMLでWebクライアントを構築したい向きにはCWPが必要になるが、一方でライセンス費用を気にしなくてもいいといったコストに偏った見方をされている場合もある。

ライセンス体系は今後どうなるのか?

FileMakerはVer.13以降、接続クライアントに応じたライセンスということを重視した製品系列へとシフトしてきており、FLTというライセンス体系の追加や、IWPの廃止やGOの接続ライセンス必須化を含めて、CWPのような自由な接続という仕組みを排除してきている。加えて、年間ライセンスへとユーザーをシフトさせようとしている。

そうなると、1つの重要な命題は「CWPがいつまで使えるのか」ということに集約できる。現行のライセンスモデルにマッチしない手法だけに、いつ、機能としてなくなっても不思議ではないのである。しかしながら、それに替わる仕組みがなくなることで、システム構築の自由度がそがれることは明白である。CWPに替わるものが、Ver.16で搭載されたFileMaker Data APIとなるが、「トライアル」ということで、今後の展開を見てライセンス形態を決めようとしている意図が見えてくる。正式にリリースされたことで、まだアナウンスはないもののCWPの継続が中止される可能性はゼロではなく、結果的にどのバージョンまで使えるかという問題に帰着する。そして、FileMaker Data APIに関して、どういったライセンス体系への統合を、どのバージョンで行うかということに注目することになる。Ver.16現在、FileMaker Data APIは自由にアクセスできる状態であるが、FileMakerの製品ライセンス体系を考えれば、「いつかはお金を取る」という姿勢は容易に感じとれるのである。

モダンなデータベース利用が可能なFileMaker Data API

ちなみに、なぜ、CWPがFileMaker Data API置き換わると予想されるのかについてだが、総じてFileMaker Data APIの方がモダンであると言えるからである。サーバーにリクエストを送って結果を得るのは昔からあるXML共有でも現在のFileMaker Data APIでも同じであるが、XML共有はURLに対してXMLで結果が返るのに対して、FileMaker Data APIではHTTPのメソッドを伴うきちんと定義されたAPI動作に対してJSONで結果を返す。データの内容的には、ポータルか、別のTOのフィールドなのかを判別するという点では、XML共有は確実にできなかったこともあった。その後の改良でできるようにもなったが、パフォーマンスが悪くなった。

HTTPのメソッドとURLの組み合わせで動作を記述し、JSONで得られるFileMaker Data APIの方が、様々な用途に展開しやすいことも事実だ。機能的には、レイアウト情報まで取得できるCWPの方が勝るものの、FileMaker Data APIは必要最小限の機能になっており、むしろデータ処理に特化されてシンプルに使えることも、学習しやすい点もあり、実運用に即した進化であると言える。

筆者が現在、開発を進めているWebアプリケションフレームワークのINTER-Mediatorも、もちろん、FileMaker Data APIへの対応を行う予定である。CWPがなくなることを見越しての対応である。そこで基礎部分の足固めとして、PHPで使えるクラス「FMDataAPI」を開発し、こちらは単独でMITライセンスのオープンソースソフトウェアとしてGitHubで公開した。こちらの開発で得られた知見を元に、しばらくはFileMaker Data APIについての情報を本ブログで提供することにする。

[開発プロセス#13] アプリケーション全体を改めて記述する(2)

前回の続きである。前回はユーザーインタフェース要素、つまり、HTMLで記述できる要素は、仮想的に変数とバインドされているという仕組みの考えた上で、ユーザーインタフェース要素と、処理の記述の分離ができていることを説明した。その時の図を利用して、続きを説明しよう。

ここで処理は、分類1から5までに分けて記述をした。このうち、分類3と4がサーバーで他はクライアント側の処理として実装するのが効率良いと考えたとする。「分類2」は、最初に検索フォームを表示する仕組みを記述しているので、特にギミックがないのであればスタティックなHTMLを表示するだけになる。この図では、HTMLの表示には、その要素のHTML記述をテンプレートとして、それを元に画面を構成して表示するという記述で統一することにする。

「分類1」は、フォームに入力された検索条件を元に検索を行い、その結果を画面に表示するまでの、残りの分類を全て通ることになる。分類1については、以前に考えた基準に従って、「やるべき処理」をボックスにして記述をしたが、ここでまず、違和感が出てくる。やはり、ここでは、ボックス間の矢印は「次の処理」を示すことになり、ボックスによって矢印による処理の段取りが変わってくる。であれば、同じ矢印で示すのはどうかと考える。このボックスと矢印の記述の意味を検討して改良することは次のステップで進めることにする。

「入力内容検証」となっているが、設計であるのなら、どのような検証を行うのかを記述すべきであることは明白である。ここでは、OCL等を利用した記述を行うのが順当と考える。

入力に問題がなければ、その値を持ってサーバーからデータを取りに行く。ここで、分類1から分類4にかけては、要するにサーバに対してHTTPのリクエストをPOSTメソッドで行うというごく一般的なCGIの仕組みを利用することになる。「サーバーへPOSTメソッド」から「POST受け入れ」までの処理は、時代によって記述方法が違っていた。古くから行われているのは、FORMタグ要素のSUBMITボタンを利用することで、POSTメソッドをサーバーに投げるということだ。そして、PHPを利用していれば、「POST受け入れ」は自動的に処理されて、分類4は言語要素というか、Apache等のWebサーバーとの連携の中で処理がなされて、POSTメソッドに含まれるパラメータが変数に設定されて、プログラムのファイルの1行目からが実行されるということになっていた。分類5については、PHPを使うのであれば、echoコマンド等で出力した結果をバッファに蓄え、クライアントに送り返す。ここはリクエスト-レスポンスの関係を分離4の部分が担う。その意味では、分類4の部分は、よほどのことがない限り、自分で作ることはないと言えるだろう。分類3がサーバーサイドでの処理の部分である。

なお、FORMタグを使って検索条件を送り込み、その結果を表示するとしたら、分類5の「検索結果表画面生成」はサーバー側の処理となる。それをブラウザはそのまま表示すればいいからだ。しかしここで、分類1〜分類4までの流れをAJAXで実装したとする。そうすれば、おそらく、サーバーから受ける分類5のインプットの部分は、JSONなどの純粋なデータのみになると考えられる。そのデータを、クライアント側が保持する一覧表のテンプレートと合成して、実際にページとして表示される。これは、モダンなJavaScriptプレームワークに共通した仕組みであると言える。

これまでに検討した記述方法で全体像を記述してみたが、前述の通り、ボックスと矢印の部分の違和感を払拭することが必要であると考える。また、バインドしている事実が明白であれば、たとえば、フォームないの「名前」と「名前:検索条件」と記述した変数とのステレオタイプがbindingの関係は明白なので、この関係は1つのオブジェクトで記述しても良いだろう。また、ボックスと矢印がどの変数をアクセスするのかをより詳細に記述することにより、ユーザーインタフェースと処理プロセスの間の同時存在必要性も見えてきて、モジュール分離の指針にもなると考えられる。これらの点を引き続いて考えて行くことにする。

[開発プロセス#12] アプリケーション全体を改めて記述する

開発プロセスの検討を継続的にブログの記事にしてきたが、前の書き込みから3ヶ月が空いてしまった。しかも、#11はフレームワークの機能との分離を目指すことを書いたが、ちょっと順序を間違えたかもしれない。これまでのところで、Webアプリケーションの設計図を描くということを目指しているのだが、ユーザーインタフェース要素と処理の明確な分離がまず1つの目標であった。そして、ユーザーインタフェースは概念的な意味での変数にバインドしているという状況を記述するものであった。その間を、使用しているデータ(あるいはモデル)をある程度意識しながら、「処理の流れ」を記述することを検討していた。

Webアプリケーションとして、検索フォームがあって、その結果を一覧表示するようなものを検討してきたが、ここまでの検討の結果を利用して、図をさらに詳細に描いて見たのが以下の図である。図がだいぶんと大きくなってきた。また、書きながら問題点も出てきているが、まずは、図が何を示しているか、あるいは図が何を表現できているのかをまずは説明しよう。

まず、図の左側には、<<user interface>>というステレオタイプが記述されたサブシステムによる3つの「画面」が縦に並んでいる。「フォーム」と「一覧表」の2つだが、エラーメッセージ用にダイアログボックスが表示されるとすると、ダイアログボックスは「フォーム」の一部であるとも見ることができる。以前に説明したように、「フォーム」では、検索条件を入力するテキストフィールドがあり、「検索条件入力画面」というバウンダリーは、「名前」などのテキストフィールドから構成される。また「検索」ボタンをクリックするとデータベースから検索を行い、その結果を一覧表示に表示されることを期待する。エラーメッセージを表示する「JavaScriptアラート」は、メッセージとOKボタンの処理から構成される。

「一覧表」画面も、同様に「検索結果表示画面」というバウンダリーに代表されるが、名前や住所などのエンティティを表示する。「一覧表」の中の記述だけでは、一覧表になっているということが不明確である点は何らかの検討が必要と考える。

バウンダリーの要素としてはテキストフィールドやチェックボックスなどがあり、図では「検索条件入力画面」のコンポジションの1つである「名前」や「住所」などのように、具体的な定義が記述されている。Web開発ではその要素を参照して…というプログラムを書くか、あるいはフォームの仕組みを利用してサーバーにサブミットすることで終わりとなるが、ここでクライアントサイドの動作の詳細を検討するために、バウンダリーの要素は変数とバインドしていることにする。図では<<binding>>というステレオタイプで記述しており、「名前:検索条件」がその一例である。こうすれば、画面上の要素の設定や取得は、変数に対して行うという処理で一貫性が出てくる。しかしながら、実際にはそこまでの動作をやるとしたら、何らかのフレームワークを使うだろう。ここではフレームワークを取り入れた設計を先々では考慮したいので、あえてバウンダリーの要素を変数にバインドするという記述を行うことにする。

一方、「検索結果表示画面」バウンダリーについてはどうだろうか? 変数とは言え、単一のフィールドなら変数でいいとしても、データベースへのクエリーで得られたものであれば、結果的にはレコードという1つの集まりとなり、それらがさらに配列等で複数存在する結果を記録できなければならない。図では「レコード」、および「レコードセット」と表現している。一覧表にデータを表示するとなると、バウンダリーの要素(図では一覧表サブシステムのコンポジション「名前」など)は、テキストフィールドにしてもいいのだが、通常はTDタグ要素や、あるいはその中のP/DIV/SPANなどのタグに値として設定することになるだろう。テキストフィールドの場合には、変数とのバインディングということは考えやすいが、編集不可能なタグ要素についても、その要素と変数がバインディングしていると考えることが必要と考える。ただし、通常は、変数に値を代入すれば、それが要素に出てくると言った、変数→要素という一方向のものである。しかしながら、ある同一のレコードの、同一のフィールドの値が、テキストフィールドとDIVタグ要素に表示されているとする。単にHTMLだけの実現ではテキストフィールドの値を変えても、DIVタグ要素の値は変わらない。しかしながら、同一の変数、あるいは変数間の同期を実現しているのであれば、テキストフィールドを変更すると同時にDIVタグの表示が変わるということが実現可能となる。結果的に、データベースから取り出した値を有効に使うにはレコードをオブジェクト、レコードセットを配列で扱うことになるが、それらをオブザーバブル(Observerパターンを適用して、変更結果を他のオブジェクトに伝達する仕組みを持つもの)にする必要があるという議論に到達できるのである。一覧の表示に変数という媒介を考える必要はないと言ってしまえばそれまでだが、バインディングを通じてバウンダリーと背後の処理が連携するという仕組みは、MVVMパターンが持つ大きな特徴の1つでもある。その点でのバインディングを基調とした抽象化はフレームワークを単なるテンプレートエンジン以上の価値があるものへと押し上げたこの10年近くのフロントエンドの発展を支える重要な概念となった。

図の説明はまだまだ尽きないので、続きは次回に説明する。