要件定義 / 基本設計 / 詳細設計
基本:共通仕様 / 機能一覧 / テーブル一覧 / 画面一覧 / 画面遷移
詳細:テーブル定義書 / 画面定義書 / イベント仕様書
本書は、基本設計・詳細設計の全成果物が共通で参照する規約を定める。
各成果物は、共通で決まっている事柄を再掲せず、本書の ID(PRE-* / VAL-* / ERR-*)を参照する。
| 項目 | 内容 |
|---|---|
| 対象システム | NorthwindDb を用いたサンプル業務アプリケーション |
| 対象 DB | Microsoft SQL Server サンプル DB「Northwind」(原典) |
| アプリ形態 | Web アプリケーション(マルチユーザ、ブラウザからの利用) |
| 技術スタック | 特定のフレームワークに依存しない。本設計書はコントロール名・API 名・ライフサイクル名を用いず、「一覧表」「ドロップダウン」「ページ読み込み」等の一般語で記述する |
| 文字コード | UTF-8 / 日本語表示。DB 側は Northwind 原典どおり Unicode 型(nvarchar 等) |
本システムはサンプルであり、次の設計・実装は行わない。設計書中にこれらを登場させてはならない。
- ワークテーブル、採番テーブル(採番は
IDENTITYを用いる) - 変更履歴テーブル、監査ログテーブル
- 論理削除(削除は物理削除とする)
- 非同期処理(帳票・印刷を含む)、ジョブ、キュー
- データ・キャッシュ層
- ドメイン駆動設計(DDD)に基づく戦術的パターン(エンティティ/値オブジェクト/リポジトリ等の設計)
帳票は同期処理とし、ブラウザの印刷機能を用いる印刷用画面として設計する。
| 種別 | 書式 | 例 | 定義場所 |
|---|---|---|---|
| モジュール | <MOD> |
ORD |
本書 3 節 |
| 機能 | FN-<MOD>-nn |
FN-ORD-01 |
機能一覧 |
| 画面 | SC-<MOD>-nn |
SC-ORD-01 |
画面一覧 |
| 画面項目 | <画面ID>-I<nn> |
SC-ORD-01-I01 |
画面定義書 |
| アクションボタン | <画面ID>-B<nn> |
SC-ORD-01-B01 |
画面定義書 |
| イベント | EV-<MOD>-nnn |
EV-ORD-101 |
イベント仕様書 |
| 共通事前条件 | PRE-<名称> |
PRE-DB |
本書 5 節 |
| 共通検証ルール | VAL-<名称> |
VAL-REQUIRED |
本書 6 節 |
| 共通エラー | ERR-<名称> |
ERR-DB |
本書 7 節 |
イベント ID の下 3 桁は <画面連番><イベント連番> とする。
例:EV-ORD-101 = 受注管理の 1 番目の画面(SC-ORD-01)の 1 番目のイベント。
| コード | モジュール | 主要テーブル |
|---|---|---|
CMN |
共通(メニュー等) | - |
ORD |
受注管理 | Orders / Order Details |
CUS |
顧客管理 | Customers / CustomerDemographics |
PRD |
商品管理 | Products / Categories |
SUP |
仕入先管理 | Suppliers |
EMP |
担当者管理 | Employees / Territories |
SHP |
配送管理 | Shippers |
SLS |
売上分析 | Orders / Order Details(集計) |
INV |
在庫分析 | Products / Categories(集計) |
PRF |
パフォーマンス分析 | Employees / SalesTargets |
日本語表記と Northwind の物理名の対応。設計書中の日本語は本表の語に統一する。
| 日本語 | 物理名 | 説明 |
|---|---|---|
| 受注 | Orders |
顧客からの注文 1 件 |
| 受注明細 | Order Details |
受注に含まれる商品 1 行 |
| 受注 ID | Orders.OrderID |
受注の識別子。IDENTITY による自動採番 |
| 受注日 | Orders.OrderDate |
注文を受け付けた日 |
| 要求納期 | Orders.RequiredDate |
顧客が希望する納品期限 |
| 出荷日 | Orders.ShippedDate |
出荷した日。NULL は未出荷を意味する |
| 送料 | Orders.Freight |
受注 1 件あたりの配送費用 |
| 出荷先 | Orders.ShipName ほか Ship* 列 |
配送先の名称・住所 |
| 顧客 | Customers |
取引先企業 |
| 顧客 ID | Customers.CustomerID |
5 桁の英大文字コード。利用者が入力する(自動採番しない) |
| 担当者(社員) | Employees |
受注を担当する自社社員 |
| 上司 | Employees.ReportsTo |
自己参照による上長。NULL は最上位 |
| 配送業者(運送会社) | Shippers |
出荷を担当する運送会社 |
| 商品 | Products |
販売する商品 |
| 単価 | Products.UnitPrice / Order Details.UnitPrice |
商品マスタの単価/受注時点で確定した単価 |
| 在庫数 | Products.UnitsInStock |
現在庫数 |
| 発注済数 | Products.UnitsOnOrder |
仕入先へ発注中の数量 |
| 発注点 | Products.ReorderLevel |
補充を要すると判断する在庫数の閾値 |
| 廃番 | Products.Discontinued |
販売終了フラグ。真のとき新規受注に使用できない |
| カテゴリ | Categories |
商品分類 |
| 仕入先 | Suppliers |
商品の仕入元 |
| 地域 | Region |
テリトリーの上位区分 |
| テリトリー | Territories |
社員に割り当てる営業担当区域 |
| 顧客区分 | CustomerDemographics |
顧客の分類 |
| 行バージョン | RowVersion |
楽観排他のために本設計で追加した列(9 節) |
| 売上目標 | SalesTargets |
パフォーマンス分析のために本設計で追加したテーブル(9 節) |
設計書中の金額項目は、次の式で統一する。
| 名称 | 式 |
|---|---|
| 明細単価(割引後) | Order Details.UnitPrice × (1 - Order Details.Discount) |
| 明細金額 | 明細単価(割引後) × Order Details.Quantity |
| 小計 | Σ 明細金額(同一受注の全明細) |
| 受注合計 | 小計 + Orders.Freight |
- 割引率
Discountは 0〜1 の実数(0.15 は 15% 引き)。 - 計算は 10 進数型で行い、浮動小数点型で行わない。
Discountは DB 上real(単精度)であり、 そのまま計算すると誤差が蓄積する(テーブル定義書の「Discountの扱い」)。 - 明細金額は小数第 3 位を四捨五入して小数第 2 位までとし、その値を合算して小計とする。
- 画面表示は通貨記号なしの千区切り+小数 2 桁とする。
全画面に共通する仕様。個別の画面定義書では本節との差分のみを記述する。
| 項目 | 仕様 |
|---|---|
| 画面モード | 一覧/照会/登録/編集の 4 種。照会モードでは全入力項目を読み取り専用とし、更新系ボタンを非表示にする |
| 一覧の既定件数 | 1 ページ 20 件 |
| ページング | 「先頭・前・次・末尾」およびページ番号。総件数と現在ページを表示する |
| 並べ替え | 一覧の列見出し選択で昇順/降順を切り替える。既定の並び順は画面ごとに定義する |
| 検索条件の保持 | 一覧から詳細へ遷移し戻った際、直前の検索条件・ページ・並び順を復元する |
| 必須項目 | 表示名の末尾に「*」を付す |
| メッセージ表示 | 画面上部の共通メッセージ領域に、情報/警告/エラーを区別して表示する |
| 項目単位のエラー | 該当入力項目の直下にエラー内容を表示する |
| 削除の確認 | 削除操作は必ず確認ダイアログを挟む |
| 未保存の離脱 | 登録・編集モードで未保存の変更がある状態の離脱操作は、確認ダイアログを挟む |
| 日付の表示・入力 | yyyy/MM/dd |
| 空値の表示 | NULL の項目は空文字を表示する(「-」等は用いない) |
ID の書式は PRE-<名称>。各イベント仕様の「事前条件」では、本表の ID を参照し、個別の事前条件のみを追記する。
| ID | 事前条件 |
|---|---|
PRE-DB |
データベースへ接続可能であること |
PRE-PARAM |
当該画面が要求する遷移パラメータが取得済みであること |
PRE-EXIST |
遷移パラメータで指定されたキーのデータが存在すること |
PRE-MODE |
画面が当該操作を許可するモード(登録/編集)であること |
PRE-LOADED |
画面の初期表示(ページ読み込みイベント)が完了していること |
ID の書式は VAL-<名称>。
| ID | 検証内容 | エラー時の扱い |
|---|---|---|
VAL-REQUIRED |
必須項目が未入力でないこと | ERR-VALIDATION |
VAL-LENGTH |
文字列項目がテーブル定義書の桁数以内であること | ERR-VALIDATION |
VAL-NUMERIC |
数値項目が数値として解釈でき、定義された範囲内であること(数量 > 0、単価 >= 0、割引 0〜1、在庫数・発注済数・発注点 >= 0、対象年 >= 1900、対象月 1〜12、目標金額 >= 0) | ERR-VALIDATION |
VAL-DATE |
日付項目が日付として解釈でき、日付の前後関係が矛盾しないこと(受注日 <= 要求納期、受注日 <= 出荷日) | ERR-VALIDATION |
VAL-CODE |
コード項目が定められた書式であること(顧客 ID は英大文字 5 桁) | ERR-VALIDATION |
VAL-EXISTS |
選択・入力された外部キーの値がマスタに存在すること | ERR-VALIDATION |
VAL-DUP |
一意であるべきキーが既存データと重複しないこと | ERR-VALIDATION |
検証は保存操作の前に全項目をまとめて実施し、エラーがある場合は 1 件も更新せずに全エラーを表示する。
DB は妥当性を保証しない。 業務系で使用しない制約(外部キー・CASCADE・CHECK・UNIQUE・トリガー)は DB に定義せず、 アプリケーションで担保する方針である(DB に持たせない制約)。 DB が弾いてくれることを前提にせず、本節の検証を必ずアプリ側で実施すること。 とくに
VAL-EXISTS(参照先の存在確認)とVAL-DUP(重複確認)は、 従来 DB の外部キー制約・一意制約が担っていた役割を代替するものであり、省略できない。
ID の書式は ERR-<名称>。
| ID | 発生条件 | 動作 |
|---|---|---|
ERR-DB |
データベースへの接続・実行に失敗した | 「データベースに接続できませんでした。時間をおいて再試行してください。」を表示し、画面の状態は変更しない |
ERR-NOTFOUND |
指定されたキーのデータが存在しない(他ユーザによる削除を含む) | 「対象のデータは存在しません。」を表示し、当該モジュールの一覧画面へ戻る |
ERR-VALIDATION |
6 節の検証に違反した | 該当項目にエラー内容を表示し、入力値を保持したまま画面に留まる。更新は行わない |
ERR-CONFLICT |
更新対象の行バージョンが読み込み時と異なる(9 節) | 「他の利用者によって更新されています。最新の内容を読み込み直してください。」を表示し、更新を取り消して最新データを再表示する |
ERR-FK |
他テーブルから参照されているデータを削除しようとした | 「他のデータから参照されているため削除できません。」を表示し、削除を行わない |
ERR-BIZ |
業務ルールに違反した(個別のイベント仕様で定義) | 違反内容に応じたメッセージを表示し、処理を行わない |
- 更新を伴う処理は 1 トランザクションで実行し、いずれかのエラーが発生した場合はロールバックする。
- 上記いずれにも当てはまらない例外は
ERR-DBと同じ扱いとする。
全画面に共通して存在するイベント。各画面のイベント一覧では再掲しない。
| 名称 | トリガー | 処理内容 |
|---|---|---|
| メニューへ戻る | ヘッダのメニューリンクを選択 | メニュー画面(SC-CMN-01)へ遷移する。未保存の変更がある場合は確認ダイアログを挟む |
AGENTS.md の方針に従い、Web アプリケーションとして必要な最小限の追加のみを行う。追加した要素はテーブル定義書の備考欄に「追加」と明記する。
複数利用者が同一データを同時に更新した際の上書き事故(ロストアップデート)を防ぐため、 更新対象となるテーブルに行バージョン列を追加する。
| 項目 | 内容 |
|---|---|
| 列定義 | RowVersion int NOT NULL DEFAULT 1 |
| 追加対象 | Orders, Order Details, Customers, Products, Categories, Suppliers, Employees, Shippers, SalesTargets(9 テーブル) |
| 追加しない | Region, Territories, EmployeeTerritories, CustomerDemographics, CustomerCustomerDemo(参照または関連の付け外しのみで、行の項目更新を行わないため) |
| 採番 | アプリケーションが更新のたびに +1 する。DB は自動更新しない |
| 画面表示 | しない(画面定義書の画面項目には含めない) |
- 画面表示時に読み込んだ
RowVersionを画面が保持する。 - 更新・削除の
WHERE句に、主キーとあわせて保持していたRowVersionを指定する。 - 更新時は
SET句でRowVersionを +1 する。 - 更新・削除の件数が 0 件のときは
ERR-CONFLICTとする。 (主キーの行自体が存在しない場合はERR-NOTFOUND。両者を区別すること)
更新の定型文。すべての更新系イベントはこの形に従う。
UPDATE <テーブル>
SET <更新する列> = <値>
, RowVersion = RowVersion + 1 -- ★ 必ず書く
WHERE <主キー> = <値>
AND RowVersion = <画面が保持していた値>削除の定型文。削除では RowVersion を更新しない。
DELETE FROM <テーブル>
WHERE <主キー> = <値> AND RowVersion = <画面が保持していた値>登録時は RowVersion を列に含めない(DEFAULT により 1 で初期化される)。
RowVersion = RowVersion + 1の記述漏れは、競合検知を無言で無効化する。 加算を忘れると版数が進まないため、後続の更新が古い版数のまま通り、 先行更新が上書きされる(ロストアップデート)。 トリガーを使わない方針のため DB 側では救えない。 更新系イベントを実装する際は、必ず上記の定型文から書き始めること。
行バージョンの実現方式には複数の選択肢があるが、整数の版数をアプリが +1 する方式を採用する。
| 方式 | 採否 | 理由 |
|---|---|---|
| 整数の版数列(採用) | ○ | 全 DB で同一に動作する。精度差・時刻同期の問題が原理的に発生しない |
| DB 固有の行バージョン機構 | × | SQL Server の rowversion は理想的だが、他 DB に同等物がない。Oracle の ORA_ROWSCN は ROWDEPENDENCIES なしではブロック単位、PostgreSQL の xmin は VACUUM FREEZE で変化、MySQL の TIMESTAMP は既定の秒精度では同一秒内の更新を検知できない |
| GUID | × | 一意性は得られるが、順序を持たず、整数より記憶域と比較コストが大きい |
| UNIX 時間・タイムスタンプ | × | DB 間で時刻の精度が異なり、時刻同期のリスクも排除できない。同一時刻内の更新を取りこぼす |
特別の事情がない限り、DB 間での精度差や時刻同期リスクを完全に排除できる版数(整数 +1)方式が最も安全である。 この方式はクロス DB 対応(SQL Server / Oracle / PostgreSQL / MySQL)を前提とした選定であり、 制約をアプリで管理する本システムの方針とも一致する。
- パフォーマンス分析の「目標設定・進捗トラッキング」要件は Northwind 原典のテーブルだけでは満たせないため、担当者別・年月別の売上目標を保持するテーブルを 1 つ追加する。
- 詳細は テーブル定義書(パフォーマンス分析) を参照。