[DBデザイン#7] 実例から考える: 共通の概念を抽出する

前回の再掲になりますが、ここまでに、部署ごとに、その部署での関心ごとについて表にしていきました。ここで、フィールド名をつけるところまでを解説しました。

続いて、この一連の表から、共通の概念を持つデータを抽出します。厳密には、正規化の議論があって、そのルールに基づくという手法もあるのですが、ここでは会社のドメイン、部署のドメインについて、要求分析を通じてだいぶんと理解が深まったという状況をもとに考えてみましょう。

まず、ここでどの表にも「商品名」があります。であれば、商品名を共通化することで何かメリットは生まれないかと言うことを考えます。それぞれの表にも名前をつけることにしますが、加えて、商品名だけを独立させた「商品」と言う表も記述してみました。つまり、「販売明細」「製造管理」「カタログ在庫」いずれも、「商品」にある商品名の文字列を持ってきて表が作れるというものです。こうすれば、販売管理や製造管理において、何度も繰り返し登場する1つの商品名を記述することなく、商品名はシステムの中では商品の中に1箇所登場するだけにすることもできそうです。効率が良くなるかもしれません。

ちなみに、これが「商品マスター」と呼ばれる考え方の1つの理解の仕方です。効率良いことと、修正の確実性ということが言われます。例えば、商品名を間違って記録していたら、それが最初の図のような表の場合、表の中で一括置換をするなど、変更が重い処理になり、また確実に終わりそうにない処理にもなります。マスターで一元的に商品名を管理すると、商品名が違っていても、1箇所直すだけです。しかしながら、商品名の間違いってそんな頻繁にはないでしょうという気もするかもしれません。実際そうですが、実はマスターの役割は確実に変更できるということ以外にさまざまなことがあります。システム内では、データの複製をするような場合が出てきます。要求から、ここのフィールドは複製が必要と判断される箇所は時々出てきます。その場合でも、マスターの内容を複製することで、確実に名前を入力できると言ったこともあります。この辺りは、リレーショナルデータベースの理屈だけでは説明しきれない側面です。ただ、実際にある製造管理によって管理されている個体の商品が、商品テーブルをどのように参照するのかということは、実装上のルールがあって、それは次回に説明したいと思います。

「商品」という存在は、部署によって共通であり、商品名は、どの部署でも同様に利用できるという、ここでは表にまたがって存在するデータの共通性を見つけました。実際には、さらに販売先顧客名が重複しているなどの問題はありますが、それは追々見つけましょう。

ここで、概念が共通という意味では、日付もそうではないかと思いませんか? もちろん、販売日と製造日は、対象が異なりますが、いずれも、日付という共通の概念ではないかと思うところです。たまたま、この表では同じ日がなかったということです。では、日付を共通化するのかというと、おそらく多くのデータベースでは共通化していないと思われます。これはなぜなのでしょうか? 日付や時刻はいずれも3つの整数を持つような複合データであり、突き詰めて考えれば複雑そうです。この結論を先に言えば、日付や日付時刻といったデータは、データベースが持つ型として定義されているからです。言い訳っぽい理由になりますが、「商品」という型はありませんが、DATEやTIMESTAMPといった型があり、日付という単独の値、つまり、数値などと同じように扱えるから、多くの場合は別の表に分離しないということです。仮に別の表に分離しても、1フィールドだけです。商品の場合は、ここでは明示していませんが、おそらく商品名だけでなく、販売開始日など、共通の概念として「商品」に紐づく属性がフィールドとして付加されることになるでしょう。つまり、この会社における共通概念の商品を扱うために必要な情報を追加することになります。しかしながら、日付は多分日付だけなのだろうと思われます。

しかし、日付を別の表に分離しないと対処しづらい場合もあります。それは日付以外の情報が入っている場合で、例えば、祝日の管理が挙げられます。また、その会社特有の記念日(創立記念日など)もあります。そうなると、日付にもう少し意味が付加されてしまい、実はそれは「予定表」だったりして、「日付」という概念ではなくなってくるでしょう。予定表の日付ということで、ここでも日付という型があることで、単独フィールドとして扱えるというあたりが日付時刻についての特殊性とも言えます。

このように、とにかく「マスターを作る」というデータは1つの案件内では結構あり、いくらか経験を積めば、大体いい感じに設計できると思います。しかしながら、そこには、表ごとに異なる「商品」と、表を通じて共通の「商品」の概念があって、後者がマスターになるということを理解しておく必要があります。ところで、共通というのは実は抽出時に考えることで、運用上はそこまで厳しくありません。商品の販売単価は、おそらくはここでは営業部門だけが使いたいでしょう。では、それは商品マスターに入れるのかというと、実は入れることが一般的です。これは、他の部門では無視すればいいというのがまずはざっくりとした見方なのですが、より重要な概念があります。単価は、その共通概念である商品1つについて、1つの値が割り当てられる属性であるとみなすことができれば、それは商品マスターのフィールドの一つにすればいいのです。そして、必要な表では使い、不要な表では無視するというのがデータベース利用のポイントになります。ここで、「商品1つについて1つの属性」、つまり、1対1の関係であることをしっかりと考え、確認しておく必要があります。実は、部門午後の表のフィールドは、その表1行の概念に対して、1対1の関係が成り立っているものが並んでいます。作ってある表はちょっと恣意的ではありますが、こうすれば、整理されているとも言えるでしょう。

次回は、分離した表から必要な情報を持ってくるというリレーショナルデータベースの基本的な考え方を説明しましょう。

[DBデザイン#6] 実例から考える: 表で考える

前回までに、単純な「商品」という単語でも、状況によって異なるものを示すことを説明しました。実際の開発では、これと同じように、たくさんのユビキタス言語を認識して、それらを分析し、必要な仕組みを考えていくことになります。その時に有用な考え方が、まさに「表」です。それぞれの部署で記録したいデータを実際に表に作ってみます。場合によってはすでにその部署で表が作られている可能性もあります。しかしながら、もっと大雑把なデータしか得られないかもしれません。これは利用者側作るものではあるのですが、表の内容が無茶苦茶でないかなどはやはりエンジニアリング的な視点でチェックしないといけません。表の内容が途中から変わってしまっているような表の利用は要注意です。

それで、ここでの実例でできたおもちゃロボットメーカーについて、ちょっと恣意的ですが、システム化したい業務についての根幹となるデータを表にしてみます。現実にはこんなに単純明快ではないとは思いますが、考え方のサンプルということです。

現状、多くの仕事はExcelが絡んでくるので、中途半端にシステム化されていることが多いでしょう。特にExcel自体を「便利に使っている」ような職場では、システム化と言っても、ヘタをするとExcelの再発明を求められてしまうことも、結構あります。表にするのですが、ここで何を求めたいかのかというと、1レコードに相当するものとして何を見るのかということです。実は営業部門が一番わかりにくいです。営業については実際にはリレーショナルデータベースの典型的な例でもあるので、少し先に詳しく説明しますが、あえて「営業は、紙の納品書を作っている」くらいの感じで考えていただければ、いつ、どの顧客に、どの商品をいくつ売ったのかという情報を記録することで、月末にまとめて請求ということができるかと考えます。ここでの表は、納品書の明細が1レコードになりそうです。言い換えれば、それより小さな単位がなさそうであるというくらいの根拠です。商品や顧客は当然ながら表には繰り返し登場します。

製造部門はある意味わかりやすいです。作った箱入り製品1つずつを管理したいのですから、1レコードは、1ボックスということになります。マーケティング部門は、とりあえず製品カタログの残り部数を管理するとしたら、1レコードは、まさにマーケティング部門が把握する1商品ということになります。

なお、このままだと、データベースの設計に持ち込めません、ここからまだやるべきことはあるのですが、重要なことは、実際に現場で発生しているデータを記述するということです。ここで、単に曖昧に記述するのではなく、表の形で頑張って記述するということです。全部でなくても構いませんが、少なくとも、表の数行分を記述してみることが必要と考えます。もっとも、そういう表の形になったものを頭の中で再現して、何も書かずにできる人もいます。設計が得意な方はそれができるかもしれません。しかしながら、こうして作り込んで行くコアな考え方が正しいかどうかを検証するのは設計が不得意な人かもしれません。記述して見える化するという意味では、表は出発点としてはみんなが理解できるものとも言えるもので、大変有益でしょう。

ちなみに、ここではそれなりに整理してしまっている感じですが、空白があるのは当然としても、同じ列に途中からデータの種類が変わってしまうこともあります。その場合は列を分けるなどします。つまり、列で分類するという言い方もできるでしょう。そうしているうちに、列に名称をつけることができるようになります。その列にあるデータの代表的な名前をつければ、逆にその列に何のデータが入れられるのかも理解しやすくなります。もちろん、それがすでに紹介したフィールド名になります。

フィールド名の命名ルールは結構人それぞれですが、少なくとも、「代表名」であるというのはほぼ全ての方に同意いただけるでしょう。また、データベース上では同一のフィールド名を複数つけることは許されていませんので、異なるフィールド名にしなければなりません。また、長すぎると式を書いたりするような時に結構面倒です。ということで色々悩みます。以前に大変分析が困難なデータベースにあたったのですが、どう困難かというと色々あるのですけど、「適用_編集用」と「適用編集用」みたいなフィールドがあって、フィールド名で判断が極めて困難という状況でした。このようなフィールド名だと、「フィールド1」「フィールド2」と付けられているのとあまり変わりません。さらにその時にはオチがあって、それらのフィールドの前者はPDF出力時、後者は印刷時に使われるというこれまたクイズのような(パズルではなく!)データベースでした。

いずれにしても、フィールド名はよく考えて、統一的な名前で、かつそこに入ってくるデータが連想しやすいものにするのが言うまでもありません。例えば、「平均値」と言う名前のフィールドをつけたけど、そこには月間の平均値が入っているとします。しかし、やっぱり週の平均値も欲しいので「平均値_週間」フィールドを作ったとします。そうなると、「平均値」ではなく、「平均値_月間」フィールドにするのがベターな方法ではあるのですが、そこをそのままにするエンジニアが多く、後からデータベースに関わる人たちに混乱をもたらしてくれます。もちろん、プログラム内にフィールド名が文字列で記述するような場合、下手にフィールド名は変えたくないと思うかもしれませんが、一括置換すればいいことです。また、FileMakerでは基本的に気軽にフィールド名は後から変えられます。今、この平均値が売上だったとして、個数の平均値が欲しいとなると、どうしましょう。この集計した結果のフィールドは「売上_平均_月間」のように、処理対象、処理方法、グループ化基準といった情報が、どのフィールドにも、同一のルールで、同一の用語で入っていないと、分析が辛くなります。日本語の用語だと思っていたら、途中から突然英語になってしかもカタカナだと(「売上_アベレージ_年間」みたいな)何かのギャグか嫌がらせかと思ってしまします。用語のルールも重要ですが、自分で決めたルールを全体にわたって最後まで踏襲するということがもっと重要なことになります。

ところで、フィールド名自体に「データ」的な性質の文字列が入るのは、ちょっと違和感あるものの、ある意味便利なのかもしれません。例えば、アマゾンから購入したかどうかを記録する「Amazon購入」フィールドはどうでしょう? では楽天やモノタロウと購入先を増えてきた時にそれぞれ別々に管理したければ、フィールドを増やすしかありません。通常、そうなると、「購入先」と言うフィールドに文字や数字で区別して購入先を記録するのが妥当な気がします。となると、フィールド名は抽象度の上がった名称であるとも言えて、実はフィールド名にデータ(この場合は「Amazon」と言う文字列がある意味ではデータです)が入ることはないと言うことも言えます。しかし、単にAmazonだけ特別で管理したい場合には、「Amazon購入」フィールドは、わかりやすいので悪くはないと思います。この問題は、結果的に最後まで作ってみないと正しかったのか、正しくなかったのかはわからないものの、ルール的には一概に決められないと言うことでもあります。

そういえば、フィールド名に表の名前を入れるかどうか問題もあります。これに関しては入れないのが基本だと思います。入れるとしたら、全部のフィールドに入れないと妙にも思えるからで、それは非効率的です。ところが、「名前」と言うフィールド名は、それだけ単独あってもわかりづらいです。そのような場合は「商品_名前」にするという手もありますが、SQLの世界では「テーブル名.フィールド名」の記述が随所にできるので、表の名前はフィールドになくても、表現は可能とも言えます。ですが、極めて一般的な名称については、やっぱり表の名前をつけたり、あるいはそれを連想させる名前をつけたくなってしまいたくなります。これは感覚的な問題です。加えて、あちこちのテーブルに「名前」フィールドがあるのも、混乱の元かもしれません。

ついでに、フィールド名に誤変換や間違えたスペルはなるべくやめましょう。データベースを分析しているときにストレスが強くかかります。見る度に、何だか設計・分析とは違うスイッチが入るのですよ。スペルは今時の開発ツールではみてくれますが、誤変換は自分で見つけるしかありません。データベース全体に渡って「精算」であるはずが「清算」だったものを見たことがあります。レイアウト上は流石に利用者が指摘したのか「精算」になっているのですが、フィールド名が全部「清算」でした。

次回は、この表にした結果をもう少し分析してみましょう。

[DBデザイン#5] 実例から考える: “商品”に注目する

前の記事では前提となる会社の業務を紹介しましたが、どの部署にも「商品」という単語が出てきました。データベースに慣れているみなさんは「はいはい、『商品マスター』でしょ」と思われるところかもしれません。もちろん、商品マスターは作るのですが、なぜ商品マスターが必要なのでしょうか、そして、それだけでいいのでしょうか?ここで、「商品」というキーワードをより詳細に分析してみます。

次の図では、それぞれの部門に対して、「商品とはなんでしょうか?」と質問した結果だと考えてください。実際、要求分析をするときに、そんなダイレクトな質問はいろんな意味で(機会やあるいは適切な担当者と話ができるのかなどを含めて)無理でしょうし、しかもちゃんと答えてくれるとも限りません。通常は、いろんなインタビューをもとに、分析者がこうではないだろうかと考えるのが一般的かと思います。なお、前回は経営者が出てきましたが、言っていることが曖昧なので、ここから先は3部門だけに絞りましょう。

営業部門にとって、商品は売っているものです。製造部門は作っているものです。この辺りは明確でしょうけど、どうもマーケティング部門にとっては、商品というのは何なのかということがどうも曖昧で、具体的に言いづらい感じです。おそらく、状況によって変わるのでしょう。

ここで、部署ごとに、商品をどのように扱っているのかをみてみましょう。それを示したのが次の図です。

まず、製造部門は、製造した商品1つ1つをどうやら管理したいようです。つまり、商品の箱1つ1つが対象になります。一方、営業部門は、商品の箱があることは理解しているでしょうけど、商品そのものを集合的に扱います。しかも、製造部門は、商品の物理的なことを考えなければなりませんので、在庫ということまでもしかして考えているかもしれませんが、営業部門はおそらく商品という存在を移動させているという考えが支配的ではないでしょうか。つまり、営業担当者は、実際に自分で箱を手に取って顧客に届けているというよりも、伝票を書いて、ロジスティックスに依頼をするわけで、実際に商品そのものを目に見ていることは滅多にないようなのがいわゆる営業という活動ではないかと思われます。マーケティングに至ってはなんだかわかりませんが、インタビューでどうやら商品カタログの管理くらいは必要なことがわかったという程度です。

同じ商品という呼び方をしているのに、このように部署によって実は扱う概念が大きく変わってきます。当然、それらを一緒くたにするのは問題があると考えます。部署ごとに違いがある一方、共通の概念もあります。例えば、商品名は社内で統一的に扱われているはずです。一方、商品の単価が業務上必要でしょうか? 販売部門は伝票を作成するのに必要そうです。一方、製造部門は単価が存在しても、業務上は通常は使わないでしょう。一方、マーケティングはおそらく単価情報は、業績等をチェックするような場合に使うかもしれません。商品1つずつにつけるシリアル番号はどうでしょう? 製造部門には必須かもしれませんが、営業部門には興味のないデータです。このように、共通のものと共通でないものが存在するのです。

ドメイン駆動開発の世界では、こうした概念を「ユビキタス言語」として捉えます。ある特定のコミュニティで通用する言語なのですが、つまり、ここでは「営業部門言語の商品」と「製造部門言語の商品」に若干の違いがあると考えて、これらの部門間では異なるユビキタス言語が使われていると考えます。同じ言葉で違う概念があるということは、ドメインつまり「業務そのものの定義」が異なるという考え方です。実は、商品というよく似た言葉でも、このような違いがあるものの、社内で働いていると、なんとなくそういうものだということでドメインが違うことは気づきにくいものです。まさに、第三者が設計するときに、そうしたドメインの違いを見出すことができ、業務の整理が進むということが期待できます。もちろん、分析者や開発者は、顧客のドメインを理解し、ユビキタス言語を使いこなせるくらいになっていることが理想です。

ユビキタス言語は、そのドメインのモデルの基礎になるものです。言語を構成する概念を整理したものがモデルとして利用できるでしょう。ユビキタス言語はモデルが表面に出てきたものでもあります。私たちは、ドメインのモデルを知りたいのです。そのモデルをデータベースに実装すれば、システムは成功するはずです。モデルを探るのが要求分析であり設計です。その手がかりがユビキタス言語にもあるということです。

ちなみに、1つの言葉が異なる概念を示すだけでなく、異なる言葉が同じものを指す場合もありますし、1つの単語が状況によって異なるものを示す場合もあります。最後の例は1つの単語が同一職場の同一業務で状況によって違っていたのですが、よくそれでトラブル発生しないもんだと思ってしまいます。たまたま問題にならなかったのでしょう。言葉というのはコンテキストを引き連れて登場するので、区別は可能なのかもしれませんが、外部からその世界に入ってきた人には面食らってしまう事象です。こういう事例があった場合は、ドメインをまたがって用語の整理をするのが理想なのですが、なかなか業務の上で使い続けている言葉は変えてもらえないのが実情です。

ドメイン駆動開発といえば、現在はマイクロサービシズで話題になっていますが、ドメイン駆動開発の方が先に提唱されていた概念です。マイクロサービシズでは、どんなサービスに分割をするのかというのが設計上の大きな問題です。ここでサービスの分割を考えるとき、ユビキタス言語の通用する範囲を重視するという考え方があります。これを、非常に雑に考えると、要するに部署ごとに別システムであり、部署間の動きが必要ならそれはシステム連携だろう、そしてシステムは1つのマイクロサービスであるとも言えるとも言えます。実は、マイクロサービスシズの勉強を一時期頑張っていた時期があり、いろんな資料に当たったのですが、あっさりと「マイクロサービシズは、部署ごとに分ます、以上」と説明されているものがありました。その資料ではドメイン駆動開発やユビキタス言語といった抽象概念はすっ飛ばしていました。あらあらと思いつつ、非常に大まかに言えばそういうことで、間違いはないかもしれませんが、会社の部門構成が最適化されていないと色々苦しいだろうなと思ったりもします。しかし、最適化されていない会社ってきっと破綻するでしょうから、システム作っても早晩使われなくなる? ということで、部署でサービス分けるというのはあながち悪いサジェスチョンではないと思った次第です。そこで、ここでの実例も、部署を単位にしてみました。

商品のような基本的な単語でも、そのドメインによって役割が違うようです。実際、みなさんの会社やあるいは扱った案件ではどうでしょう? 他には「在庫」なんてどうでしょう。在庫と言ってもいろんな概念があります。会計的には在庫は金額ですが、倉庫で働く人にとってはそこにあるたくさんの段ボールだったりします。商品や在庫などはどの会社でもあるようなものなので、ある意味では扱い方はある程度はわかっているようなものでもあり、経験則も適用できるかもしれませんが、むしろ、わかったつもりになるのは危険で、そのドメイン特有のルールや扱い方がないかを常にアンテナを張るくらいの気持ちがないと、後から気づいて大きく出戻りが発生するということにもなりかねません。商品や在庫だけでなく、部署ごとに違う、あるいは担当者ごとに違うような概念がないかを見つけてみるのも良いでしょう。また、部署で違うだけでなく、部署を横断するようなドメインの存在も見えてくるかもしれません。要求分析以降は常にドメインやそこでのモデルを意識する必要があります。

次回は、異なる概念を表を作って捉えるということを説明しましょう。

[DBデザイン#4] 実例から考える: 前提となる業務

今回から、数回に分けて、データベース設計をするときにどこに注目するのかを考えることにします。一応、「分かりやすい」業務を架空の会社でおこなっているという想定です。もっとも、そういう架空の設定そのものが、いかにも記事をそれらしく見せるためのわざとらしい前提に見えるかもしれませんが、やはり現実の世界そのままはなかなか複雑で理解しづらいですし、現実には「要求が不明あるいは曖昧である」という問題との対峙が非常に難しいところになります。なので、問題を単純化したいと思います。

データベース設計の1つの肝は、「1レコードに相当する単位あるいは概念の特定」だと考えます。そのために、どんなフィールドが必要かを集めて分類などを行うと思いますが、1レコードの特定が設計の1つの目標になります。そこに至るまでに、表にして考えるということをまずはこの実例で見ていっていただきたいのですが、表が出てくるのは次回以降になります。まずは、ロボット製造販売を行うような会社がありますという前提の説明をしましょう。あえて非現実的にするために、おもちゃロボットがなぜかヒットしたという会社を考えます。画像素材は誰が見てもご存知のイラストやさんです。ありがとうございます。

まず、この会社には営業部門があります。製造したロボットを、卸売や大手小売業者に販売します。営業部門では、「ロボットさんま1号 x 24個」のように、この会社の商品を、通常は複数個まとめて出荷するという作業を行います。営業部門が考える関心ごととは、ともかくたくさん販売して、売上を伸ばすことです。また、季節性のある商品や何かイベントなどでの売上の波が来そうな場合に、別の部門との折衝を行なって在庫確保などもしているかもしれません。

一方、この会社には製造部門も持っています。製造はどうやら外注していないようです。製造部門は、当然ながら、商品を1つずつ作ります。まとめてどこかに在庫しますが、どうやら出荷計画を作ってそれに基づいて製造をするという大きな流れを持っているようです。この部門の関心事は不良品がないなどの製品品質を高めることが大きいようです。

さらにマーケティング部門もあります。マーケティング部門なので、現状の商品を訴求するためのさまざまな活動が行われていますが、一番大きなミッションは新たな市場を作るということを経営側から命じられています。この部門にとっては、商品1つ1つは関心ごとではなく、商品という大きな概念そのものを扱っていると言えるでしょう。

もちろん、この会社には経営陣がいます。もちろん、経営陣は会社の収益を確保し高めることが一番の関心事になりますが、どうやらこの会社はハイテクな商品を作っているように見えて、情報システムは部門ごとに作ってしまっているようで、連携はしていないようです。

このような会社で、部門にまたがって使える業務システムを設計するということが発生しました。ということで、設計を進める上で何を考えるかということを考えてみたいと思います。これくらいの内容なら、すぐに作れるよとおっしゃる方もいらっしゃるでしょうけど、そういう方が頭に即思い付くような「テーブル構成」がどのように導き出されるのかを、「表を作ってみる」というアクションから考えてみたいと思います。

[DBデザイン#3] 表のモデル

昨日このポストを書いた後、サーバーのメンテを長くやってないなと思ってアップデートをかけたら、一気に起動しなくなってしまってデータが消えてしまいました。ある程度はバックアップしてあるので、メッセージは一昨日分まで、画像などは2019年までしかなかったです。まあ、でも、Ubuntu Server 20.04に入れ替えて心機一転です。ただ、同じ内容を書いても、日が変わると内容が違って来そうで、いいのか悪いのか、ともかく昨日書いた内容を思い出しつつ、変化しながら書きます。

データベースの設計を行う上で、まず、データをどのように見るのかという基本的なことで、表を出しました。表に対して、レコードやフィールドといった名称を定義しました。多くの方が表計算ソフトを使っているので、表は便利かつ有用であるというのは理解はしていると思いますが、それが「なぜ?」を突き詰めると実はなかなか難しいということも説明しました。ほとんどの方が、表にまとめて、あるいは表にまとまったものを参照して、何か目的を達したり、より効果的に作業ができるなどの成功体験があるということがあるでしょう。そうした体験から有用性を理解しているということが、ともかくの理由でした。

なお、数学的な世界では、集合の仕組みを利用して、表そのものをきちんと定義するということは可能であり、いわゆるデータベースの教科書ではそうした集合論をベースにした表の定義が最初の方で説明されています。いきなりその辺りで挫折する方も多いかもしれません。また、そうした高度に抽象化された世界が実際のデータベース設計にどこまで役に立つのと問われると、最初のとっかかりとしてはやはりきついと思います。データベースの設計をある程度理解した時、そうか、基本は集合だったよなということを思い出すことで理解が深まるということもあります。

いずれにしても、まずはデータを表として記述することで、ある程度コンパクトに、そして存在するデータを余すことなく記述できます。つまり、Excelでなんでもできるでしょうというあたりの考えに近いかもしれません。つまり、表はそれで完結した世界です。しかしながら、私たちは書ききれないほどの大量のデータを扱いたいのでデータベースを使おうということがあります。この時、データベースは表形式にデータを扱いものの表の縦横を自由に使うのではなく、まずは行に相当するレコードに区切り、レコードはフィールドとして分割され、フィールドにデータを入力できるということを説明しました。その状況をツリーのように記述できます。ここでの線は、導出可能であるということを意味しています。つまり、あるレコードが決まれば、そのレコードからフィールドの値が取り出せるということです。プログラミング言語で処理をすると、実際にそうした側面が強く出ますが、ここではモデルの段階から表はレコードの集まり、レコードはフィールドの集まりであるということを意識したいと思います。

このように、表は階層的なツリー図で表現できるということであれば、表とツリーは同一のデータを示していると言えます。ただ、ツリーの方が実際に描画するのは大変そうですが、概念としては同一のものを示しています。

ここで、具体的にデータが存在するのはフィールドです。レコードもデータの集まりではあり、要するにフィールドの集合ではありますが、単一のデータを持つわけではありません。その意味では、レコード、そして表自体も存在がちょっと抽象的になります。それをまずはあえて楕円形のオブジェクトで書きます。レコードには名前等がないので、便宜的にレコード1などと数字付きで書きますが、表そのものには「住所録」といった名前があります。

ここで、表自体の設計情報を記述する場合、もちろん、全データを書くというのは設計図としては複雑すぎて意味がありません。設計、つまりモデルは、興味のある対象に絞った情報を集めたものというのが原則です。それを、必要な情報に捨象するといった言い方をします。つまり、「どんな表なのか」ということを如実に示す情報が欲しいわけです。

ここでの表を見てみると、まず、どのレコードも同じフィールドを持っています。そのフィールドの実データではなく、フィールドの名前を使って、どんなフィールドが存在するのかを記述してみると、次の図のようになります。どのレコードからも、同一のフィールドが存在するので、全レコードについて記述する必要はなく、レコードは1つだけで良いでしょう。

ここでさらに、表はレコードの集合であるということが決められているということでああるのなら、レコードが存在しますということをモデル上に表現する必要はないとも言えます。ただ、「しない」わけではなく、そういう表現をすることもありますが、ここではシンプルな表はみんな同じ考えで見ているとして、レコードの存在はあえて書かなくても同じフィールドを持つものが複数存在するということを前提とします。すると、残ったものは、表の名前と、フィールド名です。これらを、ちょっとわざとらしく、ボックスに書いてみると次のようになります。

これは、ER図のエンティティのようでもあり、クラス図のクラスのようでもあります。いずれにしても、こうした記述が住所録を管理する表の設計として認識できます。元は表ですが、それを階層的に見た上で、必要な情報だけを残すと、このようなものができます。データベースの設計者は、このボックスを見ることで、実データが表として展開されて、たくさんのデータが入るという状況を想定し、それが実際のシステムの用途に合致したものかどうかを検討しながら設計を進めるということができるのです。

ここで、命名が「住所録」といった集合的なものになっている点にちょっと気に掛かる人もいるかもしれません。ここはある意味好みの問題なのかもしれませんが、表に対して名前をつけているのか、レコード1つに対する名前なのかで分かれるところだと思います。データベースの設計では、レコードとして実現されるので、表とレコードは最初から組み合わされているので、ER図のような世界に入り込めるのです。これがクラス図であれば、「住所録」ではなく、「顧客」などの単一レコードを示す名称をつけ、さらに「顧客リスト」といったクラスを考えて、顧客リストは顧客の集合、つまり表とレコードの関係のような記述をする方が落ち着くと思われかもしれません。クラス図の方が抽象度が高いので、いろいろな記述のバリエーションは考えられます。これは、結果的には設計者がどう決めるかの問題です。少なくとも、1つの設計の中で、ボックスの粒度をどう扱うかを統一した上で、そのルールが他の人にわかるようなコミュニュケーションをしているかどうかということです。

私自身は、クラス図で書くことが多いのですが、いきなりデータベース設計するのではなく、まずはドメイン分析からスタートして詳細化してデータベース設計に持ち込むので、その結果クラス図で記述する異なってしまいます。もっとも、使っているツールのastah* professionalは、クラス図からER図を作成できるので、単にツールで書き換えればER図になります。また、クラス図で記述すれば、オブジェクト図を書くことができます。オブジェクト図はクラスに基づくオブジェクトであり、つまり実データが入ったボックスを記述できます。その仕組みにより実際のデータを当てはめてみて、それが意図した状態を表現できているかということを、検証することが可能です。複雑なデータであれば、そうした設計から実データ展開した検証をしたくなりますが、クラス図とオブジェクト図で、作業が可能です。クラス図でスタートしたら、結果的にクラス図で記述したデータベース設計になり、自分としては違和感ないのですが、怪訝な顔をされることもありますね。

次回からは、架空の会社の業務を想定した上で、同じ名前の対象物に対して、部署ごとに管理したい内容が違い、結果的に違う表が必要になるというお話を何回かに分けて行います。

[DBデザイン#2] データベースのモデル

データベースの話を進める上で、基本的な概念として何をベースに話をスタートさせるかをきちんと決めておきましょう。用語の整理というよりも、基本概念の整理がまず必要です。以下の図は、どこかで見たことがあるようなと思われる方もいらっしゃいますが、大して難しい概念はないと思います。まず、これを見て、直感的に、住所録、つまり複数の人の名前、住所、電話番号を「表にしている」と見てもらえると思います。

この表がデータベースのごく基本的なモデルとなります。表にまとめることで、人間がデータを参照したときに理解、あるいは活用がしやすくなるということがあります。データがを混沌と記録していたとして、記録はできているとしても、そこから特定のデータを探したり、データの傾向を求めるということは大変なことだったり失敗したりということになります。一方、データをきれいに整理しておけば、容易に検索したり、確実に集計したりということが期待できます。その整理された形式が表です。

ここで、Excelなどの表計算ソフトを引き合いに出して、「表は良い」ということを議論することもできるでしょう。表にしておくことで、オーバーな言い方ではありますが、多くの人が成功体験を積んでいるはずです。色々な利点が見出されている表というのものをモデルとして考えるということが出発点になります。もっとも、それは鶏と卵の議論ではないかということも言えるかもしれません。リレーショナルデータベースの理論が最初に発表されたような時期だと、表というモデルを考えること自体は単に1つのアイデアであり有用性までは実証されていないとの見方もあったようです。後々、ソフトウエアとして実装された上で、リレーショナルデータベースの有用性が証明され、理論と実際が相互に発達してきたという経緯もあります。

結果的に「まず表で始めます」となると、表が便利なのは常識だろうということで理由が吹っ飛んでしまいますが、表が便利なことを突き詰めて考えるのはやはりかなり難しいとも言えます。感覚的に、理解しやすく、しかも、大量のデータを扱えそうだというあたりの考えが出発点にあるということは、それほど不自然ではないと考えます。

さて、表とは言ってももう少しその構造を細かく見ましょう。非常に重要なことは「1人の人が1行」ということです。つまり、この行のことを「レコード」と呼ぶとして、1レコードが何を表しているのかということが非常に重要です。実は、これが決まればデータベースは実装可能ですが、1レコードを示すものが揺らいだり、間違っていると、データの記録がうまくできません。このことは改めて説明しますが、ここでは住所録は1レコードが1人であるということに注目します。そして、1人のレコードには、複数の「フィールド」があります。フィールドには「フィールド名」がつけられています。

1人の人の住所録を管理する上で、ひたすら名前や住所を書き並べても良いのですが、よく整理された状態というのは、一定の基準で情報が分離され、整頓されているということであると言えます。基本的に1人の人は、1つの名前があって、1つの住所があるということにここではしてください。だとしたら、名前と住所をごちゃ混ぜに記録するよりも、名前の枠、住所の枠で分離しておく方が、整理されたように見えます。つまり、ある特定の「属性」の情報「だけ」が取り出したりあるいは入力しやすくなっている方が都合が良いということが言えるはずです。もし、ごちゃ混ぜだったら、その混沌としたデータから一部分のデータ(例えば、名前だけ)を取り出すことが大変だったり、あるいは不可能だったりします。よって、フィールドに分離分割され、フィールドに実際のデータを入れておくという仕組みが作られたわけです。そして、フィールドという単位で処理をすることにより、うまくいけばデータの種類に関わらず、必要なデータだけがポンと出てくるということができるはずです。

ちなみに、レコードについては、行、ロー、タプルなどの言い方があり、フィールドについては、列、カラム、属性、アトリビュート、プロパティなどの言い方もありますます。一部のコミュニティではその言い方を間違えると白い目で見られるということも以前はあったようですが、表形式でデータ全体を考えるという概念上は概ね同じものを指しています。一連の記事では、レコード/フィールドという呼び方で進めます。

表計算ソフトだと、縦横にセルが並んでいるのですが、見かけは同じ表でも、データベースでの表は、まず、表をレコードごとに分割されていて、そのレコードにフィールドが存在するという見方をするのが良いでしょう。表の一部分を自由に扱うということもある意味はできますが、階層的に記述したら、以下の図のように、レコードの方が上位概念になります。この図の線は、正確には「導出可能」という意味です。ある表である「住所録」があるとき、その住所録からレコードに辿り着き、特定のレコードからフィールドのデータに辿り着けるというのが導出の具体例です。実際にそういうプログラムを記述できると言っても良いでしょう。視覚的にいえば、表をまず横方向にスライスして、そのスライス1つ1つについて、縦方向にスライスすることで実データに辿り着くという感じです。

階層の図(「ツリー」と呼びましょう)ではフィールド名は省略していますが、最初の表と、この階層図は、概念的には同じものを示しています。同じとは何か? ここでは「同一データ」と言っても良いでしょう。「表とツリーは同一である」ということは理解しづらいことかもしれませんが、一方で当たり前すぎて意識していない人も多いかもしれません。住所録は表で記述できますが、ツリーでも記述できるので、同一なのです。もちろん、表のほうがコンパクトで扱いやすそうです。ツリーが優れている理由はここでは明確にはありませんが、ツリーは関連性を明示可能です。つまり、表/レコード/フィールドという階層を明確に示すことができています。

ツリーを見ていると、フィールドの集合がレコードであり、レコードの集合が表であるということが明確にわかります。ここで、フィールドだけが具体的なデータを記録できていて、レコード自体はそのフィールドの集合という位置づけになります。なので、もちろん最初のレコードを「鈴木一郎」という名前で呼んでもいいのですが、レコードを特定する情報はここでは明確ではないので、便宜的に「レコード1」と記述しています。なお、レコードの特定の問題については、今後、色々な視点で説明をすることになります。

集合(set)といえば数学、数学といえば「嫌い」という人も多いかもしれませんが、集合論の真面目な議論に入らなくても、日常的な感覚の範囲では頑張って理解しましょう。ただ、集合と言うと深い議論があって、その1つは「集合には要素に重複はない」と言う定義です。集合の基本的な定義は「お互いに区別できるものの集まり」となっています。住所録の場合、重複したデータ、つまり全く同一の2つの行があった場合、用途上それは2つ存在している必要は全くなく一方は消したりないものとして扱うことは問題ありません。なので、レコードの「集合」が表なのです。また、フィールドについても、1つしかない名前を2つ以上のフィールドに入れたところでそのうちの1つしか必要ないので、フィールドの「集合」がレコードになるのです。この辺り、現実と数学の定義がよく合います。集合の考え方がリレーショナルデータベースの理論の基礎になっているという点は決して無視できない時事です。ここでは細かく議論しませんが、集合の要素は順序は問わないという定義もやっぱりデータベースの表といろんな意味でよくマッチングします。ちなみに、今回は数式は出しませんでしたが、先々では数式も出ると思います。その方がわかりやすいこともありますので、その時はなるべくわかりやすく説明するように心がけますが、数式があっても驚かないでください。

数学としての集合は有名ですが、その仲間のようなものも数学で定義されています。要素の重複を許すものをバグ(bag)あるいは多重集合(multiset)と呼ばれています。また、重複を許しつつ順序も情報として持つものを列(sequence、list)と呼ばれています。さらに重複は許さないが順序も情報として持つ順序集合(ordered set)もあります。これらも集合を基にした数学の理論は展開されています。ですが、プログラムができる方は、むしろ配列などとして理解されており、物理的な意味でデータを実際にこの形式で扱っているとも言えるので、抽象数学よりも具体的な世界での理解はされているのではないかと思います。数学に興味のある方はその辺りも書籍などを当たってみると良いでしょう・・・と言いつつ、この種の数学の書籍はかなり気合いと時間をかけないと理解に至らないのは確かですね。

次回は、表をツリーにしたことで、ER図の一部の定義に到達できることを説明しましょう。

[DBデザイン#1] データベースデザインについて書く

データベースデザインを、ここでは、「リレーショナルデータベースでシステム開発等を行う場合に、データベースのスキーマ、つまりどんなテーブルやフィールドを用意すれば良いのか」と言う問題であると定義します。データベースそのものの設計ではなく、データベースを利用する場合の問題です。RDBで開発をしている人は、どのように設計をすればいいのかと言うことが大変難しい問題であることはよくご存知でしょう。FileMakerを使って「簡単にテーブル定義ができます」となっていても、操作が簡単なことで設計が適切にできるかどうかは定かではありません。単純なシステムならともかく、今時は手元でやっている複雑怪奇でどうしようもない作業があるからコンピュータにさせようと言うのが動機としては一般的です。したがって、目的とするシステムを実現可能なデータ構造も複雑化しがちです。そう言うことで開発をしようというと、ベテラン、エースあるいはアーキテクトなどと呼ばれる専門家などがスキーマ設計を行うことになります。彼らは、多くの事例にこれまで取り扱ったという経験があり、複雑でどうしようもなさそうな要求をうまくシステムが飲み込んでしまうようなスキーマを作ってしまいます。

そうしたスキルを得るにはどうすればいいか? 経験を積むと言うこともあります。しかし、経験を積んでもそれができない人もいます。理解をするには理由を知ることが重要です。簡単な問題には「なぜ?」に対する答えは言えるのですが、非常に複雑な問題や、要件が怪奇すぎて微妙な問題に対するうまい解決策などをスキーマ設計者が出してきたとき、なぜそうなのかと言うことは設計者もうまく説明できないかもしれません。もちろん、理由があるのですが、知識を知らない人に説明できるかというとなかなか難しいと言うのが実情でしょう。もちろん、そう言う場合に頼りになるという意味では悪くはないとも言えますが、「自分もそうしたスキルをつけたい」と思ったらどうすればいいのでしょうか?

そう言うわけで、いろんな書籍があり、セミナーなどもやっていて、それらで勉強すればなんとかなっているという人もいるでしょうし、やっぱりわからなかったという人もいるでしょう。私も、ある有名なデータベース設計者のセミナーを参加して気づきました。そのかたの示す設計はもちろん、なるほどと思うところもあるのですが、理由を仔細におっしゃらない場面も多々あり、要するに「常識的にはこうなりますね」的な説明で終わってしまう場面もあったからです。その理由を知りたい、理由を知って応用したいと思うのが通常かと思いますが、やはりデータベース設計の世界は、どうもまずは経験を積んだ人の知見が主なナレッジということになってしまうのでしょう。

私自身はその答えはもう持っていて、クローズドなセミナー等で少しはお話ししています。また、そういうコンテンツを持っているのなら、それをビジネス展開してはどうかと思われるところかもしれません。少しはそう思っていたのですが、いろんな状況が重なり、「そうだ、淡々とブログに書こう!」と思った次第です。不定期にこの話題を積み重ねて行こうと思っています。まず、近々は、以前に所属した会社の社内セミナーで話そうとしていた内容を文章にまとめようと思っています。大まかに説明すると、「同じ名前のものが部署によって異なる対象になる」という事例から、それらはテーブルを分離しないと管理できないという話です。ドメイン駆動開発の世界でのユビキタス言語の考え方を、データベース設計のある側面に適用したお話しです。

そういうわけで、データベースデザインについて書くことにしました。

Apple IDの2要素認証をいつまでも求められる場合の対処

ちょっと話題的には古いのかもしれませんが、Apple DeveloperのApple IDは2要素認証が必須になり、そのような警告メッセージが出ました。で、ある時から、2要素認証を「しないといけない」状況になりました。

そこで、appleid.apple.comで、2要素認証をオンにしてみたのですが、XcodeやDeveloperサイトでの状況は変わりませんでした。Xcodeでは署名のたびにパスワードを求められるのですが、それでも認証が通らなくなってきてなんとかしないといけなくなりました。appleid.apple.comで設定すればいいだけではないというのがポイントです。

で、どうすればいいかといえば、macOSのシステム環境設定にあるiCloudで、そのApple IDを入力します。しばらくすると、警告アイコンが出てきて、更新するみたいな内容のボタンが出てくるので、それをクリックしてしばらくすると、アカウントの情報が更新された模様です。そこまでくると、Xcodeでの認証が通るようになります。

多分、何かの具合で、appleid.apple.comでは更新ができない状態なのでしょうけど、iCloudで普段使っていないアカウントの場合、入力し直しになり、データが消えるみたいなメッセージに対処しないといけないわけですが、データはクラウドにあるので原則問題ないと思います。しかしながら、システム環境設定を変えるのは色々面倒と後の影響がきになるところですが、appleid.apple.comでダメだったら仕方ないので、iCloudでセットアップして、更新処理をmacOS側からやってください。

米国からカルガリ経由で帰国

バンクーバー経由でアメリカに入った帰りは、やはりエアカナダだったのですが、サンフランシスコからカルガリーまでUnited Expressで行き、そこで乗り換えるというスケジュールでした。これも、2014年6月の状況ですが、メモとして残しておきます。

往路は先にエアカナダだったのでいろいろな意味でスムーズだったのでしょうけど、復路は先にエアカナダのコードシェア便でスタートです。そうすると、エアカナダの事前のチェックインは、カルガリーと成田間のフライトしかできず、最初にサンフランシスコで乗るフライトは、空港に行かないとチェックインができません。ちなみに、エアカナダはiOSのPassbookですので、紙はまったく使いませんが、その前には昔ながらのチケットを持ってカルガリーまで移動することになります。

まず、出発のサンフランシスコからの便は、ユナイテッドとエアカナダのコードシェア便で、運用はユナイテッドです。エアカナダのカウンターは国際線側にしかないため、この場合は運用しているユナイテッドの、しかも国内線のターミナル3に行って手続きをすることになります。カルガリーはもちろんカナダなのですが、国内線扱いですね。自動チェックイン機で、パスポートをかざせば、問題なく、チェックインがそこでできました。荷物もそこであずけて、成田行きというタグを貼ってもらいます。そして、セキュリティチェックを受けて普通に乗り込みます。23Aという席だったのですが、いちばん後ろの席でした。小さなジェットで約2時間半でカルガリーです。なお、最初に登場するときにバッグを預ければ、そのバッグの扱いがどうなるかを紙でもらえます。飛行機では税関深刻の用紙を記入しておきます。

カルガリーではまず入国審査をします。そこでけっこう並んだので焦ったのですが、幸か不幸かカルガリー発の飛行機も遅れたので、ダッシュしなくて済みました。アメリカからの便だと全員入国審査があり、たままた飛行機が重なったのか、かなりの列ができました。入国にはビザは不要で(乗り換えだけだから)、単にどこから来て、どこに行くのかを言って、滞在時間くらいを言っただけです。アメリカの入国のように、指紋や写真は撮らないのですぐに終わります。その後、ターンテーブルに行って、まず自分の荷物を持ち、関税申告の用紙の回収場所を通り抜けます。そこを出たすぐのところに、エアカナダのカウンタがあって、そこで荷物を再度預けます。単にチケットのチェックをして、ベルトコンベアに載せるだけです。この荷物の移動を自分でやらないといけないということです。

そして、後は飛行機に乗り込みますが、工事中なのか、迷路のように入り組んだところを通貨して乗り場に行きました。そして、カルガリー発の便に乗る時に、入り口の係の人がパスポートチェックをします。Passbookのチケットとパスポートを渡し、検索をして確認すればOKです。iPhoneとパスポートを返されるときも、紙のチケットと同じように、パスポートにiPhoneをはさんで返してくれます。まあいいのですが、習慣って変わらないのですね。カルガリーからの便は半分ほどしか席が埋まってない感じでした。

ちなみに、サンフランシスコ空港まではいつもBARTを使っているのですが、到着時に何も考えずに往復分のチャージをしました。しかし、今回、朝早い便だったのでBARTで行く事ができず、シャトルで移動しました。チャージされたBARTチケットが余ってしまって困っています(苦笑)。

[IM]ドラッグ&ドロップでファイルアップロード

ファイルのドラッグ&ドロップによるアップロードをINTER-Mediatorに実装しました。動作条件を整える方法はドキュメントを改めて書きますが、ページファイル上は、

class=”IM[testtable@vc1] IM_WIDGET[im_fileupload]”

のように、IM_WIDGETで、利用するコンポーネントを書くだけで、以下のムービーのようなドラッグ&ドロップによるファイルのアップロードができるようになっています。

dragdrop