現在表示中:

ソース

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

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

詳しくは、http://wiki.apache.org/jackrabbit/DavidsModel を参照してください。

David からのあいさつ

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

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

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

注意:

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

簡単な 7 つのルール

ルール 1:データが第一、構造は二の次(おそらくですが)。

説明

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

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

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

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

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

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

上記の例のように「ブログ投稿」ノードなどに lastModified 日付プロパティを使用することは、特殊なノードタイプが必要ということではありません。私だったら、少なくとも最初は、ブログ投稿ノードには間違いなく nt:unstructured を使用します。私のブログアプリケーションでおこなおうとしていることは、何らかの方法(並べ替えの基準としてなど)で lastModified の日付を表示することなので、それが日付であるかどうかさえも気になりません。私のブログ作成アプリケーションに対しては、「日付」を何らかの方法で入れてくれると暗黙の信頼を寄せているので、ノードタイプの形式で 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() のどのメソッドも使用しない場合は、単一のワークスペースが有効な方法かもしれません。

「対応するノード」は、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:folder および nt:resource を使用するか、それらから拡張しようと試みます。

私の経験では、多くの汎用アプリケーションで、nt:folder および nt:files とのインタラクションが暗黙的に許可されており、メタ情報が追加された場合にイベントを処理して表示する方法が認識されています。例えば、JCR をベースとしている CIFS や WebDAV のようなファイルサーバー実装との直接のインタラクションは暗黙となります。

私の経験からすると、ファイル名と MIME タイプを格納する必要がある場合は、nt:filent:resource が適しています。複数の「ファイル」を持つ可能性がある場合は、nt:folder に格納するとよいでしょう。

例えば「作成者」や「説明」プロパティのように、リソース用にメタ情報を追加する必要がある場合は、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)

本作品は Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License によってライセンス許可を受けています。  Twitter™ および Facebook の投稿には、Creative Commons の規約内容は適用されません。

法律上の注意   |   プライバシーポリシー