その他

どこにも入らなかったことや,いただいた意見への回答,その他私見を書き連ねました.まとまったらどこかへ移すかもしれません.

主キー項目のnull

主キー項目にnullを設定できない理由です.

まずnullとは,数字のゼロや空(長さのない)の文字列ではありません.nullという「値」を定義している訳でもありません.nullは「そのフィールドには値を定義できないこと」,「そのフィールドには情報が欠落していること」を表しています.したがって,nullを算術演算や論理演算には使用してはいけません.「指定したフィールドがnullかどうか」を判定するために“=null”,“<>null”,“!=null”ではなく,“is null”,“is not null”という構文をSQLが用意しているのも,nullが数値や文字とは性質が異なるためです.
#RDBMSによっては“=null”,“<>null”,“!=null”が使える場合もありますが,簡便性のためです.

次に,主キー項目とはテーブルの中のデータを一意に区別するものです.主キー項目が複数フィールドから成る場合には,それらの項目全てに値を定義しないと他のデータとの区別はできません.主キー項目に値の欠落はありえません.

主キー項目がnullとは「データを一意に区別する主キー項目に値の欠落が存在する」ということです.つまり,「主キー項目に値を定義しなくてもデータは一意に定義できる」ということであり,主キー項目の存在を主キー項目自ら否定しています.

したがって,主キー項目にnullは指定できません.言い換えれば,nullが指定できると言うことは,その項目は主キー項目ではないと言うことです.

正規化とはテーブルを分けることではない

「正規化」とは「テーブルを分ける」ことではありません.例えば,

商品テーブル内のデータ件数が多いので,正規化してテーブルを二つに分けました.商品テーブルAには商品コードxxx番まで,商品テーブルBには商品コードxxx番からが入っています.

これは正規化ではありません.そして,正規化は「データが多いから」行うものでもありません.

帳票や画面もエンティティか?

「帳票や画面」も実世界に存在するし,システムで管理しなければならないものなので「エンティティ」と考え,同じ構造を持つテーブルを定義してはいけないのでしょうか.

定義すべきではないと思います.帳票や画面はエンティティの属性を紙やディスプレイに映し出したものにすぎません.したがって,帳票や画面そのものを管理しなければならないのではなく,それらが映し出した属性を持つエンティティを管理しなければならないのです.もし,帳票や画面と同じ構造のテーブルを定義すれば,それらの属性は全て他のエンティティの属性から持ってくれるはずです.

ただし,帳票の印字位置等,帳票そのものが持っている属性は別です.これらまで,無理矢理どこかのエンティティに持たせるのなら,帳票を表すエンティティを定義すべきです.

それはバグではないのですか

同じ値や計算で求めることのできる項目をテーブルに持たせるべきではないという話でしたが,同じ値を持たないといけない項目,あるいは計算値と同じでないといけない項目の値が異なっいているというのはバグではないでしょうか.当然テストで発見しなければならないことで,もしテストで見つからなくても本番稼動後にフォローとして対処すれば良いはずです.

結論から言うとバグです.同じ値,あるいは計算した値と同じものが入っていないといけない項目に異なる値が入っているのですから当然プログラムに誤りがあります.どのレベル(プログラミングなのか仕様なのか)のバグなのかここでは考えません.テストで発見しないといけないはずと言うのも,本番稼動後のフォローで対応すれば良いというのもその通りです.異論はありません.

こういう状況を考えてみましょう.

あなたはあるプログラムを作成しました.ユーザとの仕様の確認もきちんと終わらせましたし,既存システムとのインタフェースも確認しました.テストも完了し,本番切り替えも問題なく終わりました.

1ヶ月程たったある日,今回の開発とは直接関係ないシステムの担当者から抗議がきました.あなたの作ったプログラムがデータベースに不整合をひき起こしていると言うことです.かなり怒っています.しかし,そんなはずはありません.テストもきちんと終わっています.ユーザも問題があるとは言っていません.

よく話を聞くとこういうことのようです.つまり,あなたが更新しているテーブルと同じ値を持たないといけない項目が他のシステムのテーブルにもありました.しかし,それは今回あなたが担当したシステムとは直接関係なかったので誰も気付かなかったのです.仕様からも漏れていましたし,テストの対象にもなっていませんでした.

既存システムの設計書を再度確認しましたがそのような記述はありません.念のため,相手のシステムの設計書も見せてもらいました.すると,その旨の記述があります.どうやらこちらのシステムが先にできて,そのデータを借用する形で相手のシステムがテーブルを作ったようです.したがって,後からできたシステムの設計書には記載があっても,もともとあったシステムの設計書には記載がなかったのです.正直思いました.「書いてないものが分かるかよ」.

あなたは,自分のシステムとは全く関係のないシステムのテーブルを更新するため,取ってつけたかのようなプログラムを追加しました.明らかにプログラムは変なことになっているのですが,同じ値でないといけないというのですから仕方がありません.

こういう状況を考えてみましょう.

ある日の午前3時のことです.真夜中です.当然もう寝ています.ところが,こんな時間に電話です.眠い目を擦りつつ電話に出ると会社からです.プログラムか異常終了したので対処してほしいと言う連絡でした.仕方がありません.ユーザに電話をし,明日の朝の対応で間に合うかどうか(これを期待して)訪ねました.ところが,朝の6時までに動かないと間に合わないと言う返事でした.ぐずぐずしてはいられません.服を着替えタクシーで会社へ急ぎます.

