今回はFileMaker固有の機能ではなく、データモデルについての記事をご紹介します。最近業務でワークフローエンジンを作る必要があり、この記事を参考にしました。
ご紹介するVertabeloのサイトでは、この他にもデータモデル設計に関する興味深い記事を多く公開しています。興味のある方はぜひ参照してください。
Vertabeloはデータモデル設計のコラボレーション作業を支援する有償のWebサービスです。Webブラウザ上でER図を作成・編集し、結果をSQLのDDL(CREATE TABLE文)として出力するなどもできます。
なお、この作成したCREATE TABLE文をFileMakerでどう活用するかが問題ですが、例えば以下のような方法があります。
- MySQLなどにテーブルを作成し、ESSとしてFileMakerから接続する
- FileMaker ProでODBC共有をオンにしてデータソースとし、(ODBCクライアント設定をした上で)[SQLを実行]スクリプトステップでCREATE TABLE文を実行する
The Workflow Pattern. Part 1
Using Workflow Patterns to Manage the State of Any Entity
(元記事はこちら)
フリーランスデータモデラー
2016/3/15
時間の経過とともに遷移するものごと(entity)の状態を管理しなくてはいけない状況になったことはないですか? 身のまわりを見ればそのような例はたくさんあります。簡単なものから始めましょう。顧客レコードを「名寄せ」する作業です。
2つの異なる情報ソースから顧客のリストをマージしているとします。以下にあげる状態が発生する可能性があります。
Duplicates Identified -同一人物かもしれないエンティティを検出
Confirmed Duplicates -同一人物であることが確定
Confirmed Unique – 別人であることが確定
これらの状況のいずれにおいても、ユーザは[ はい | いいえ ]の決定を下すだけです。
しかし、もっと複雑な状況ではどうでしょうか? 状態間の実際のワークフローを定義する方法はあるでしょうか?
ものごとは簡単に間違った方向に進む
多くの組織では、job application(求職申込書)を管理する必要があります。シンプルなモデルでは、 JOB_APPLICATION
というテーブルを持ち、次のような値を含む参照データテーブルを使用して願書の状態を追跡できます。
Application Status (申込書の処理状況) |
---|
APPLICATION_RECEIVED (申込書受領) |
APPLICATION_UNDER_REVIEW (申込書確認中) |
APPLICATION_REJECTED (申込を却下) |
INVITED_TO_INTERVIEW (面接の依頼) |
INVITATION_DECLINED (面接依頼を却下) |
INVITATION_ACCEPTED (面接依頼を受入) |
INTERVIEW_PASSED (面接合格) |
INTERVIEW_FAILED (面接不合格) |
REFERENCES_SOUGHT (推薦の確認) |
REFERENCES_ACCEPTABLE (推薦合格) |
REFERENCES_UNACCEPTABLE (推薦不合格) |
JOB_OFFER_MADE (ポストの提示) |
JOB_OFFER_ACCEPTED (ポスト提示の受入) |
JOB_OFFER_DECLINED (ポスト提示の拒否) |
APPLICATION_CLOSED (求職申込み処理終了) |
これらの値は、いつでも任意の順序で選択できます。各段階で論理的かつ正確な選択を確実に行うかどうかはエンドユーザに任されています。不合理な状態の遷移を禁止することはできません。
たとえば、申込書が拒否されたとします。現在の状態はAPPLICATION_REJECTED
です。経験のないユーザが次にINVITED_TO_INTERVIEW
などの非論理的状態を選択するのを防ぐのに、アプリケーションレベルでできることは何もありません。
必要なのは、論理的に正しい次の状態をユーザに選択させるための何か、つまり論理ワークフローの定義です。
また、さまざまな職種の求職申込に、それぞれ異なる要件がある場合はどうなるでしょうか? たとえば、職種によっては適性テストを受ける必要がある場合があります。確かに、これに対応するためにリストに値を追加することはできますが、現在の設計では、エンドユーザが問題の求職申込書の職種を誤って選択するのを妨ぐ方法はありません。実際には、 コンテキストごとに別々のワークフローが存在します。
考慮すべきもう一つのポイントは、リストされた選択肢は本当にすべて状態なのか、という点です。この中のいくつかは実際には結果ではないでしょうか? 例えば、ポストの提示は、応募者によって受け入れられたり、拒否されたりします。したがってJOB_OFFER_MADE
は実際には、JOB_OFFER_ACCEPTED
とJOB_OFFER_DECLINED
の2つの結果を持ちます。
もう一つの結果は、職種の提示が取り下げられることです。取り下げられた理由は補足情報に記録することができます。これらの理由を上記のリストに追加するだけでは、エンドユーザが論理的な選択を行うことはできません。
したがって、状態、結果、補足が複雑になればなるほど、 プロセスのワークフローを定義する必要性が高くなります。
プロセス、状態、結果を整理する
データをモデル化しようとする前に、データに何が起こっているのかを理解することが重要です。最初は、種別にプロセス → 状態 → 結果という厳密な階層構造があると考えるでしょう。
上記の例を詳しく見ると、INVITED_TO_INTERVIEW
とJOB_OFFER_MADE
という2つの状態は、ACCEPTED
とDECLINED
という同じ結果を持てるということがわかります。これは、状態と結果に多対多の関係があることを示しています。これは他のいくつかの状態、結果、詳細にも当てはまります。
概念レベルでは、メタデータに実際に起こっていることは以下の通りです。
標準的なアプローチでこのモデルを現実世界に変換する場合は、 Process
、 State
、 Outcome
、Qualifier
という4つのテーブルを作るでしょう。 また、合わせて 多対多の関係を解決するために、Process_State
、 State_Outcome
、Outcome_Qualifier
という中間テーブルを置く必要があります。しかし、この方法は設計を複雑にしてしまいます。
さてここで、レベルの論理階層(プロセス→状態→結果→理由)を維持しながら、よりシンプルにメタデータを物理的に整理する方法があります。
ワークフローパターン
次の図は、ワークフローデータベースモデルの主要コンポーネントを示しています。
左側の黄色のテーブルにはワークフローのメタデータが含まれ、右側の青色のテーブルにはビジネスデータが入ります。
最初に言っておきたいのは、このモデルを大きく変更することなくどのようなエンティティでも管理できるということです。your_entity_to_manage
テーブルは、ワークフロー管理下のテーブルです。今回の例では、これはjob_application
テーブルになります。
次に、管理したいテーブルにwf_state_type_process_id
という列を追加するだけです。この列は、エンティティの管理に使用されている実際のワークフロープロセスを指します。これは厳密には外部キー列ではありませんが、 workflow_state_type
に対して正しいプロセスを迅速に問い合わせることができます。状態の履歴を含む表はmanaged_entity_state
です。ここでも内容を表す独自のテーブル名を選択し、独自の要件に合わせて変更してください。
メタデータ
ワークフローの複数のレベルがworkflow_level_type
に定義されています。このテーブルには以下の項目が含まれています。
Type Key | 説明 |
---|---|
PROCESS | 高水準のワークフロープロセス |
STATE | プロセスの状態 |
OUTCOME | 状態がどのように終わるか、その結果 |
QUALIFIER | (任意の)補足情報 |
workflow_state_type
とworkflow_state_hierarchy
は、典型的な部品表(Bill of Material ; BOM)構造になっています。この構造は、実際の工業製造品の部品表をよく表しており、データモデリングでは頻繁に使われます。階層を定義したり、多くの再帰的な状況に適用することができます。ここでは、プロセス(process)、状態(state)、結果(outcome)、(任意の)補足(qualifier)からなる論理階層を定義するために、この構造を利用します。
階層を定義する前に、個々の部品を定義する必要があります。これが基本的な組立ブロックの最小ピースになります。簡潔にするためにTYPE_KEY
(これはユニークです)でこれらを参照することにします。今回の例では以下のような項目があります。
Workflow Level Type | Workflow State Type.Type Key |
---|---|
OUTCOME(結果) | PASSED(合格) |
OUTCOME | FAILED(不合格) |
OUTCOME | ACCEPTED(受理) |
OUTCOME | DECLINED(却下) |
OUTCOME | CANDIDATE_CANCELLED(候補者キャンセル) |
OUTCOME | EMPLOYER_CANCELLED(雇用側キャンセル) |
OUTCOME | REJECTED(拒否) |
OUTCOME | EMPLOYER_WITHDRAWN(雇用側取り消し) |
OUTCOME | NO_SHOW(欠席) |
OUTCOME | HIRED(採用) |
OUTCOME | NOT_HIRED(不採用) |
STATE(状態) | APPLICATION_RECEIVED(申込書受領) |
STATE | APPLICATION_REVIEW(申込書審査) |
STATE | INVITED_TO_INTERVIEW(面接を依頼) |
STATE | INTERVIEW(面接) |
STATE | TEST_APTITUDE(適性テスト) |
STATE | SEEK_REFERENCES(推薦の取り付け) |
STATE | MAKE_OFFER(ポストの提示) |
STATE | APPLICATION_CLOSED(申込処理終了) |
PROCESS(プロセス) | STANDARD_JOB_APPLICATION(一般職の求職申込) |
PROCESS | TECHNICAL_JOB_APPLICATION(専門職の求職申込) |
次にこれらを使って階層を定義することができます。部品である組立ブロックを使って、構造を定義します。それぞれの状態について、とりうる結果を定義します。実際、このワークフローシステムでは、状態は必ず結果で終わらなければならないというのがルールです。
Parent Type – STATES (状態) | Child Type – OUTCOMES (結果) |
---|---|
APPLICATION_RECEIVED | ACCEPTED |
APPLICATION_RECEIVED | REJECTED |
APPLICATION_REVIEW | PASSED |
APPLICATION_REVIEW | FAILED |
INVITED_TO_INTERVIEW | ACCEPTED |
INVITED_TO_INTERVIEW | DECLINED |
INTERVIEW | PASSED |
INTERVIEW | FAILED |
INTERVIEW | CANDIDATE_CANCELLED |
INTERVIEW | NO_SHOW |
MAKE_OFFER | ACCEPTED |
MAKE_OFFER | DECLINED |
SEEK_REFERENCES | PASSED |
SEEK_REFERENCES | FAILED |
APPLICATION_CLOSED | HIRED |
APPLICATION_CLOSED | NOT_HIRED |
TEST_APTITUDE | PASSED |
TEST_APTITUDE | FAILED |
プロセスは、ある期間にわたって存在する状態のセットです。以下の表では論理的な順序で提示されていますが、これは実際の処理順序を定義するものではありません。
Parent Type – PROCESSES (プロセス) | Child Type – STATES (状態) |
---|---|
STANDARD_JOB_APPLICATION | APPLICATION_RECEIVED |
STANDARD_JOB_APPLICATION | APPLICATION_REVIEW |
STANDARD_JOB_APPLICATION | INVITED_TO_INTERVIEW |
STANDARD_JOB_APPLICATION | INTERVIEW |
STANDARD_JOB_APPLICATION | MAKE_OFFER |
STANDARD_JOB_APPLICATION | SEEK_REFERENCES |
STANDARD_JOB_APPLICATION | APPLICATION_CLOSED |
TECHNICAL_JOB_APPLICATION | APPLICATION_RECEIVED |
TECHNICAL_JOB_APPLICATION | APPLICATION_REVIEW |
TECHNICAL_JOB_APPLICATION | INVITED_TO_INTERVIEW |
TECHNICAL_JOB_APPLICATION | TEST_APTITUDE |
TECHNICAL_JOB_APPLICATION | INTERVIEW |
TECHNICAL_JOB_APPLICATION | MAKE_OFFER |
TECHNICAL_JOB_APPLICATION | SEEK_REFERENCES |
TECHNICAL_JOB_APPLICATION | APPLICATION_CLOSED |
BOM(部品表)の階層に関する重要なポイントがあります。実際の部品表が、組立品と組立部品を掘り下げて最小の部品まで定義するのと同様に、今回の階層も同じ構造を持ちます。これは、「組立品」と「組立部品」を再利用することを意味します。
例として、 STANDARD_JOB_APPLICATION
とTECHNICAL_JOB_APPLICATION
の2つのプロセス(process)はINTERVIEW
という状態(state)を持ちます。次に、 INTERVIEW
という状態には、PASSED
、 FAILED
、 CANDIDATE_CANCELLED
、NO_SHOW
という結果(outcome)が定義されています。
プロセスに状態(state)を使用すると、それが既に組立品であるため、自動的にその子供である結果(outcome)をセットで持つことになります。これは両方のタイプの求職申込でINTERVIEW
の段階に同じ結果(outcome)が存在することを意味します。異なる職種の求職申込に、それぞれ異なる面接の結果(outcome)が必要な場合は、たとえばTECHNICAL_INTERVIEW
とSTANDARD_INTERVIEW
それぞれに固有の結果(outcome)があると定義する必要があります。
今回の例では、2種類の求職申込の唯一の違いは、技術職の方には適性テスト(TEST_APTITUDE)が含まれていることです。
次に進む前に
今回、2回シリーズの記事のパート1として、ワークフロー用データベースのパターンを紹介しました。この構造を利用することによって、データベースであらゆるエンティティのライフサイクルを管理することができるようになります。
パート2では、追加の設定テーブルを使用して実際のワークフローを定義する方法を説明します。そこから、ユーザがとりうる次のステップが示されます。合わせて、BOMで組立品(assemblies)と組立部品(sub-assemblies)の再利用を厳密に制御する手法についても説明します。