ワークフローパターン(1/2) -「状態」の管理-

今回はFileMaker固有の機能ではなく、データモデルについての記事をご紹介します。最近業務でワークフローエンジンを作る必要があり、この記事を参考にしました。
ご紹介するVertabeloのサイトでは、この他にもデータモデル設計に関する興味深い記事を多く公開しています。興味のある方はぜひ参照してください。

Vertabeloはデータモデル設計のコラボレーション作業を支援する有償のWebサービスです。Webブラウザ上でER図を作成・編集し、結果をSQLのDDL(CREATE TABLE文)として出力するなどもできます。

なお、この作成したCREATE TABLE文をFileMakerでどう活用するかが問題ですが、例えば以下のような方法があります。

  • MySQLなどにテーブルを作成し、ESSとしてFileMakerから接続する
  • FileMaker ProでODBC共有をオンにしてデータソースとし、(ODBCクライアント設定をした上で)[SQLを実行]スクリプトステップでCREATE TABLE文を実行する

Vertabelo

The Workflow Pattern. Part 1

Using Workflow Patterns to Manage the State of Any Entity

(元記事はこちら)


Jean-Marc ReynaudJean-Marc Reynaud
フリーランスデータモデラー
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_ACCEPTEDJOB_OFFER_DECLINEDの2つの結果を持ちます。

もう一つの結果は、職種の提示が取り下げられることです。取り下げられた理由は補足情報に記録することができます。これらの理由を上記のリストに追加するだけでは、エンドユーザが論理的な選択を行うことはできません。

したがって、状態、結果、補足が複雑になればなるほど、 プロセスワークフローを定義する必要性が高くなります。

プロセス、状態、結果を整理する

データをモデル化しようとする前に、データに何が起こっているのかを理解することが重要です。最初は、種別にプロセス状態結果という厳密な階層構造があると考えるでしょう。

上記の例を詳しく見ると、INVITED_TO_INTERVIEWJOB_OFFER_MADEという2つの状態は、ACCEPTEDDECLINEDという同じ結果を​​持てるということがわかります。これは、状態と結果に多対多の関係があることを示しています。これは他のいくつかの状態、結果、詳細にも当てはまります。

概念レベルでは、メタデータに実際に起こっていることは以下の通りです。

class conceptual

標準的なアプローチでこのモデルを現実世界に変換する場合は、 ProcessStateOutcomeQualifierという4つのテーブルを作るでしょう。 また、合わせて 多対多の関係を解決するために、Process_StateState_OutcomeOutcome_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_typeworkflow_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_APPLICATIONTECHNICAL_JOB_APPLICATIONの2つのプロセス(process)はINTERVIEWという状態(state)を持ちます。次に、 INTERVIEWという状態には、PASSEDFAILEDCANDIDATE_CANCELLEDNO_SHOWという結果(outcome)が定義されています。

プロセスに状態(state)を使用すると、それが既に組立品であるため、自動的にその子供である結果(outcome)をセットで持つことになります。これは両方のタイプの求職申込でINTERVIEWの段階に同じ結果(outcome)が存在することを意味します。異なる職種の求職申込に、それぞれ異なる面接の結果(outcome)が必要な場合は、たとえばTECHNICAL_INTERVIEWSTANDARD_INTERVIEWそれぞれに固有の結果(outcome)があると定義する必要があります。

今回の例では、2種類の求職申込の唯一の違いは、技術職の方には適性テスト(TEST_APTITUDE)が含まれていることです。

次に進む前に

今回、2回シリーズの記事のパート1として、ワークフロー用データベースのパターンを紹介しました。この構造を利用することによって、データベースであらゆるエンティティのライフサイクルを管理することができるようになります。

パート2では、追加の設定テーブルを使用して実際のワークフローを定義する方法を説明します。そこから、ユーザがとりうる次のステップが示されます。合わせて、BOMで組立品(assemblies)と組立部品(sub-assemblies)の再利用を厳密に制御する手法についても説明します。

Leave a Reply