[続開発プロセス#1] そして、開発プロセスを再考する

以前に、INTER-Mediatorを中心とした開発プロセスを作るということで、あれこれと記事を書いていましたが、最後の記事からもう3年近く経過してしまいました。開発プロセスとして明白な結果は得られませんでしたが、抽象的に記述することを細部に渡ってやってみて、色々知見は得られたと思っています。もちろん、細部に到ることが抽象化とは反対の方向に向かっているのではないかとか色々考えることがありましたが、その後、しばらく塩漬けにして考えをまとめることにしました。ただ、今も、まだ固まった考えがあるわけではなく、また、別のシリーズとして、書き続けると言うことで、結論に近づければいいなと考えているところです。

まず、以前に書いていた内容は、明らかに粒度が小さすぎます。UIに関しての設計方法は、UIそのものを対象にするのが、直接的であり、そこからわざわざ対象オブジェクトの抽出をして抽象化しても、単に手間がかかるとか、かえってややこしくなるだけではないかと考えました。結果的に、モックアップ駆動開発と言う路線はそのままがいいと言う考えに至っています。

次に、モデルそのものは階層的にすべきではないかという考え方が出てきました。多くの設計ではそうした考え方は一般的です。現状のドメインをモデル化し、それを元に実装可能な形式のモデルをクラス図で描く。ここまでは一般的です。これに加えて、実装可能な設計モデルのコア版、つまりDBスキーマとかなり一致度が高い物を記述する一方、さらに、フレームワークに特有な設計情報を入れ込めた設計モデルを記述するという方法が良いのではないかと考えました。この方法だと、INTER-Mediatorだけでなく、他の環境にも適用ができるでしょう。実際に、FileMakerでもその手法で開発をしてみました。SalesforceやService Nowなど、様々な開発環境を利用する必要がある現在、環境依存とそうでない部分を早い段階で分離することで、実装計画がよりスムーズに進むのではないでしょうか。ローコード系ではとにかくツールにかじりつく蛍光が強いですが、方針を持って作業に入ることがエンジニアリングを実現する手法だと考えます。

モックアップとしてのUIはHTMLで記述します。そして、クラス図を中心にしてドメインモデル、コア設計モデル、実装環境依存設計モデルを作るという方法で設計が進められるということを、しばらくあれこれと書こうと思っています。

論理値の演算で→(IMP, implication, ならば)があればなぜ便利か?

ブール代数の演算では、AND(∧)、OR(∨)、NOT(¬)があれば、どんな論理式でも構築できるというのが基本ではあるが、命題論理の世界では、PとQが命題(真か偽かのどちらかの結論しか持たない記述)として、P→Qという演算を定義し、頻繁に利用する。この演算は、Pが真の時は、Qの真偽の値が得られる一方、ちょっとわかりにくいのが、Pが偽ならP→Qは真になるというルールだ。ここで、「ならば」というのを日本語として解釈すると、しっくりこない。これは『強いて言えば「ならば」みたいな感じ』程度での理解をしておくのがいいだろう。

この→は、命題論理だけではなく、もちろん、ブール代数でも定義して利用可能だ。論理式で記述すると、P→Qは「¬P ∨ Q」となる。ということは、プログラミング言語できちんと書けるではないかということになるのだが、 →に相当する演算子はあまりプログラミング言語としてサポートしている例は少ない。例えば、OCL(Object Constraint Language)ではサポートされているが、JavaScriptなど他ではあまり見ない。もちろん、演算子の定義ができれば自分で作るという手もあるが、言語でサポートされていない機能はそれだけ馴染みが薄いとも言える。しかしながら、→を使った方がシンプルに論理式を記述できるとしたら、プログラムの中で使ってみたくなる。

→演算が便利な場合はないかと例を考えてみた。ここで、何か商品を販売するときに、付随するオプション的な項目が、それぞれ状態があるとすると、→が使えると考えた。例えば、名刺印刷という基本的なテキストのみの印刷を行う商品があるとする。これに、「顔写真印刷」「会社ロゴ」印刷がオプションとして、追加料金を取っているとしよう。顔写真、会社ロゴ、いずれも画像ファイルを入稿しなければならない。つまり、入稿を確認して、印刷に入れるということだが、もちろん顔写真オプションを選択していないなら、入稿の有無は関係ない。次のように命題を定義する。

P = 顔写真印刷を申し込んだ
Q = 会社ロゴ印刷を申し込んだ
Y = 顔写真の画像をアップロードした
Z = 会社ロゴの画像をアップロードした

そして、名刺印刷のための版下作成が可能かどうか(ここでは簡単のためにオプションの画像が必要であれば入手されているという状況だけで考える)は、以下の論理式で求めることができる。

P→Y ∧ Q→Z

もちろん、真理値表を記述して全部検証すれば問題ないのはわかるが、まずはシンプルに意味的に検証しよう。P、Qはいずれも、→の左辺にあり、値が偽なら、つまり、オプションとして申し込んでいなければ→の結果は真になる。つまり、∧の両側は申し込みしていないものは常に真になり、真偽は申し込みをしているものに限って考えれば良いということになる。そして、申し込みをしていれば、アップロードしたかどうかで、∧の両側の値は決まるので、上記の式が真になるのは両方とも真、つまり、申し込んだオプションが全てアップロードされた場合に真になる。繰り返すが、オプションを何も申し込んでいないと式の結果はやはり真になり、オプション関係なしに印刷に入れば良いということだ。そういった状況が一気に→が表現しているとも言える。

真理値表を作成すると、以下のようになる。なお、オプションとして申し込みをしていないのにアップロードしているという矛盾した状況もある(表の最後の列に*を記述)が、申し込みをしていないという状況だけが結果に影響されるので、そのために式を修正する必要はない。言い換えれば、うまく→の右辺の状況を打ち消してくれている。

PYQZP→YQ→ZP→Y ∧ Q→Z
0000111
0001111 *
0010100
0011111
0100111 *
0101111 *
0110100 *
0111111 *
1000010
1001010 *
1010000
1011010
1100111
1101111 *
1110100
1111111

以上のように、「商品のオプション」という状況なら、→演算でシンプルに論理式を記述できそうだ。もちろん、¬と∨で展開してもさほどではないが、複雑な式は別の機会にみた場合には、間違いを誘発しそうな感じがありありとする。また、→での記述の方が、要求や要件の記述に近いと言うことも期待できるのである。

composer.jsonファイル内でのスクリプトのパスをUNIX/Windows互換にする

 PHPでのモジュール管理ツールであるcomposerでは、通常「composer update」と入力することでインストール作業が始まるが、インストール後に実行するスクリプトを記載することもできる。INTER-Mediator Ver.6では、composerの仕組みによりnode.jsをインストールして、「composer update」に引き続いて「npm install」を自動的に動かすようにしている。composer.jsonファイルの主要部分はこんな感じだ。package.jsonはすでに用意されている。composerはvendorというディレクトリを作り、そこにモジュールをコピーし、加えてネームスペースを元にしたファイル検索の仕組みが組み込まれる。単にコマンドを入れてみれば、nodeやnpmコマンドがvendor/binにコピーされているので、相対パスの記述が適切だと考えた。

{
"name": "inter-mediator/inter-mediator",
"version": "6-dev",
"time": "2019-03-07",
:
"require": {
"php": "^7",
:
"mouf/nodejs-installer": "*",
:
"scripts": {
:
"post-update-cmd": [
"./vendor/bin/npm --save-dev install"
],
:

 これで、macOS、Linuxでは正しくnpmコマンドが稼働するのではあるが、Windowsではエラーが出てnpmが動かない。PowerShellでは次のようにでる。最後の行は赤い背景になる。コマンドプロンプトでもほぼ同様だ。

> ./vendor/bin/npm --save-dev install
'.' is not recognized as an internal or external command,
operable program or batch file.
Script ./vendor/bin/npm --save-dev install handling the post-update-cmd event returned with error code 1

 やっぱり/だろうかと思ってディレクトリセパレータを¥にしてみた。もちろん、JSONなので¥¥とタイプするが、やはり同じだ。./を無くしても同じである。

 あれこれ調べて分かった。composerのドキュメントのNoteの所に書いてある。要するに、./vendor/bin(あるいは.¥vendor¥bin)へは、composerによってパスが通っているらしい。composerによってインストールされるコマンドの場合は、以下のように相対パスを書かなくても、npmコマンドの実行はできるということである。この記述だと、UNIXでもWindowsでも同一の記述でnpmコマンド実行ができる。

 :
"post-update-cmd": [
"npm --save-dev install"
],
:

要求は対話を通じて次第に明確化するもの

 ソフトウェア開発では、実際に動くようにする「実装」という作業が必要である。どのように実装するかは「要件定義」という記述を元にして検討され、その要件定義は顧客の「要求」を元に作られるというのが原則だ。本来は要求が先にあり、「〜をしたい」「〜を実現したい」という形式で記述できるものが基本である。「○秒以内で処理が完了する」と言った非機能要求も記述される。しかしながら、この要求による記述内容だけでは、その実現方法が多岐に渡る事になる。そこで、実装を円滑に進めるために「〜ができるようにする」という形式で記述できる要件を定義し、実装側は要件の実現に注力する。容易に分かるのはこうすれば実装の分業がやりやすいことだ。開発業務は元請けから下請けや複数の開発者に至る階層化された業務フローが一般的であり、要件定義は分業の基礎としてビジネス構造にもマッチする。この方法の是非はあるのだが、長年この流れをベースにやっているだけに、なかなか変えられれないというのが実情だとして、この枠内で開発における問題点を考える。

 うまく分業され開発が進むかと思うと、現実には顧客が望んでいたものと違ったものが開発されてしまうという問題がある。笑い話になりそうな、全く違うものができてしまうこともある。ちょっと意図的に強調した例として次のようなものがある(もちろん、かなり単純化している)。要求として「ポイントシステムを作りたい」として、要件としていくつか作られた項目の中に「ユーザー管理機能」というものがあるとして、その要件だけを知らされて実装したとしよう。すると、単に住所録みたいなものが出来上がり、管理番号がないとか、期限の管理はどうするのよ?みたいな実装が上がってくるかもしれない。もちろん、通常は自身が実装する要件以外も目を通すので、優秀なプログラマーたちの忖度機能が発動され、次第に顧客の要求に近づくということになる。なんだ、うまく行っているということではないのか?と思われるかもしれないが、うまくいく前提の1つとして、要求も要件も記述されている、つまりは文書化されているという前提がある。もちろん、100%文書化できるものではないのは確かだが、一定以上の割合の文書化がされていないとおそらく忖度ベースの開発は成り立たない。そして、経験上、一定以上の割合が満たされることはほとんどないと感じている。

 ソフトウェア開発の形態は実に様々あり、個別の事情も多いのだが、ここでは単純化して、顧客とコントラクターとデベロッパー(開発者)の3つの存在があるとして考えよう。下請け構造については「開発者」の一言で片付ける。ざっくりと言えば、SIerという人たちは「コントラクター」であるが、いわゆる「ゼネコン」の意味でのコントラクターであり、顧客から業務を請負、遂行する中心人物である。このような状況で開発をしている場合、開発者にとっては顧客の要求が極めてわかりにくいことが多々ある。好意的に見えればコントラクターが開発者にわかりやすいように解釈して作業に分割してくれている結果とも言えるのだが、コントラクターが顧客の要求を本当に理解しているのか疑問に持つような要件を投げてくることもある。たぶん、誰も悪意はない。それでも、比較的大きめの開発をしていると、要件に矛盾が目立つようになることが出てきて、疑問は急激に膨らむのである。要件は解釈がぶれる余地のない文章に一般的にはなっていることもあり、開発者は要件は書いてある通りに解釈できるものの要求が断片的にしか分からないと強く感じるようになる。コントラクターとの関係が悪くなると、責任の押し付け合いにもなる。

 何とかならないのだろうか? だからこそアジャイルなのだろうか? 手法に至る前にまず、問題の本質をどこに求めるかを特定したい。開発者が要件が分からないと感じる時、実はコントラクターも要件はよく分かっていないことが多い。開発者がコントラクターに問い合わせた場合、開き直って「私にもわかりません」と言われても困るのだが、もっと困るのは分かっているふりをすることで、顧客の要求と異なる回答をしてしまうこともある。実は、開発者と同じ程度にコントラクターも顧客の要求が分かっていないと考えるべきだ。そうなると、コントラクターがもっとしっかりすべきなのだろうか? それでは、よくある「営業 vs 実行部隊」の局面になってしまい責任の押し付け合いに等しく、ここから何か生み出されたことを見た事はない。開発者はコントラクターを責めてはいけない。その理由は、実際のところ、顧客自身が実はコントラクター以上に要求を理解していないからである。顧客に何か要求が明確にあるのかというとそうでもない事が普通にあるというのが現実だ。正直な顧客は「モヤモヤした話で恐縮ですが」と切り出して、構想を語る。不誠実な顧客は「お前らプロなのにそんなんことも分からないのか」と訝る。分からないから聞いているのである。私たちが超能力者でないことを説明する気力は普通は出ない。何れにしても、要求が文書化されているかと言えば、極めて限定的になってしまうのが通常である。

 そこで、顧客は要求を理解していないという前提に立つ必要がある。理解していないというのは色々な側面がある。何か構想はあるけど言語化されていない場合もあれば、上司に言われてシステム化の取りまとめをしており経営的な意味は全然説明されずに担当者になっているような場合もある。この点は掘り下げたいところだが、ここでは文書化あるいは言語化されていないという状況としてまとめておこう。このような状況は、次のように考えて見よう。顧客の頭の中はファンタジーであり、顧客の発する言葉はポエムなのである。ソフトウェア開発において、コントラクターはそのファンタジーを実現すべく奔走する人であり、開発者はポエムを開発言語に翻訳する人たちである。それじゃあやってられん!と言う前にこう考えよう。ソフトウェア開発者は、要するにスターウォーズのような素晴らしいSF作品を制作しているスタッフのような存在なのだと。若干無理やりかつ恣意的なポジティブ化ではあるが、ここで前を向かないとどうしようもないのである。

 ここであっさり「要求なんぞはないものだ、幻想だ」と言い切るのも無理がある。現在の多くの開発手法は要求が出発点にあるから。要求がないのではなく、開発者は要求を何らかの方法で明確化をする必要があるという前提に立ちたい。筆者は開発者として関わることがあるが、一人で全部行うコントラクター兼開発者の場合もある。後者の場合の問題点はかなり別のことが絡むので、ここでは顧客/コントラクター/開発者モデル場合だけに限定する。短絡的な考えとしては、開発者として関わっても、顧客と直接話をしたらなんとかなるのではないかとも考えた。だが、ビジネスライン的な意味で、普通はコントラクターは嫌がるのと、対顧客に対する原点的な意味での要求獲得は別の難しい問題があるので、開発者と顧客を会わせるというのはよほど限られた状況でしか成立しない。少なくとも、開発者が顧客対応可能なSE能力を持つような場合などである。ということで、顧客/コントラクター/開発者ラインを保って要求を明確化する方法はないかと試行錯誤をした結果、1つの方法がうまくやれば良い方向に行くのではないかという感触を得た。確証を得るほどの事例に当たった訳ではないが、提案はできる段階に来たと感じている。

 その方法は、コミュニケーションにおいて、要求の断片を話題に含めて、その要求あるいは会社が正しいかを検証することである。例えば、要件定義として「顧客管理番号は7桁である」と書かれているとしよう。これは少なくとも、「123」でいいのか、「0000123」のようにするか悩む定義である。単に「この要件は管理番号の頭を0で埋めるという意味でしょうか?」などと問い合わせるのが普通だと思われる。このコミュニケーションの中において、要求に近い文章を紛れ込ませる。例えば、「管理番号は、ポイントカードに印刷されるので、頭を0で埋める7桁なのでしょうか?」と聞いてみる。ここで「ポイントカードは印刷してお客様に渡したい」「ポイントカードには管理番号が印刷されていて、システム問い合わせで利用したい」と言った要求を言い換えて、質問に含ませている。このような問い合わせに対して、正解と言われるかもしれないが、違っているかもしれない。「管理番号はポイントカードには印刷しません。単にバックエンドのシステムが7桁で切られているから、それを気をつけて欲しいという意味です」のように答えが返るかもしれない。どっちにしても、ほんの少しだが、要求に近い情報が得られた。もちろん、それは小さな積み重ねだが、全くないより大きな進歩があるはずだ。なんとなくそうなのかなと思っていたことが明確になることも小さな進歩だろう。前記の例だと、「実は顧客情報はバックエンドのシステムにも入れられる」という新しい発見があったのかもしれない。仮にポイントカードに印刷するための0埋めだったとしたら、それをどこでやるのかという議論に発展するかもしれない。

 開発者からコントラクターに、要求が分からないから示して欲しいと言っても、コントラクターは開発者と同程度、下手をするとさらに下回るレベルでしか要求は理解していないと考えるべきだ。しかも、コントラクターはその点を意識しているかどうかも怪しい。無理やり文書化をお願いしたとしても、出てくるものには新しい情報はない。顧客に依頼するというのも同様だ。しかしながら、要件の中から要求を含めた、あるいは要求に至る内容を込めたコミュニケーションをすることで、不明瞭な要求群に対して逆算的に少しずつ隙間を埋めるような効果が期待できる。その結果、要求が次第に明確化し、気づいていない関連性が見えて来ることも期待できる。開発者にとって知る事も重要だが、コントラクターやさらには顧客に対しても気づく機会を作っていることも重要である。開発に関わる全ての人の意識を要求のさらなる明確化に向けるためのコミュニケーションが活発になることで、開発現場の様々な側面で要求が次第に固まるということを期待できるのではないかと考える。

 この手法で一番難しいのは作文である。コントラクターや顧客との関係上、どこまで言っていいのかなど、ドメインや個別の事情も絡む。要件に絡めるというのが1つの成立しやすい手法だが、普段の会話で投げてみるというのもあるかもしれない。しかしながら、同じようなことを何度も聞く、突拍子もない質問になってしまうといったようなことは避けたほうがいい。バカ者かと思われてしまうのは不利な状況を作りかねない。それでもうまい問いかけを繰り返し辛抱強く進め、成果物に対する着目点を顧客/コントラクター/開発者でなるべく多く共有できれば、より良い結果になることは十分に期待できる。

 実装する開発者が何人もいるような開発で、頼りになるように見える人は必ずいる。その人は、発言が多く、かつ、発言の中で、念の為にという意味合いで色々な角度で言葉を繰り出す発言が目立つ。そうしたやりとりが、開発の中で自身の実装部分に対しても非常に参考になったという経験もある。確認のために、条件を言い換えてみたり、その要件の目的をたずねてみると言った行動が、他の開発者の助けになるということもあった。そういう人はコミュニケーションスキルが高いという事で終わらせがちだが、スキルには細かなポイントがたくさんある。その1つが要求の明確化であり、それがコミュニケーションから可能ではないかということも、様々な人たちの行動や自身のプラクティスからの結論である。一方、この方法がうまく行かない事例として、コントラクターが開発者の発言を抱えてしまって顧客に流さないタイプの人である場合だ。コントラクターがしっかりしていればいいとも言えなくはないが、前記の通り、開発者が要求が分からないときは得てしてコントラクターも分かっていない。顧客に確認もしないというのは、単なる顧客に対するイエスマンかもしれないが、要求に対する問題意識がないのかもしれない。こういう現場では、とにかく時間がかかり、作業方針も立ちにくく、開発者の間で何かがぐるぐる回っているだけになる。このようにアンチパターンはある程度は見えている部分もあるが、まずはプラクティスとして問いたいと考える。

Ubuntu Server 18上でのMySQL

別の記事でUbuntu Server 18で、INTER-Mediatorが動くまでのところを説明しました。

この中で、一部忘れていたことがあるので記載しておきます。MySQLのエンコードです。既出の記事の手順だと、MySQLのエンコードの指定をどこかでしないといけなくなります。mysql.cnfでもいいのですが、mysql.cnfにエンコード情報を入れるのではなく、PDOの接続文字列に

"charset=utf8mb4;"

の記述を追加するのが一番手軽だと思われます。スキーマにも、もちろん、

use utf8mb4;

を記述して、中身はUTF-8で記述すればいいですね。

Ubuntu Server 18でINTER-Mediatorを動かすまで

この原稿の内容は時間が経過して内容として不足しています。こちらの記事を参考にしてください。


Ubuntu Server 18.04.1 LTS上でINTER-Mediatorを動かす話です。とは言え、半分以上はLAMPサーバーセットアップの方法となるかと思います。なお、様々なコマンドがちょっとずつですが変わっているので、その辺りも含めてまとめておきます。

サーバーはVirtual Boxで稼働させました。このサーバーは単に実験するだけでなく、INTER-Mediatorのデモ用にも使いますので、外部からのアクセスが必要です。そこで、ネットワークは、NATとブリッジネットワークをこの順序に設定しておきました。そして、インストール途中で、ブリッジネットワーク側は、ローカルネットワーク側に存在できるような固定IPに設定します。この設定は後からでもできるのですが、最初からやっておくのが失敗がありません。NATが必要かどうかの問題もありますが、ブリッジネットワークを切っても外部に接続できるようにするために、こうしました。

さて、セットアップ後、apt-getなのですが、その前に、以下のように、レポジトリの設定ファイル/etc/apt/sources.listの3行いずれも末尾に「universe」という単語を入れておきます。こうしないと、PHPのいくつかのモジュールをインストールできませんでした。

$ cat /etc/apt/sources.list
deb http://archive.ubuntu.com/ubuntu bionic main universe
deb http://archive.ubuntu.com/ubuntu bionic-security main universe
deb http://archive.ubuntu.com/ubuntu bionic-updates main universe

(2019-01-03追記)ubuntu-18.04.1.0-live-server-amd64.isoというファイルでインストールしたところ、上記のuniverseを追加する作業は不要でした。最初から、レポジトリが読み込まれる状態になっています。

こうして、apt-getします。私はaptitudeでやる習慣ができてしまったので、aptitudeでやったのですが、試行錯誤しないのなら、apt-getでやることになるので、コマンドはapt-getで書きます。Apache、PHP7.2、MySQL、PostgreSQL、SQLiteまでを入れました。INTER-Mediatorを稼働するのに必要なPHP追加モジュールは、概ねこのようなあたりですが、追加が必要そうならこの文書を更新します。

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install -y apache2 php7.2 libapache2-mod-php7.2
sudo apt-get install -y php7.2-mbstring php7.2-bcmath php7.2-curl php7.2-xml
sudo apt-get install -y mysql-server-5.7 mysql-client-core-5.7 php7.2-pdo-mysql
sudo apt-get install -y postgresql php7.2-pdo-pgsql
sudo apt-get install -y sqlite3 php7.2-pdo-sqlite

ちなみに、PDOのライブラリは、「-PDO」の付いていないもののエイリアスらしく、そういうメッセージが出て、例えばMySQLなら「php7.2-mysql」がインストールされます。

なお、Apacheの再起動が必要になることがあるかと思われますが、こちらのコマンドを使います。serviceコマンドも従来通り使えますが、systemdベースになっていますので、今現在の状況に合わせたコマンドを使いましょう。

sudo systemctl restart apache2

INTER-Mediator Ver.6を試すなら、composerは必須です。ホームフォルダをカレントにして以下のようなコマンドを入れることでインストールされます。レポジトリのものもあるようなのですが、この方法だと最新版が入手できるので、こちらを紹介します。他のサイトもほとんどこちらの方法を紹介しています。これで、コマンドプロンプトに「composer」と入れればヘルプが表示できます。なお、実際のcomposerの動作では、PHPのzipモジュールとunzipコマンドのインストールも必要なので、そのコマンドも記載しておきます。それから、gitも必要ですね。

cd
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
sudo php composer-setup.php --install-dir=/usr/local/bin --filename=composer

sudo apt-get install -y php7.2-zip unzip
sudo apt-get install -y git

ここまでで、LAMPサーバーセットアップができているということになります。WebサーバーのルートにINTER-Mediatorをインストールするとしたら、例えば、以下のコマンドで行えます。

cd /var/www/html
git clone https://github.com/INTER-Mediator/INTER-Mediator.git

ファイルのダウンロード後に、INTER-Mediatorフォルダをカレントにして、composerコマンドを稼働します。composerを稼働させないと、PHPのプログラムへのパスが通りません。composerを使ったいろんな作業はあるのですが、ここではダウンロードしたものをそのまま動かす方法をまずは説明しました。

cd INTER-Mediator
composer update

MySQLへのrootユーザーでのログインは次のように行います。なんとなくPostgreSQLのようになってきました。rootパスワードを設定してどうこうするという状況ではなくなったようで、この状況に適応しましょう。管理者ユーザーで、mysqlコマンドを打つのでjはなく、sudo mysqlということです。パスワードは、sudoの時のパスワードで、つまりはログインしている管理者のパスワードを入力します。MySQLのrootのパスワードはつまりは指定しません。

sudo mysql -uroot

INTER-Mediatorのサンプルファイルを読み込むとしたら、こんな感じになります。もちろん、必要に応じて、管理者のパスワードを入力します。サンプルは、INTER-Mediator/dist-docsにあります。

sudo mysql -uroot < sample_schema_mysql.txt

一方、PostgreSQLは、以前からpostgresユーザーでの接続を行うことで、データベース接続していましたが、その点は変わりません。sudoでpostgresユーザーになるので、現在のログインしている管理者ユーザーのパスワードを知っておく必要があり、postgresユーザーのパスワードは利用しません。コマンド接続と、INTER-Mediatorのサンプルの読み込み例を記載します。サンプルは、INTER-Mediator/dist-docsにあります。

sudo -u postgres -i

sudo -u postgres psql -c 'create database test_db;'
sudo -u postgres psql -f sample_schema_pgsql.txt test_db

SQLiteは特に違いはありません。サンプルは、INTER-Mediator/dist-docsにあります。

sudo mkdir -p /var/db/im
sudo sqlite3 /var/db/im/sample.sq3 < sample_schema_sqlite.txt
sudo chown www-data /var/db/im
sudo chown www-data /var/db/im/sample.sq3

Jupyter notebookでPHPを動かす

macOS Mojave上で、Jupyter notebookを動かし、PHPのkernelを稼働させる方法を記載します。ほとんど自分用のメモみたいなものですね。なんでJupyterなのかというと、先日Bitcoinのセミナーに行ったのですが、その中で自身が作ったライブラリのデモをJupyterでやっていた人がいて、なかなか良いなと感じたからです。結構分かりやすく、セットアップしていれば実際に動かすこともできるからです。そこで、FMDataAPIのサンプルをJupyter notebookベースで示せるようにしたいということがあります。

まず、Jupyterが動いている必要があります。以前にJuliaを入れた時に色々試行錯誤したこともあって、素直な手順がわからないのですが、Homebrewを使うなら、

brew install jupyter

もし使わないのなら、以下のように、pipのアップデートをしてからjupyterをインストールします。

pip3 install --upgrade pip
sudo pip3 install jupyter

PHPの稼働が必要ですが、Mojaveでは、Homebrewを使って入れるのが良いでしょう。こちらも、いろんな用途に使っているので、あれこれ試行錯誤した結果を使っています。何れにしても、php72を、brew installで入れています。

Jupyter用のPHPカーネルは、Jupyter-PHPをインストールします。なお、このカーネルを使うには、PHPのZMQ (ZeroMQ)のモジュールが必要になります。これは、Homebrewにないので、peclでインストールします。最初のコマンドを入れると、次のように、直接レポジトリを指定しなさいと出てくるので、ともかくそうします。

sudo pecl install zmq
sudo pecl install channel://pecl.php.net/zmq-1.1.3

php -iで、phpinfo()関数相当の情報を見てみますが、おそらくエラーが出ると思われます。peclが識別している.soファイルのフォルダと、php72の.soフォルダが違うからです。

メッセージを読めば、それぞれのパスがわかるので、例えば、以下のようなコマンドで、生成したzmq.soファイルを、php72の.soファイルの位置にコピーします。これで、php -iはエラーなく実行できました。

$ cp /usr/local/lib/php/pecl/20170718/zmq.so /usr/local/Cellar/php/7.2.12/lib/php/20170718
$ php -i|grep zmq
zmq
libzmq version => 4.2.5

続いて、Jupyter-PHPをインストールします。サイトのトップページに、インストーラーのダウンロードリンクがあります。署名付きで試したらエラーになったので、とりあえず、署名なしをダウンロードして以下のコマンドを打ち込むと問題なく終わりました。

cd ~/Downloads/
sudo php ./jupyter-php-installer.phar install

こうして、「jupyter notebook」とコマンドを入れれば問題なく使えるようになりました。NewのところにPHPが出てくるので、それを選択してノートブックを用意します。FMDataAPIのノートブックは出来上がれば。レポジトリに公開します。実行済みのノートブックだと、Outも全部入っているのですが、GitHubは多分、.ipynbをリードオンリーのノートブックとして開ける機能があるようなので、サンプルコードを解説とともに読めるノートブックを、該当ソフトウエアをインストールして稼働させなくても、結果を見ることができるようになります。

で、作業していると、コードのカラーリングがされないのがちょっと寂しいです。方法はあるようですが、これをやっても自分の環境だけなのではありますが、それでもカラーリングしたいので、探してみると、jupyter-themesというのがありました。手順通りインストールできました。wgetではなく、curlを使う程度の違いです。

mkdir -p $(jupyter --data-dir)/nbextensions
cd $(jupyter --data-dir)/nbextensions
mkdir jupyter_themes && cd jupyter_themes
curl -O https://raw.githubusercontent.com/merqurio/jupyter_themes/master/theme_selector.js
cd ../ && jupyter nbextension enable jupyter_themes/theme_selector

しばらくカラーリングはうまく動いていたのですが、今、これを書いている時にはなぜか動いていません。再起動ですしょうね。

[IM] FileMaker Server 17とINTER-Mediator

FileMaker 17が発売されました。そして、FileMaker Server 17がリリースされました。ちょっとずつ変わりながら毎年アップデートするFileMakerですが、サーバーは結構変わっています。大きなところでは、管理コンソールがグッと今風なデザインになり、かっこよくなりましたが、その代わり、管理コンソールで設定変更できない項目が出てきました。その辺りがINTER-Mediatorの利用に大きく関連するので、INTER-Mediatorの利用に重点を置いて、変わった部分を説明しましょう。

PHPはインストール直後は未導入

FMS16までは、セットアップ時に選択すればPHPを設定できましたが、FMS17は初期状態ではPHPは使えない状態になっています。もし、PHPを別のサーバーで動かすなら、もうFMSのWebサイトにはPHPは不要ということになりますが、FMSのWeb機能を自分のマシンで動かして検証するなどの作業をしたい方も多いでしょう。その場合、以下のようにコマンドを入れます。$に続く部分が自分で入力するコマンドで、太字にしてあります。fmsadminコマンドで、管理コンソール上では見えなくなったいくつかの機能の設定を行うようになったのです。ユーザー名とパスワードを聞かれれば、FMSの管理者のユーザー名とパスワードを入力します。

$ fmsadmin set cwpconfig enablephp=true
username (msyk):admin
password:
EnablePHP = true
Restart the FileMaker Server background processes to apply the change.

macOSの場合は、「ターミナル」を使います。ログインしているユーザーが管理者の場合には、sudoをしなくても、fmsadminは利用できます。Windows 10の場合、最近まで、スタートメニューの右クリックででてくるメニューで管理者権限でコマンドプロンプトを起動できましたが、いつの間にかこの項目はでなくなっています。スタートメニューの右クリックで「Windows PowerShell(管理者)」を選択して、PowerShellを使いましょう。「コマンドが違うのでは?」と思われるかもしれませんが、上記のfmsadminも、以下のnetコマンドもPowerShellで使えるので安心してください。

このコマンドを入力すると、最後に再起動をするように出てきます。ここで、Webサーバーだけの再起動(HTTPServerフォルダにあるstop、startというファイルをsudo touchで更新)でやってもPHPは稼働しません。それから、CWP(Custom Web Publishing)の再起動も同様です。以下のコマンドで機能の再起動を行います(松尾さん、ありがとうございます)。もちろん、FileMaker Serverの管理者のユーザー名とパスワードを入力する必要があります。

fmsadmin restart httpserver -y

以下のように、FMS全体の停止と起動を行う必要があります。macOSの場合は次のように2つのコマンドを入れます。

sudo launchctl stop com.filemaker.fms
sudo launchctl start com.filemaker.fms

Windowsの場合は、以下の2つのコマンドを入力します。なお、Windows 10の場合は、他に考慮点が色々あるので、この記事の最後の方にそれを記載をします。

net stop "FileMaker Server"
net start "FileMaker Server"

これで、phpinfo()関数を動かすと、次のように、Ver.5.6.24が稼働していることがわかります。なお、info.phpファイルの中身は、phpinfo()関数だけでなく、タイムゾーン指定を入れないと警告が出て情報は表示されません。例えば、info.phpファイルは次のように作ります。

<?php date_default_timezone_set("Japan"); phpinfo(); ?>

PHP自身は古いビルドのままですし、Ver.7.2が主要リリースな今時にVer.5.6なので、アップデートする気はないというところが感じられます。

つまり、FMS17をインストールすると、PHPの実行環境はインストールされているものの、利用できる状態になっていなかったということです。ちなみに、macOSの場合は、Apache2の主要設定ファイルである/Library/FileMaker Server/HTTPServer/conf/httpd.confの最後に、

Include '/Library/FileMaker Server/Web Publishing/publishing-engine/php/sierra/httpd.fmi.conf.php'

という行が加わり、モジュールが読み込まれます。Windowsでも、FileMaker ServerフォルダはC:¥Program Files¥FileMakerにありますが、そこからのパスはほぼ同じような場所にPHPの実行環境が用意されていますが、IISにサイトを追加してWebサーバーとして稼働するようにしています。phpinfo()関数でphp.iniファイルを確認して、必要であれば設定を変更しましょう。

db-class=”FileMaker_FX”を指定する場合

FX.phpを使ってFileMaker Serverへ接続する場合を説明しましょう。INTER-Mediator 5.7/6現在、現実にはFX.phpの一部分だけを使っていますが、何れにしても、以前からあったXML共有を利用してデータベースアクセスしています。

XML共有を利用するには、まず、Web公開エンジンをオンにします。管理コンソールで、コネクタのページを開き、左側のリストで「Web公開」を選択し、右側の「Web公開エンジン」にあるボタン(右のほうにある左右に動くスイッチ)が全体的に青くなるようにしてオンにします。しかし、これだけではありません。

XML共有をオンにするには、さらに、以下のような$以降のコマンドを入力します。もちろん、FMSの管理者アカウントで認証が必要です。このコマンドに関しては、再起動は不要です。

$ fmsadmin set cwpconfig enablexml=true
username (msyk):admin
password:
EnableXML = true

このように、「Web公開エンジン」のオン、そしてXML共有をオンにすることの両方が必要になります。

db-class=”FileMaker_DataAPI”を指定する場合

FMS16でプレビュー扱いだったFileMaker Data APIも、FMS17では正式機能となり、ライセンス価格も「ダウンロードデータ量」に関連することに決まりました。ユーザー数で考えれば幅が広くなるWebサイトの事情を考慮したという点では評価できると考えます。1年間のライセンスの場合、24GX人数までが購入価格に含まれた分量ですが、ともかく、データ転送量を見積もらないと、かかるコストが分からないという状況になりました。

FileMaker Data APIの正式版は、ある意味で「バージョン1」と呼ぶのが適切でしょう。API呼び出しのURLがプレビュー版と大きく違っており、URLに「v1」という文字があることからも、API自体にバージョン管理を今後は行うということを示唆しているものと思われます。

FileMaker Data APIに応答するようにするには、管理コンソールで、コネクタのページを開き、左側のリストで「Web Data API」を選択し、右側の「Web Data API」にあるボタン(右のほうにある左右に動くスイッチ)が全体的に青くなるようにしてオンにします。これだけでよく、コマンドの入力は不要です。

なお、INTER-Mediatorは、FMDataAPIというライブラリを利用して、FileMaker Data APIを利用しています。FMDataAPIはVer.8で、プレビュー版からバージョン1へと対応APIを変更しました。FMS17リリース直後からVer.8は公開していますが、INTER-Mediatorで利用できるようになるためには、INTER-MediatorにあるFMDataAPIをアップデートしないといけません。アップデートするのは簡単ですが、FMS16のFileMaker Data APIは使えなくなります。もっとも、プレビュー版のAPIで真剣に構築していることはないだろうという見込みもあるので、単にどどーんとアップデートしてもいいのですが、その辺り、現在は検討中というところです。アップデート情報はFacebook等で公開します。

Windows 10でFileMaker Server 17

FileMaker Serverは、以前からWindows Serverが対応OSとなっており、Windows 10は対応OSではありません。また、FMS14に関するFileMaker社の文書では、「互換性はありません」となっています。ところが、Windows 10 Pro に FileMaker Server をインストールする によると、FileMaker Server 14/15のインストールができるようにする方法が書かれています。開発者としては手元のWindowsでFMSが動いて入れば便利だと思うところでもあるので、FileMaker Server 17がWindows 10で稼働するかどうかを試してみました。前述の記事のようにインストーラが動かないということはなく、インストーラは問題なく動き、インストールは可能です。ただし、インストーラが動くとは言え、様々なエラーメッセージをうまく捌かないといけない模様であり、「簡単ではないかもしれない」と言ったところです。そこで、PHPを動かすところまでを実現するためにどうすればいいかを確認しました。なお、FileMaker社は稼働するという保証をしていないので、Windows 10でのFMS利用はご自分のリスクで進めてください。

実際に確認したのは、Windows 10 Proに、バージョン1803のアップデートを当てたPCです。IISが稼働していない状態でインストールをすると、途中で次のようなメッセージが出てきて、インストールは途中で終わってしまいます。

そこで、IISをあらかじめ起動しておきます。スタートメニューを表示した時に左端に見えるギアのアイコンの「設定」を選択して、設定ウインドウを表示します。そして、「アプリ」を選択します。そして、右端にある「プログラムと機能」を選択し、懐かしいコントールパネルの「プログラムのアンインストールまたは変更」を表示し、左側にある「Windowsの機能の有効化または無効化」を選択して「Windowsの機能」ウインドウを表示します。ここで「インターネットインフォメーションサービス」のチェックを入れます。黒い四角になるのは下位の項目が全部チェックされているわけではないということを意味しています。ここで、World Wide Webサービス>アプリケーション開発機能と階層を下り、「CGI」のチェックを入れておきます。このチェックを入れておくのがポイントです。他はそのままでいいのですが、必要に応じて他の機能を入れてもいいでしょう。OKをクリックします。もし、再起動を求められたら再起動をしてください。

この準備をした上で、FileMaker Server 17のセットアップを行えば、概ね問題なく稼働するもようです。インストール途中で以下のようなダイアログボックスが出てくれば、「Webサイトを無効にする」をクリックしてください。これはIISのデフォルトのサイトをオフにして、FileMakerでセットアップされるサイトだけを利用するためです。

こうしてセットアップが終われば、最初に説明したようにコマンドを入れればPHPが利用できるようになります。ただし、INTER-Mediatorを稼働させるという観点では、初期状態のPHPのモジュール読み込みは十分ではないので、php.ini等の設定を変更する必要があります。これについては、近日中にまとめたいと思います。

IISの設定を見るには、スタートメニューを右クリックして「コンピュータの管理」を選択します。「サービスとアプリケーション」の下位項目に、IISがあります。Default Web Siteは停止状態になり、FileMaker Serverのセットアップにより、FMWebSiteという設定が増えていることがわかります。

ここで、PHPを稼働させる設定は、「ハンドラマッピング」の中にあります。その項目の詳細設定ダイアログボックスは次のようになっています。パスは、C:¥Program Files¥FileMaker¥FileMaker Server¥Web Publishing¥publishing-engine¥php¥php-cgi.exeが指定されています。

ちなみに、WindowsでのPHPの稼働方法をチェックすることも含めて、fmsadmin set cwpconfig enablephp=trueを使わないで、IIS上でPHPを稼働できるかを試してみたのですが、その時には、以下の2つのパスのフォルダに、IIS_IUSRSグループに読み取りと実行の権限を与える必要がありました。要するにWeb公開するフォルダと、PHPの実行モジュールへのアクセス権を設定する必要があるということでしょう。

C:¥Program Files¥FileMaker¥FileMaker Server¥HTTPServer¥conf
C:¥Program Files¥FileMaker¥FileMaker Server¥Web Publishing¥publishing-engine¥php

他に、アプリケーションプールの詳細設定で、32ビットアプリケーションの有効化をtrueにしてやっと動いたということもあるのですが、FileMaker Serverに自動設定させた結果では、アプリケーションプールの設定はfalse(既定値)のままでした。

以上のように、Windows 10でもFileMaker Server 17は使えたのですが、なんども書きますが、対応OSではない点を理解した上で対処をしてください。

INTER-Mediatorのレコード数制限の実装

INTER-Mediatorのことをブログで書くのが久しぶりな気がしているが、以前のように、設計書代わりにブログを書いておく。INTER-Mediatorのコードにタッチしていない方はなんのことか分からないと思うので、最初にその点を指摘しておく。

INTER-Mediatorでは、ページネーションコントロールを自動的に生成して、例えば30レコードずつ表示するような仕組みを設定だけで実現している。しかしながら、その後に、ポップアップメニューからレコード数制限をできるようにしたり、Master/Detail形式のUIを実現したりと、1度に表示するレコード数に絡む機能を追加してきた。3年ほど前に、かなり混乱した感じになったのでリファクタリングをしたが、バグレポートをもらい、相変わらず怪しい部分があることに気づいた。ここで、根本的に直したいと思うのだが、今までの方法で欠けていたのは「ルールの明確化」だった。そこで、ルールを作って実装というか、リファクタリングをしたいと考える。

まず、現状(5.7+α)で、どんな要素が関連しているのかをまとめて見たい。レコード数に影響するUI要素は次のものである。

  1. ページネーション
  2. ポップアップメニュー(data-im=”_@limitnumber:コンテキスト名” の属性があるSELECT)
  3. Master/DetailのDetail側(navi-control=”detail”、詳細側なので常に1レコードにしたい)

コンテキスト定義のキーで、関連するものは次のとおりである。

  1. records
  2. maxrecords
  3. paging
  4. relation
  5. navi-control

さらに、関連するプロパティを挙げると次のとおりである。プロパティと言いつつ、オブジェクトは1つなので、事実上のグローバル変数である。なお、以下のプロパティの3, 4, 5は、getter/setter実装している。ローカルストレージ等を利用してページ移動してもパラメータの記憶をしたいためだ。

  1. INTERMediator.pagedAllCount
  2. INTERMediator.totalRecordCount
  3. INTERMediator.startFrom
  4. INTERMediator.pagedSize
  5. INTERMediator.pagination

これれらの仕組みをどのように解釈するかという問題である。

まず、INTERMediatorオブジェクトのプロパティについては、paging=trueのコンテキストに対してページネーションを動作させるためのものであるので、ここでは「ページングを特定のコンテキストに対して実施する」という決定がなされた後のものである。したがって、UIとコンテキスト定義の内容について、どのように解釈をすべきなのかを、まずは決めなければならない。ここを曖昧にしていたのが、バグが常に治らない原因と考える。しかし、基準も何もない。よって、「UIが自然かどうか」という観点で推測しながら決め事をしなければならない。

前提条件1:
ページネーション処理は単一のコンテキストのみ

この点は、異論はあるかもしれないが、複数のコンテキストにページングを配置すると、画面に複数のページネーションコントロールが登場して、混乱をしかねないUIとなる。適切なUI設計では複数のページネーションは不要と考える。これを前提とする。また、1コンテキストに複数のページネーションコントロールを用意するということも同様にやらないことを前提とする。

前提条件2:
Master/Detail形式のUIでは、ページネーションはMaster側にだけ適用される

MasterにもDetailにもページネーションが欲しいという声が聞こえてきそうであるが、それぞれを同時に表示することも仕組みとしては持っているため、ページネーションはMasterだけに適用させたい。Detail側にレコード移動の機能を組み込めないようにしたいのである。なお、どうしてもそうしたいと思う場合には、Master/Detailの機能を使わないで、Detailと同一内容のページファイルを用意して、普通にページネーションを利用できる。適切な対応策があるので、この前提条件はデグレードには当たらないと考える。

優先順位1:
そのコンテキストで取り出されるレコード総数はmaxrecordsを上回ることは絶対にない

この仕様の優先順位が高いとしたら、サーバー側での検証とレコード数の修正は必要であるし、通信直前に処理するなど、UIから遠いところで処理をしないといけない。

優先順位2:
navi-control=detailのコンテキスト場合、レコード数は常に1以下とする

ある時点でこの設定を入れた。優先順位を高めにして、他の設定より優先される方が、矛盾するコンテキスト設定してもうまく動く模様であるが、一方、間違いに気づきにくいということにもなる。

優先順位3:
ポップアップメニューがあればそれに従う

ポップアップメニューは、ローカルコンテキストに記録するのであるが、ローカルコンテキストのバインド処理は、ページ合成処理の最後の方にやっている。少なくとも、limitnumber:*の値の処理を、ページ合成前にもしなければならないし、本当に初めてページを開くときはローカルコンテキストがセッションに残されていないので、ノードを探る処理も結果的に入れておく必要がある。ここの改造は、コードの追加を伴う。

優先順位4:
recordsキーの値に従う

これは順当なルール。なお、relationがあるとレコード数の制限はなくすということを一瞬考えたが、関係レコードの上位3件だけ表示したいということもあると思う。結果的にrelationキーは考慮しなくてもいいのではないかと思う。

これらのルールで得られた「レコード数」を元にしてレコードを取得する。ページネーションを利用するコンテキストなら、ページネーションとの連動が必要になる。このページネーションとの連動部分が、コードとしてはうまく分離されていないのが現状である。上記のルールで決まれば、それに応じてページネーションを設定するという風に、レコード数とページネーションの処理順序を決めて、依存関係をシンプルにするようにリファクタリングを進める必要があると考えられる。すなわち、

方針:
レコード数決定プロセスとページネーション処理を分離し、レコード数の決定を先に行って結果を必要ならページネーション処理に渡す

ということになる。この方針で行ってみようと思う。

「Excelみたいに作ってくれ」という案件が失敗する理由

Excelは悪いソフトではないし、昔から使い込んできただけに、それなりに愛着がある。また、書籍もたくさん書かせてもらって一時はそれで食わせてもらっていたので感謝もしている。しかしながら、Excelの利用技術が結果的におかしな方向に行くのを目の当たりに見てきた。「ネ申エクセル問題」はその集約として非常に良いポイントを突いている。良し悪しを決めつけるのは簡単だが、問題はなぜそのようになり、なぜ是正できないかという分析だろう。「ネ申エクセル問題」としてまとめられた結果、ある領域についての理由と方向性がはっきりしたと言える。

業務システムの開発を請け負っていると、時々、「Excelみたいに作ってくれ」と言われる案件がある。要件がはっきりしていいのじゃないかと思うかもしれないが、これが大きな落とし穴になることもある。なるべく、そのような案件は断るようにしているが、作ってからメンテが大変だったりして、よくよく聞くと、Excelみたいに作ってもらいたかったと思っていたと言うこともあって、顕在化しない場合もある。

ある案件では、これまで、何十人レベルの人たちから毎月Excelのワークシートを提出していたものをWebアプリケーションにして欲しいと言われた。ちょっと複雑な経費精算である。Excelのテンプレートは、おそらく受け入れ側の都合を反映したもので、あまり分かりやすいとは言えないものと感じた。フィールドを全部埋めるのではなく、場合によっては埋まらないフィールドも多く、分類の違うフィールドがずらりと並び、状況によって入力したりしなかったりと言うことを入力者が決めるタイプだ。要するに、第一正規形を満たしていない。

それをそのままWebで作るとしたら、テキストフィールドがずらずら並ぶ。当然ながら、横幅は結構なものになる。状況に応じて必要なフィールドだけを出すようにすれば、スマホでも使えると考え、散々説得したが、「Excelみたいに作ってくれ」というところに常に落ち着く。仕方ないので、「Excelのように見えるだけで動作は違うけどいいでしょうか」と言って、それは納得してもらったはずなのである。

実際にExcelのように作ると言った時、その見かけを2次元セル的にやることと普通は思うかもしれないが、フタを開けると、「Excelのように」が指すポイントが人により異なることが判明した。つまり、これだけの文言では、要求定義にも、要件定義にもなっていない。単なる曖昧な表明にしかなっていないのである。

Webアプリでデータベースだから、レコードを作って入力すると言うのは、あまりに当たり前過ぎることなので、普通に実装したら、「画面を開いたら、最初からワークシートみたいになっているようにして欲しい」と来た。もちろん、そう言うライブラリもあるだろうし、レコードを複数作っておけば済むのだろうけど、ここで受け入れたら、本当にExcelそのものを作らされるのだろうと思って、それはできないと突っぱねた。最初からExcelと同一のものは作れないと言うことは明言し、データベースを利用して作ることも決まっていて、開発費用も決めたので、こちらの裁量がある。こちらとしても、要望が後から来たものは「費用の範囲に収まらない」と言う理由で断れる。そう言うわけで、当然ながら、「レコード追加ボタン」で対応した。

そこで引き下がっていたら、ドラッグしたらコピーするようにとか、式を入れられるようにみたいに要求が留まらないのではと危惧し、前記のような対応を取った。一応、システムは作成でき、想定外のことがあったもののメンテナンス開発でクリアし、今も使用しているようだ。しかしながら、「Excelみたいに〜は要件でもなければ要求でもない」というアンチパターンを実感したと言う意味で、悲喜交々な案件だった。それに、ワークシート的な見え方だと、多分、利用者は保存して添付する手間がないだけで、入力の手間はほとんど変わっていない。保存はないけど、ログインは必要になるので、面倒になったと思う人もいると思う。これは、つまりは今までワークシートを受け取っていた人だけが、集計が楽になるだけという非常に悪い設計の典型のようなシステムでもある。

「ネ申エクセル問題」での大きな教訓は、便利なソフトも使い方によって足かせになると言うことだ。よく、「紙での作業をそのままシステム化しても、効率が上がるわけではない」と言うことも言われる。まさに、ペーパーをExcelに置き換えても同じことが言えるし、それはExcelだけはないだろう。例えば、「LINEみたいなチャット機能もよろしく」みたいな要求は今だといろんな案件で出て来そうだ。しかし、そこで、思考を止めてはいけない。曖昧すぎて、本当に実現したいことが何なのかは、実はそれだけではコミュニケーションできないのである。馴染みのシステムを引き合いに出すのは、要求定義においてはきっかけに過ぎないことを常に意識すべきだろう。