会社に着き機械の電源を入れデバッグのはじまりです.それにしても,異常終了したプログラムの本番稼動は1年以上前で,これまで正常に動いていたものです.どうして突然動かなくなったのでしょう.そんなことを考えつつ検証をくり返しますがプログラムが動かない原因が分かりません.何度も何度もロジックを追いかけ,手元のテストデータでテストをくり返しますがうまく動きます.時間がなくなってきました.所長と一緒にユーザに謝りに行く姿が目に浮かびます.

そんな時,はたと気付きました.テーブルの中の同じでないといけない項目に異なる値が入っているのです.(テーブルの中にある計算値を入れる項目の値と実際に計算した値が異なっているのですでも可)原因はプログラムではなくデータの不整合だったのです.データを直してもう一度動かせばうまくいきます.でも,ちょっと待ってください.いったいどちらが「正しい値」なのでしょうか.この二つの項目は同じ値でないといけないのですが,違った場合どちらが正しいのでしょう.考えたこともありませんでした.もう迷っている時間はありません.どちらかにあわせてプログラムを動かしましょう.確率は50%,2回動かせばなんとかなります.

あたりが明るくなる頃,なんとかその場をしのぐことができました.しかし,まだこれで終わったわけではありません.データの不整合が発生した原因を調べないと,また同じことの繰り返しです.このテーブルにデータを書いているプログラムを片っ端から調べ,間違った値を書いている箇所を見つけださないといけません.しかし,午前3時から働いているのですから昼を過ぎたあたりでもうへとへとです.しかし,今日探し出して修正しておかないと今晩また呼びだされるかもしれません・・・.睡魔には勝てませんでした.再度の呼び出しを覚悟し,一足先に家に帰り眠ることにしました.予想通り電話がかかってきました.再び会社へ行きデータの不整合を直しプログラムを動かします.早く原因を見つけないといつまでもこの状態が続いてしまします.

このプログラムはこれまで動いていたのだから,異常終了する前の日に本番稼動したプログラムが悪さをしているのかもしれません.そう思い調べてみましたが,違いました.そして,やっと問題のプログラムを見つけました.1ヶ月前に本番稼動したプログラムです.本番稼動後1ヶ月間使っていなかった機能をユーザが使い始めたため,この時期に問題が顕在化したのです.さっそくプログラムの修正を依頼しました.

問題のプログラムを作った担当者は同じ値が入っていないといけない項目が複数あるとは思ってもいなかったので,テストをしてもおかしいとは思わなかったのです.相当頭にきました.

「テストで発見すればいい」,「本番稼動後のフォローで対応すればいい」というのであれば,それを止めろというつもりはありません.

エンティティをユーザインタフェースから

要件を定義するにしても,ユーザの持ってくる情報は画面や帳票(ユーザインタフェース)です.ユーザインタフェースからエンティティを抜き出すのは手順として逆でしょうか.

要件から抜き出す方法を私は書きましたが,エンティティを抜き出す方法は,プロジェクトやユーザの性質で様々だと思います.最終的にユーザインタフェースに依存しないデータモデルができていれば良いのであって,手順については柔軟に考えてよいのではないかと思います.

「昔食べておいしかったこんな料理を作ってください」と料理の写真を板前に見せたとします.写った料理の材料や調理方法を推測せずに,見栄えだけ整えようとする板前を私は信用しません.写真が既存ユーザインタフェース,材料がエンティティ,調理方法がアプリケーションルール,板前が再現した料理の見栄えが新規ユーザインタフェースです.写真から材料と調理方法を推測する力がエンジニアの技量ではないでしょうか.

実装は忘れなくてはならないのか

業務概要とシステム概要を混同せず,実装を意識しない設計を行うべきなのはわかりますが,多くの場合,実装形態は既に決まっています.既決な実装形態をいったん忘れないといけないのでしょうか.

実装形態を忘れ去る必要はありません.業務概要とシステム概要の混同は避けるべきですが,業務概要をまとめ終わるまでシステム概要をまとめてはならないわけではありません.実装が頭に浮かんできたら,システム概要としてまとめておけばよいと思います.

業務概要からシステム概要を決めるのが理想だと思います.そうしないと,何を開発してよいのかわかりません.しかし現実は,システムを意識したり,実装を意識したり,業務を意識したりしながら設計という活動は進んでいくと思っています.

文章としてあらわすと,上から下・右から左へ順序良くやっていけそうです.実際は順序を飛ばしたり,後戻りをしたりでかまわないと思います.

その中で「実装に依存している設計」と「実装から独立して業務に依存している設計」をうまく切り分けることが設計という行為の中の要諦になるのではないかと思っています.「実装から独立した設計」は実装が変わっても生き続けることができます.そして,これが業務知識や分析能力というものになるのです.実装技術よりも長持ちする財産です.

プロセスへの入力

プロセスには必ず入力と出力があるということですが,時刻起動の場合はどのようになるのでしょうか.入力として時刻を記述するのでしょうか?その時刻の源泉は何になるのでしょうか?データの発生源として閉じた四角になるのでしょうか?それともデータの保管元として半開きの四角を記述するのでしょうか?

私なら,データの発生源(閉じた四角)から時刻を入力として受取るように書きます.「時刻そのものを受取っているわけではない」ので,起動イベントを受取っても良いかと思います.

時刻の発生元をデータの保管元(半開きの四角)とすると,「その保管元に時刻を保管するプロセスは何?」という疑問が湧いてきますので,保管元ではなく発生源(閉じた四角)です.「開発対象システムの外部から起動時刻を受取る.起動時刻の発生方法は開発の対象外」と考えます.