データのモデル化 - David Nuescheler のモデル

ソース

以下の詳細は、David Nuescheler 氏が表明している見解です。

同氏は、アドビが 2010 年に買収した、グローバルなコンテンツ管理およびコンテンツインフラストラクチャソフトウェアの大手プロバイダーである Day Software AG 社の共同創立者兼 CTO です。現在は、アドビのフェローであり、Enterprise Technology のバイスプレジデントです。また、コンテンツ管理の技術標準である Java コンテンツリポジトリ(JCR)アプリケーションプログラミングインターフェイス(API)、JSR-170 開発の第一人者でもあります。

https://wiki.apache.org/jackrabbit/DavidsModelで更新情報を見ることもできます。

David からのあいさつ

様々な話し合いの中で、コンテンツのモデル化という点では、JCR の機能に関して開発者たちが幾分不安を感じていることがわかりました。リポジトリ内のコンテンツをモデル化する方法や、コンテンツモデルの中に優劣が存在する理由については、まだ何の指針もなく、経験もほとんどありません。

リレーショナルな世界では、ソフトウェア業界にはデータのモデル化に関して多くの経験がありますが、コンテンツリポジトリに関しては、まだ初期段階です。

コンテンツをモデル化する方法について私の個人的意見を表明することにより、この空白を埋める試みを始めたいと思います。これがいずれ開発者コミュニティにとってより有意義なものへと変化し、単なる「私の意見」ではなく、より一般的なものとなることを期待しています。よって、これは私の最初の挑戦であり、今後急速に進化するものとお考えください。

メモ

免責事項:このガイドラインは、私個人の見解であり、賛否が分かれる場合もあります。内容について意見を交わし、改善することを期待しています。

簡単な 7 つのルール

ルール#1:最初にデータを、後で構造化します。たぶん。

説明

ERD の意味では、宣言されているデータ構造について気にしないことをお勧めします。ただし、最初のうちは、です。

開発の際は、nt:unstructured(およびその仲間たち)を好きになるようにしてください。

これについては Stefano さんがよくまとめてくれると思います。

私の結論としては、構造はコストがかかるものであり、多くの場合、基になるストレージに対して構造を明示的に宣言することはまったく必要ありません。

アプリケーションで使用することになっている構造に関しては、暗黙の契約があります。例えば、ブログの投稿の変更日を lastModified プロパティに格納するとします。アプリケーションでは、その同じプロパティから再度変更日を読み取ることが自動的に認識されるので、明示的に宣言する必要はまったくありません。

必須などの追加のデータ制約や、タイプや値の制約は、データの整合性のために必要な場合にのみ適用します。

上記の例で、「ブログ投稿」ノードなどでlastModified Dateプロパティを使用する場合は、特別なノードタイプが必要であるとは限りません。 最初はnt:unstructuredをブログ投稿ノードに必ず使います。 ブログアプリでは、lastModified日付を表示するだけなので(「順番」を付けても)、日付になってもほとんど気にしません。 私はブログ書き出しのアプリケーションに"date"を付けるのを暗黙的に信じているので、nodetypeの形式でlastModified日付の存在を宣言する必要はありません。

ルール#2:コンテンツ階層を推進し、それを実現させない。

説明

コンテンツ階層は非常に価値の高いアセットです。だから、それを実現させるのはやめ、設計してみてください。 ノードに「良い」人間が読み取り可能な名前がない場合は、それを再考する必要があると思います。 任意の数字が「良い名前」とはほとんど言えません。

既存のリレーショナルモデルをすぐに階層モデルに変換できれば非常に簡単かもしれませんが、その際は多少の配慮が必要です。

私の経験では、アクセス制御および抑制によってコンテンツ階層を駆動させるという考えが多いようです。コンテンツ階層を、自分のファイルシステムと考えてください。ファイルやフォルダーを使用して、ローカルディスク上でモデル化することも可能です。

個人的には、多くの場合、最初はノードタイピングシステム経由で階層を変換し、後からタイピングを導入する方法を好みます。

注意

コンテンツリポジトリの構造化の方法はパフォーマンスにも影響を及ぼす可能性があります。最適なパフォーマンスを確保するために、コンテンツリポジトリ内の個々のノードに接続される子ノードの数は、通常 1,000 個以下にする必要があります。

CRXで処理できるデータ量は?を参照してください。 を参照してください。

以下のような単純なブログシステムをモデル化します。この時点で使用する個々のノードタイプについて、最初は気にしてさえいないことに注目してください。

/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

私が明らかになったのは、この例に基づく内容の構造を理解している人が、それ以上の説明をすることなくいることです。

「コメント(comments)」を「投稿(post)」と共に格納しないことを最初は疑問にお思いかもしれませんが、これは、アクセス制御を合理的に階層化された方法で適用したいからです。

上記のコンテンツモデルを使用すると、「匿名の」ユーザーにコメントの「作成」を簡単に許可する一方で、匿名のユーザーを残りのワークスペースで読み取り専用ベースに保つことができます。

ルール 3:ワークスペースは clone()、merge() および update() 用。

説明

アプリケーションでclone()merge()、またはupdate()メソッドを使用しない場合は、1つのワークスペースがおそらく使用できます。

「対応するノード」は、JCR 仕様で定義されている概念です。結局のところは、本質的に、それぞれ異なるいわゆるワークスペース内の、同じコンテンツを表すノードのことです。

JCR ではワークスペースの概念が非常に抽象的に紹介されているので、何に使用すればよいのか、開発者には不明瞭なままになっています。ワークスペースを、以下のようにテスト目的で使用することを提案します。

