データモデリング - David Nuescheler のモデル data-modeling-david-nuescheler-s-model
ソース source
以下は、David Nuescheler 氏が発表したアイデアとコメントである。
Day Software AG の共同創設者で CTO は、2010 年にAdobeが買収した、グローバルなコンテンツ管理とコンテンツインフラストラクチャソフトウェアの大手プロバイダです。 現在は、Adobeのエンタープライズテクノロジー担当副社長であり、JSR-170(Java Content Repository(JCR) アプリケーションプログラミングインターフェイス (API)) の開発をリードしています。
詳しくは、https://wiki.apache.org/jackrabbit/DavidsModel を参照してください。
David の紹介 introduction-from-david
様々な議論で、開発者は JCR がコンテンツモデリングに関して示した機能や特徴にやや不安を感じていることがわかりました。 リポジトリ内のコンテンツをモデル化する方法と、あるコンテンツモデルが他のコンテンツモデルよりも優れている理由に関するガイドはまだありません。また、経験もほとんどありません。
リレーショナルな世界では、ソフトウェア業界はデータのモデル化に関する多くの経験を持っていますが、コンテンツリポジトリ領域の初期段階に入っています。
コンテンツをモデル化する方法についての私の個人的な意見を述べ、「私の意見」だけでなく、より一般的に適用できるものに、いつか開発者コミュニティにとってより意味のあるものに成長していくことを願って、この空白を埋めたい。 私の早く進化する最初の突き刺しを考えてみてください
簡単な 7 つのルール seven-simple-rules
ルール 1:データが第一、構造は二の次(おそらくですが)。 rule-data-first-structure-later-maybe
説明 explanation-1
ERD の意味で宣言されたデータ構造について心配しないことをお勧めします。 最初は
開発の際に nt:unstructured (& friends) を愛する方法を学びます。
これについては Stefano さんがよくまとめてくれると思います。
最終的な結果:構造は高価で、多くの場合、基盤となるストレージに対して構造を明示的に宣言する必要はありません。
アプリケーションが本質的に使用する構造に関する暗黙の契約があります。 例えば、ブログ投稿の変更日を lastModified プロパティに保存するとします。 アプリは、同じプロパティから再度変更日を読み取ることを自動的に知っているので、明示的にそれを宣言する必要はありません。
必須やタイプ、値の制約などのその他のデータ制約は、データの整合性のために必要な場合にのみ適用する必要があります。
例 example-1
lastModified
日付プロパティを使った前述の例は「blog post」ノードの例であり、特別なノードタイプが必要であることを意味しているわけではありません。私は、少なくとも最初は必ず nt:unstructured
をブログ投稿ノード用に使います。私のブログアプリケーションでは、lastModified の日付を表示するだけなので(「order by」の場合もある)、それが Date であるかどうかはほとんど気にしません。私はブログを書くアプリケーションが「Date」を入れてくれることを暗黙的に信じているので、nodetype という形式で lastModified
日付の存在を宣言する必要は実際にはありません。
ルール 2:コンテンツ階層は手動で設計し、成り行き任せにしない。 rule-drive-the-content-hierarchy-don-t-let-it-happen
説明 explanation-2
コンテンツ階層は非常に役立つアセットです。そのため、ただ成り行きに任せるのではなく、しっかりと設計しましょう。人間が読み取れる「良い」ノード名がない場合は、それを考え直す必要があります。任意の数字は、「良い名前」とは言えません。
既存のリレーショナルモデルを階層モデルにすばやく配置するのは非常に簡単ですが、その過程で何らかの考えを持つべきです。
私の経験では、アクセス制御とコンテインメントを考える人は、通常、コンテンツ階層のための良いドライバーです。 ファイルシステムのように考えてください。 ローカルディスク上のモデルを作成する際に、ファイルやフォルダを使用する場合もあります。
個人的には、最初に多くの場合、ノードタイピングシステムよりも階層規則を好み、後でタイピングを導入します。
例 example-2
以下のような単純なブログシステムをモデル化します。この時点で使用する個々のノードタイプについて、最初は気にしてさえいないことに注目してください。
/content/myblog
/content/myblog/posts
/content/myblog/posts/what_i_learned_today
/content/myblog/posts/iphone_shipping
/content/myblog/comments/iphone_shipping/i_like_it_too
/content/myblog/comments/iphone_shipping/i_like_it_too/i_hate_it
ここで明らかになるのは、コンテンツの構造が、例に基づいて、追加説明なしで理解できることです。
最初は予期しないことがありますが、なぜ「コメント」を「投稿」と共に保存しないのですか。これは、アクセス制御を合理的に階層的に適用したいからです。
上記のコンテンツモデルを使用すると、「匿名」ユーザーに対して「コメントの作成」を簡単に許可できますが、残りのワークスペースでは読み取り専用の状態に保ちます。
ルール#3:ワークスペースは clone()、merge()、update() 用です。 rule-workspaces-are-for-clone-merge-and-update
説明 explanation-3
アプリケーションで clone()
、merge()
、update()
などのメソッドも使用しない場合は、単一のワークスペースが有効な方法かもしれません。
「対応するノード」は、JCR 仕様で定義された概念です。 つまり、異なるいわゆるワークスペースで、同じコンテンツを表すノードにまとめられます。
JCR は、Workspaces の非常に抽象的な概念を導入し、多くの開発者は、Workspaces を使用して何をするかについて不明確にしています。 今後、以下のようなテストを行うためのワークスペースの活用を提案します。
複数のワークスペースで「対応する」ノード(基本的には同じ UUID を持つノード)の重複が大きい場合は、ワークスペースを適切に使用できるように配置する必要があります。
同じ UUID を持つノードの重複がない場合は、ワークスペースを使用しない可能性があります。
ワークスペースは、アクセス制御には使用しないでください。 特定のユーザーグループのコンテンツを表示することは、物を異なるワークスペースに分ける良い議論ではありません。 JCR は、コンテンツリポジトリで「アクセス制御」を使用してこれを提供します。
ワークスペースは、参照とクエリの境界です。
例 example-3
ワークスペースは次のような用途に使用します。
- プロジェクトの v1.2 とプロジェクトの v1.3
- コンテンツの「開発」、「QA」および「公開済み」状態
以下のような用途にワークスペースを使用しないでください。
- ユーザーのホームディレクトリ
- 公開、非公開、ローカルなど、様々なターゲットオーディエンス向けの個別コンテンツ。
- 様々なユーザー向けのメール受信ボックス
ルール#4:同じ名前の兄弟に注意してください。 rule-beware-of-same-name-siblings
説明 explanation-4
SNS(Same Name Siblings) が仕様に導入され、XML で設計され、表現されるデータ構造との互換性が可能になりましたが、JCR にとって非常に重要な機能です。SNS には、リポジトリのオーバーヘッドと複雑さが大幅に伴います。
いずれかのパスセグメントに SNS が含まれているコンテンツリポジトリへのパスは、安定性が大幅に低下します。SNS が削除または並べ替えられると、他のすべての SNS とその子のパスに影響を与えます。
XML のインポートや既存の XML とのインタラクションに必要で役に立つ可能性がありますが、SNS を使ったことはありません。また、「緑のフィールド」データモデルには決して入りません。
例 example-4
使用方法
/content/myblog/posts/what_i_learned_today
/content/myblog/posts/iphone_shipping
の代わりに
/content/blog[1]/post[1]
/content/blog[1]/post[2]
ルール#5:参照は有害と見なされます。 rule-references-considered-harmful
説明 explanation-5
参照は参照整合性を意味します。 参照は、参照整合性を管理するリポジトリに追加のコストをかけるだけでなく、コンテンツの柔軟性の観点からもコストがかかるということを理解することが重要です。
個人的には、参照を使用するのは必ずしも未設定の参照を扱えない場合に限ります。それ以外の場合は、パス、名前、または文字列 UUID を使用して別のノードを参照します。
例 example-5
ドキュメント (a) から別のドキュメント (b) への「参照」を許可するとします。 参照プロパティを使用してこの関係をモデル化する場合、2 つのドキュメントはリポジトリレベルでリンクされます。 参照プロパティのターゲットが存在しない可能性があるので、ドキュメント (a) を個別に書き出し/読み込むことはできません。 結合、更新、リストア、クローンなどの他の操作も影響を受けます。
そのため、これらの参照を「弱い参照」(JCR v1.0 では、基本的にはターゲットノードの uuid を含む文字列プロパティにボールダウンします)としてモデル化するか、単にパスを使用します。 最初にパスが意味を持つ場合もあります。
参照がぶら下がっているとシステムが機能しないと思うのですが、直接体験からは、良い「現実」で単純な例を思い付くことはできません。
ルール 6:ファイルはファイルである。 rule-files-are-files
説明 explanation-6
コンテンツモデルがファイルまたはフォルダーのように 感じられるもの を見せている場合、私は nt:file
、nt:folder
、nt:resource
の使用(または拡張)を試みます。
私の経験では、多くの汎用アプリケーションで、nt:folder および nt:files とのインタラクションが暗黙的に許可されており、メタ情報が追加された場合にイベントを処理して表示する方法が認識されています。例えば、JCR をベースとしている CIFS や WebDAV のようなファイルサーバー実装との直接のインタラクションは暗黙となります。
私は経験則として、ファイル名と MIME タイプを保存する必要がある場合は、 nt:file
/ nt:resource
がとても良いマッチだと思います。複数の「ファイル」がある場合は、nt:folder は格納場所に適しています。
リソースのメタ情報を追加する必要がある場合(例えば、「author」プロパティや「description」プロパティなど)、nt:file
ではなく、nt:resource
を拡張します。nt:file を拡張することはほとんどなく、nt:resource
を頻繁に拡張します。
例 example-6
次の場所にあるブログエントリに画像をアップロードするとします。
/content/myblog/posts/iphone_shipping
そして、最初の腸反応は、画像を含むバイナリプロパティを追加することです。
この場合は、バイナリプロパティだけを使用する良い使用例が確かにありますが(例えば、名前は無関係で、mime タイプは暗黙的です)、自分のブログの例では次の構造をお勧めします。
/content/myblog/posts/iphone_shipping/attachments [nt:folder]
/content/myblog/posts/iphone_shipping/attachments/front.jpg [nt:file]
/content/myblog/posts/iphone_shipping/attachments/front.jpg/jcr:content [nt:resource]
ルール#7:ID は悪いです。 rule-ids-are-evil
説明 explanation-7
リレーショナルデータベースでは、ID は関係を表すのに必要な手段なので、コンテンツモデルでも使用される傾向があります。 主に誤った理由から。
コンテンツモデルが「ID」で終わるプロパティでいっぱいの場合は、階層を正しく活用していない可能性があります。
実際、一部のノードは、ライブサイクル全体で安定した識別を必要とします。 思ったよりずっと少ない。 mix:referenceable はリポジトリに組み込まれたそのようなメカニズムを提供するので、ノードを安定して識別する追加の手段を考え出す必要はありません。
また、項目はパスで識別でき、「symlinks」は unix ファイルシステムのハードリンクよりも多くのユーザーにとって意味を持つので、パスはターゲットノードを参照するほとんどのアプリケーションにとって意味を持ちます。
さらに重要なことは、mix:referenceable であるということです。つまり、本当に参照する必要がある時点でノードに適用できるということです。
よって、タイプが「ドキュメント」であるノードを参照可能にしたいからといって、「ドキュメント」ノードタイプを静的な方法で mix:referenceable から拡張しなければならないということにはなりません。「ドキュメント」の任意のインスタンスに動的に追加できるからです。
例 example-7
使用方法:
/content/myblog/posts/iphone_shipping/attachments/front.jpg
以下の代わりに使用します。
[Blog]
-- blogId
-- author
[Post]
-- postId
-- blogId
-- title
-- text
-- date
[Attachment]
-- attachmentId
-- postId
-- filename
+ resource (nt:resource)