思いついたとこから(2)

昨日の続き。
昨日書いたのは、部署がツリーになっているとき、主キーとしての部署コードと、
それに対する外部キーとしての所属部署コード、というカラムを持つテーブルを使えば、
ツリーをあらわすことができる。けれど、そのテーブルを見ただけでは、ツリーをあらわしたいのか
いったい何を表したいのか分からない、というところまで。
(なんかツリーの話ばっかり書いているけど、ツリーはデータ構造の例として使っているだけで、ツリーにこだわるわけではない。)

graphvizという、任意のグラフを視覚化してくれるツールがあるらしい。
http://www.graphviz.org/
これを使えば、ツリーであることが一目瞭然にわかるではないか、というコメントをもらった。
たしかに、1レコードが、1つの有向グラフに対応するということがわかれば、
あとは自明なデータ変換と、グラフ可視化ツールで、ぱっと見てツリーだとわかる図を出力することは可能だろう。
ただ、その出力された図を見ても、これが今たまたまツリーになっているだけで、任意の有効グラフ
が入りうるDBなのか、それともツリー状になるようなデータしか入るべきでないDBなのかは、やっぱりわからない。

では、ツリーかどうか分からない事のいったい何が問題なのか。
というところを今日は書きたいと思う。

現在では、エンドユーザーが直接SQLをたたいてRDBを参照したり操作したりすることは少ないと思う。エンドユーザーはなんらかのGUIベースのアプリを操作する。その結果、DBの内容が表示されたり、DBに対して変更が加えられたりする、ということになると思う。
つまり、そのアプリは、GUIを通して、Create-Read-Update-Deleteに相当することができるものになるだろう。
ここでは、ReadとUpdateに絞って考えたい。
ReadっていってもGUIなので、SQLのクエリー結果を表示とか、単純な表形式で表示するのではなく、
いかにもツリーであることが分かりやすいビューのほうがいいだろう、ということで、

hoge事業部
 ├─営業部 
 │ ├─営業1課 
 │ └─営業2課 
 └─第二営業部

こんなかんじで表示するとする。で、「営業1課」のところをマウスでドラッグして、第二営業部のところでドロップすると、

hoge事業部
 ├─営業部 
 │ └─営業1課 
 └─第二営業部
   └─営業2課 

こんなかんじになる、という仕様になるかもしれない。
そうしたら当然、営業部を、営業1課の上にドロップすることはできないという仕様になるだろう。

たとえばWindows XPのフォルダツリーを表示する標準のウィジェットはこんな感じになっている。
(あと+とか-ボタンをおして、ツリーの子孫を折りたたみ表示する機能もついている。)
ちょっと例がそれるけど、WindowsだろうがLinuxだろうが、今のところファイルシステムは、ツリー状になっている。そして、あるディレクトリを、自分自身のサブディレクトリの下に移動するような操作は、できないようになっている。Windows XPエクスプローラでそのような操作を行ったら、
「mydir をコピーできません。受け側のフォルダは、送り側フォルダのサブフォルダです。」
というエラー表示が出た。

もし、自分自身を自分の子孫にするような操作をしてしまうと、もはやそれはツリーとは呼べないデータになってしまう。
グラフで考えれば、部署のツリーやフォルダツリーは、「根つき木」に相当する。
ループになっている部分(閉路)が存在したら、それはツリーではない。
参考:
http://ja.wikipedia.org/wiki/%E6%9C%A8_(%E6%95%B0%E5%AD%A6)
http://ja.wikipedia.org/wiki/%E9%96%89%E8%B7%AF

別に、部署の構造が、数学的に特定の構造になっていなければいけないわけではないかもしれないが、普通「所属する」といった場合、

hoge事業部────────┐
│┌営業部┐┌第二営業部┐ │
│└───┘└─────┘ │
└─────────────┘

こんな感じの包含関係を想定しているはずだ。hoge事業部のなかに、営業部があって、さらにその中にまた同じhoge事業部があるような状況は、「所属する」という概念と矛盾すると思う。

それに、アプリケーションのほかの部分が、そのデータがツリー状になっていることに依存した設計になっていることは当然考えられる。その場合、もしツリー状でないデータが一度DBに入ってしまえば、それが原因で色々なエラーがでるかもしれない。
(OSのファイルシステムでも状況は同じだろう。ファイルシステムの実装は知らないので単なる推測だが、おそらくディレクトリ構造もファイルへのポインタを使った有向グラフのような仕組みでデータに収まっていて、変更操作があるたびに「自分の子孫が自分」であるような状況が起こらないようにチェックしているのだと思う。)

もし、SQLを直接叩いてDBを操作するような場合は、こういった矛盾がおきないように気を付けて操作するだろう。

ずいぶん長くなってしまった。
まとめると、部署ツリーを格納したDBを操作するGUIアプリとかWebアプリをつくるなら、
・ツリーであることがわかりやすいよう表示する機能
・ツリーであることを保ち続けるような変更だけを受け付ける機能
が、必要になるだろう。
イメージとしては、

  ビュー        SELECT
  ←┌────────┐←┌───┐           
人  │ツリーのイメージ│ │RDB│
  →└────────┘→└───┘ 
  操作         UPDATE

こんなかんじか。
つまり、アプリケーションプログラムが、
ツリーのように見せたり、ツリーのように振舞って、ツリーとして操作できる、
(逆にツリーに対してありえないような操作はできない)インターフェースを提供しているわけだ。これによって、エンドユーザーは、まるでそこにツリーとしての実体があるかのように感じつつ操作をすることができる。
もし、SQLを直接叩いて操作をしなければいけない場合は、アプリケーションプログラムが上でやっていたことを、頭の中で必死にやりつつ、つまりツリーであることを念頭において操作することを強いられるだろう。(そしてきっと使いにくいと感じるだろう。)

(ここでメンタルモデルとアフォーダンスという言葉を導入したい。
http://usability.novas.co.jp/glossary_04.html
http://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%95%E3%82%A9%E3%83%BC%E3%83%80%E3%83%B3%E3%82%B9
ここらへんは専門外なので言葉の使い方が間違っていたらご容赦いただきたい。つっこみお待ちしています。)

RDBに部署ツリーを表すテーブルを作っても、それを直接操作する人が感じて作るメンタルモデルは、おそらくツリーではなくて、ただのデータレコードの集合としてのモデルだろう。そして、自分の頭でツリー状(もしくは箱の包含関係でもいい)になっている実際の部署に対する知識と、レコードの集合を、必死に相互翻訳しながら操作することになるだろう。そんなことは現実的には面倒すぎるし間違いも多くなるので、アプリケーション部分で、ツリー状モデルをアフォードするようなインターフェースを用意することになるわけだ。
集合のモデルからツリーモデルへの相互変換を、アプリケーション部分が行っているとも考えられるだろう。

で、とりあえずここで言いたいのは、
業務Webアプリケーションの開発をしてみて、
このモデルの変換部分を毎回作るのって無駄じゃないか、と思った。
というか、この変換部分を、"命令的に"毎回プログラミングするのは大変だと感じた。宣言的にすっきりかけるべきじゃないのか。どうしたら宣言的に書けるだろうか?そんなことを開発しながら考えました。
息切れしてきたので今日はここまで。
(続く予定)