「対応する」ノード(基本的には同じ UUID を持つノード)が、複数のワークスペースに多数重複している場合は、ワークスペースをうまく使用している可能性が高いでしょう。

同じ UUID を持つノードの重複がまったくない場合は、ワークスペースの使い方が誤っている可能性があります。

ワークスペースは、アクセス制御には使用しないでください。特定のユーザーグループにコンテンツを表示することは、別々のワークスペースに分割する十分な根拠とはなりません。JCR には、このためにコンテンツリポジトリの「アクセス制御」機能が用意されています。

ワークスペースは、参照およびクエリの境界です。

ワークスペースは、次のようなものに使用します。

  • プロジェクトの v1.2 とプロジェクトの v1.3
  • コンテンツの「開発」、「QA」および「公開済み」の状態

ワークスペースは、次のようなものには使用しないでください。

  • ユーザーのホームディレクトリ
  • 公開、非公開、ローカルなど、様々なターゲットオーディエンスの明確なコンテンツ
  • 様々なユーザーのメールインボックス

ルール 4:同じ名前の兄弟に注意。

説明

同じ名前の兄弟(SNS)は、XML 用に設計され、XML で表現されているデータ構造との互換性を得るために仕様に導入されたので、JCR にとって非常に有益ではありますが、リポジトリのオーバーヘッドが大きく、かなり複雑です。

いずれかのパスセグメントに SNS が含まれているコンテンツリポジトリのパスは安定性が非常に低くなり、1 つの SNS が削除されるか並べ替えられると、その他すべての SNS およびそれぞれの子のパスに影響します。

XML の読み込みや既存の XML とのインタラクションのために SNS が必要かつ便利な場合もありますが、私は SNS を使用したことはなく、ゼロから始めるデータモデルでは今後も使用することはありません。

以下のように

/content/myblog/posts/what_i_learned_today
/content/myblog/posts/iphone_shipping

以下の代わりに使用します。

/content/blog[1]/post[1]
/content/blog[1]/post[2]

ルール 5:参照は有害と見なされる。

説明

参照は参照整合性を暗示します。参照を使用すると、参照整合性を管理するリポジトリのコストが増加するだけでなく、コンテンツの柔軟性という点からもコストがかかることを理解することが重要です。

個人的には、定まっていない参照をどうしても処理できない場合にのみ参照を使用し、それ以外の場合はパス、名前、文字列 UUID のいずれかを使用して別のノードを参照するようにしています。

ドキュメント(a)からドキュメント(b)への「参照」を許可すると仮定しましょう。参照プロパティを使用してこの関係をモデル化する場合、2 つのドキュメントはリポジトリレベルでリンクされるということです。参照プロパティのターゲットが存在しない可能性があるので、ドキュメント(a)の個別の書き出しや読み込みはできません。統合、更新、復元、クローンなど、その他の操作も同様に影響を受けます。

したがって、私はこれらの参照を「弱い参照」(JCR v1.0 では、結局のところターゲットノードの UUID を含む文字列プロパティ)としてモデル化するか、単純にパスを使用します。そもそも、パスのほうが有意である場合もあります。

参照が定まっていないとシステムが機能しない場合があると思いますが、私の実体験からは、十分に「現実的」で、かつシンプルな例は、思いつきません。

ルール#6:ファイルはファイルです。

説明

コンテンツモデルが、ファイルやフォルダーのように​​においても、nt:filent:foldernt: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を拡張します。

誰かが以下のブログに画像をアップロードしたいと仮定します。

/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 は悪である。

説明

リレーショナルデータベースでは、ID は関係を表すのに必要な手段なので、コンテンツモデルでも ID が使用される傾向があります。ただし、多くは誤った理由によるものです。

コンテンツモデルがプロパティでいっぱいで、「ID」で終わっている場合は、階層が適切に活用されていない可能性があります。

確かに、一部のノードでは、ライフサイクル全体に渡って安定した識別が必要です。ただし、そのようなノードはそれほど多くありません。mix:referenceable によって、このようなメカニズムがリポジトリに組み込まれるので、安定した方法でノードを識別する方法を追加で考え出す必要はありません。

項目はパスによっても識別できることも心に留めておいてください。UNIX ファイルシステムで「シンボリックリンク」が多くのユーザーにとってハードリンクよりはるかに大きな意味を持つのと同様に、ターゲットノードを参照する場合は、ほとんどのアプリケーションでパスが意味を持ちます。

さらに重要なのは、mix:referenceableです。これは、実際に参照する必要がある時点で、ノードに適用できることを意味します。

よって、タイプが「ドキュメント」であるノードを参照可能にしたいからといって、「ドキュメント」ノードタイプを静的な方法で mix:referenceable から拡張しなければならないということにはなりません。「ドキュメント」の任意のインスタンスに動的に追加できるからです。

以下のように:

/content/myblog/posts/iphone_shipping/attachments/front.jpg

以下の代わりに使用します。

[Blog]
-- blogId
-- author
[Post]
-- postId
-- blogId
-- title
-- text
-- date
[Attachment]
-- attachmentId
-- postId
-- filename
+ resource (nt:resource)

このページ

Adobe Maker Awards Banner

Time to shine!

Apply now for the 2021 Adobe Experience Maker Awards.

Apply now
Adobe Maker Awards Banner

Time to shine!

Apply now for the 2021 Adobe Experience Maker Awards.

Apply now