[DBデザイン#18] 実例から考える: 要求をさらに拡大する

納品書に出荷日を入れるという簡単そうな要求でも、細かくチェックすると色々と複雑な問題が出てきました。そして、「出荷」という概念というか、それはむしろ新たな活動というべき事象が社内にはあって、以前には顕在化していなかったものが、ちょっとしたきっかけでどうやら見えてきました。出荷は、受注(ここでは「納品書」として扱っている)に関係するのは明白ですが、販売明細を出荷に紐づけるか、納品書に紐づけるかという選択肢があって、それぞれでできること、できないことがあると示しました。なお、途中には、販売明細に出荷日のフィールドを設け、納品書と販売明細の関係はそのままで、いわば、販売明細と1対1の出荷のエンティティを設けるようなことも検討しました。それらの分析途中でも指摘しましたが、納品書の明細1行がまとまって出荷するとは限らないかもしれないということもあり、今回から数回に分けて、その場合にどのようなスキーマになるのかということを検討してみましょう。

ちなみに、要求探索の意味での問題点がここで露わになってきており、なぜそんなことが発生するのかをここで考えてみましょう。出荷のことがどうやら要求を検討する段階ではおざなりになっていたというのは明白です。なぜでしょう? それは最初の方で、「いろいろな部署の意見を聞いた」とありますが、出荷部門の意見は聞いていなかったからと言えるでしょう。この会社、もしかしたら、倉庫部門が営業の中の一部で、営業の担当者は気にも止めてなかったのかもしれません。そういうことを防ぐには、ワークフローをしっかりと「記述する」ことでかなりの解決になります。記述方法は色々ありますが、ダイアグラムを記述するのが理想的です。そうすれば、出荷することは忘れないでしょう。ですが、社内の複数の部署をまたがってのフロー図を書き切るのはかなり大変です。みずほ銀行は度重なるシステムトラブルに見舞われていましたが、本格的なシステム統合に先立って何年もかけて社内業務のデータフロー図を作成したことは有名です(『みずほ銀行システム統合、苦闘の19年史』日経BP社)。これが要求を洗い出すための最善の方法になります。しかしながら、現実にそこまでの労力はかけられないとおっしゃるお客さんが多分ほとんどでしょう。そうなると、設計する側でどこまで見えない要求の糸口に気付くかに依存してしまいます。ただ、少なくとも、顧客側の経営者は、業務の要素を把握しておくべきであって、実際にフローに登場しながらも要求に組み込まれていないことを把握するのは管理者の責任であるというのが一般的な考え方だと思います。ともかく、いろいろな立場の人と対話を行うしかありません。現場の人の声を聞くのも大切だけど、それと同様に管理的な立場の人との対話も重要です。そして、少なくとも設計者はわかる範囲でワークフローを何らかの方法で記述をすべきです。書けば、繋がりの不自然なところなどが見えてきて、何か足りないのか、あるいは余計なことをやっているのかなどが顕在化してくるものです。

出荷について考慮が足りなかったのは、社内ではその部署や業務が軽視されていた可能性も高いのですが、他にも要因は考えられます。出荷業務は別途独立してシステムが確立していた可能性があり、社内的にはもう別に考えなくてもいいんだ的な空気があったのかもしれません。そのような場合、「考えなくてOK、以上」で済ませがちなのですが、そこでシステム間連携が雑だと、結局のところ最低限の業務効率化も果たせない可能性もありますし、より作業が複雑化してシステム化のメリットは全くなかったということにもなりかねません。その場合は、既存システムも調査して適合性を高めるのはもちろん、そちらの改変やリプレースを提案できるくらいの設計力は欲しいところです。

まだまだ別の可能性があります。流通を完全に外注している場合もあるでしょう。このモデルになっている会社はどうやら製造部門はあるようですが、そこから倉庫会社にひたすら製品を送り、営業は伝票を送り続けると、自動的に顧客に指定した個数が届いているのかもしれません。この場合も、根本的には別システムです。別システムでかつ別会社なので、さらに柔軟性は損なわれますが、前述の通り、適合性を高めるための工夫を設計に織り込む必要は出てくるでしょう。

ということで、「納品書と出荷の明細は対応していない」前提の設計に入りますが、まずは基本的な考え方をまとめます。以下のER図と、サンプルデータの表のような構成になります。納品書と販売明細、出荷予定と出荷明細、これらが1対多の関係にあります。納品書はもちろん伝票をもとに検討した結果ですが、出荷予定をもとにすれば、正しい意味での「納品書」つまり出荷に対応した商品明細が記載された帳票が作成できそうです。なお、納品書と出荷予定の対応は、これだと記録されていませんが、ここではそれ良しとします。ちなみに、ここでの納品書と出荷予定のそれぞれの明細が対応を取る必要がある案件をこなしたことがありますが、もう少しエンティティが増えて複雑にはなるもののちゃんと動いているのでそういう設計も可能です。

ここで検討したいのは、「ある顧客のある商品に対して、まだ出荷していない個数はいくつか」を知りたいということです。つまり、出荷残数の把握です。出荷予定の生成を考えれば、出荷残があるから行うわけで、出荷残を参照しながら出荷明細を作っていくというシナリオが自然かと思われます。ここでも表のCRUDをワークフローに乗せて考えれば具体的な方針が出てきます。発注数は納品書とその販売明細が元データとして集計すれば得られます。一方、出荷数は、出荷に対する出荷明細を元データとして集計すれば得られます。その差が、まだ出荷していない数になります。この出荷残というデータの存在は、上記のERや表ではまだ顕在化していません。

出荷残を求めることは、データベースの設計的には単純と思われるかもしれませんが、この方法には大きく2つの問題が発生する可能性があります。1つはパフォーマスの問題、もう1つは誤差の問題です。パフォーマンスの問題は、こうしたデータを何年も積み上げていることを想定すれば自ずと見えてきます。最初はそれほどのデータ量でもないものが、数年も使っていると線形的に増えます。ナイーブにな考え方では受注数と出荷数を得るために、何年も前からのデータを全部合計する必要があります。また、線形的にデータが増えるため、「年々システムが遅くなる」可能性は大です。特に、FileMakerで扱い量が多い会社では、まあ2,3年でやばくなるという感じでしょうか? SQLだとかなり多くなってもそれなりには動くと思いますが、いずれにしても効率良い方法ではありません。これに対する対応策は、何らかのキャッシュを自分で構築する方法があります。そのキャッシュをデータベースとして設計しなければなりません。別の対応策は、「現在の出荷残を記録する」方法です。販売明細や出荷明細は、在庫の出入りです。販売明細に「3個」と入力されれば3だけ増加し、2個出荷されれば2を引くということで出荷残数が1になっているようなデータを持つことです。これは、営業と出荷をそれぞれ入と出と見なせば、ちょうど銀行口座のような動作をさせるようなものと考えられます。お金ではなく、商品の個数の入と出があって、残高は出庫残となるものです。いずれにしても、こうした工夫は最初からやっておいてパフォーマンスの問題が出ないようにすべきです。

もう1つの問題は「誤差」です。在庫数や現金残高など、本来は正しく記録していれば現状と帳簿の数値は一致するのですが、これがいろんな理由で一致しません。店舗のようなところだと、一致しない理由は多岐に渡るのですが(万引き、欠品、破損、事務処理を忘れる、など)、一致しないことがいわば常識であって、定期的に「棚卸し」をするのが一般的です。つまり「現状の在庫数」を把握して、帳簿に増減をかけます。この仕組みをなしに、こうした在庫数などの処理を進めるのはおそらくかなり大変なことになります。データが正しければ棚卸しは必要はないというのはその通りですが、棚卸しが不要な現場は実のところ見たことはありません。実際の個数と帳簿上の個数が違うとき、「何で1だけ在庫が違うのか」を血眼になって検証する労力やコストを考えれば、単に調整をしてしまった方が効率的なことが普通なのです。過去の情報をどの程度振り返るのかということも関係がありますが、多くの業務は「その時点での情報」の管理で概ね方がつくという感じではないかと思います。万引きや欠品等での損失は別途考えるとして、通常の業務を回すシステムは誤差の解消を棚卸しという手法で処理をします。企業会計上、数値の調整による損失計上は一定の範囲では認められています。ただ、棚卸しによる調整をどうするのかは、その会社での業務にかなり依存します。今後に紹介するスキーマ変更では、棚卸しについては方針を示すのに止めることにします。

続きは次回に回すとして、実はこのパフォーマンスの問題を解決するのは、スキーマだけでなく、ロジックが発生します。実はスキーマは単なるデータベースの設計ではなく、ロジックのベースにもなり結果的にロジックの設計も行った結果がスキーマだったりして、システム全体に渡る方針を記述したものになるという側面が見えてきます。