Sete Regras Simples
Regra nº 1: Primeiro, os dados são estruturados posteriormente. Talvez.
Explicação
Eu recomendo não me preocupar com uma estrutura de dados declarada em um sentido ERD. Inicialmente.
Aprenda a amar o nt:unstructured (& friends) no desenvolvimento.
Eu acho que Stefano resume bem este.
Meu resultado final: A estrutura é cara e, em muitos casos, é totalmente desnecessário declarar explicitamente a estrutura para o armazenamento subjacente.
Há um contrato implícito sobre a estrutura que seu aplicativo usa inerentemente. Digamos que eu armazene a data de modificação de uma publicação do blog em uma propriedade lastModified . Meu aplicativo saberá automaticamente ler a data de modificação dessa mesma propriedade novamente. Não há necessidade de declarar isso explicitamente.
Outras restrições de dados, como restrições obrigatórias ou de tipo e valor, só devem ser aplicadas quando necessário por motivos de integridade dos dados.
Exemplo
O exemplo acima de usar um lastModified
A propriedade Date no, por exemplo, nó "publicação de blog", não significa que haja necessidade de um tipo de nó especial. Eu definitivamente usaria nt:unstructured
para os nós de postagem do meu blog pelo menos inicialmente. Já que no meu aplicativo de blogues tudo o que vou fazer é exibir a última data Modificada de qualquer maneira (possivelmente "ordenar por") eu mal me importo se é uma Data. Como eu implicitamente confio em meu aplicativo de escrita de blog para colocar uma "data" lá de qualquer maneira, não há necessidade de declarar a presença de um lastModified
no formulário a do tipo de nó.
Regra nº 2: Direcione a hierarquia de conteúdo, não deixe que isso aconteça.
Explicação
A hierarquia de conteúdo é um ativo muito valioso. Então não deixe que isso aconteça, crie. Se você não tem um "bom" nome legível por humanos para um nó, provavelmente é algo que você deveria reconsiderar. Os números arbitrários raramente são um "bom nome".
Embora possa ser extremamente fácil colocar rapidamente um modelo relacional existente num modelo hierárquico, deve-se pensar um pouco nesse processo.
Na minha experiência, se você pensar no controle de acesso e na contenção, geralmente bons drivers para a hierarquia de conteúdo. Pense nisso como se fosse seu sistema de arquivos. Talvez até use arquivos e pastas para modelá-los em seu disco local.
Pessoalmente, prefiro as convenções de hierarquia do que o sistema de datilografia de nó em muitos casos inicialmente, e introduzo a datilografia mais tarde.
Exemplo
Eu modelaria um simples sistema de blogues como segue. Por favor, note que inicialmente eu nem me importo com os respectivos tipos de nó que eu uso neste momento.
/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
Penso que uma das coisas que se tornam evidentes é que todos compreendemos a estrutura do conteúdo baseada no exemplo, sem mais explicações.
O que pode ser inesperado inicialmente é por que eu não armazenaria os "comentários" com o "post", que é devido ao controle de acesso que eu gostaria que fosse aplicado de forma razoavelmente hierárquica.
Usando o modelo de conteúdo acima, posso permitir que o usuário "anônimo" "crie" comentários, mas manter o usuário anônimo em uma base somente leitura para o restante do espaço de trabalho.
Regra nº 3: Os espaços de trabalho são para clone(), merge() e update().
Explicação
Se você não usar clone()
, merge()
ou update()
métodos no seu aplicativo, um único espaço de trabalho provavelmente é o caminho a seguir.
"Nós correspondentes" é um conceito definido na especificação do JCR. Basicamente, ele se resume a nós que representam o mesmo conteúdo, em diferentes espaços de trabalho chamados .
O JCR apresenta o conceito muito abstrato de espaços de trabalho, o que deixa muitos desenvolvedores pouco claros sobre o que fazer com eles. Gostaria de propor que se pusesse a sua utilização de espaços de trabalho à prova seguinte.
Se você tiver uma sobreposição considerável de nós "correspondentes" (essencialmente os nós com a mesma UUID) em vários espaços de trabalho, provavelmente você colocará os espaços de trabalho em bom uso.
Se não houver sobreposição de nós com o mesmo UUID, você provavelmente está usando espaços de trabalho.
Os espaços de trabalho não devem ser usados para o controle de acesso. A visibilidade do conteúdo para um grupo específico de usuários não é um bom argumento para separar as coisas em espaços de trabalho diferentes. O JCR apresenta "Controle de acesso" no repositório de conteúdo para fornecer isso.
Espaços de trabalho são o limite para referências e consultas.
Exemplo
Use espaços de trabalho para coisas como:
- v1.2 do seu projeto vs. a v1.3 do seu projeto
- um estado de "desenvolvimento", "controle de qualidade" e "publicado" do conteúdo
Não use espaços de trabalho para coisas como:
- diretórios iniciais do usuário
- conteúdo distinto para públicos-alvo diferentes, como público, privado, local, …
- caixas de entrada de email para usuários diferentes
Regra nº 4: Cuidado com irmãos de mesmo nome.
Explicação
Embora os Irmãos com Mesmo nome (SNS) tenham sido introduzidos na especificação para permitir a compatibilidade com estruturas de dados projetadas para e expressas por meio de XML e, portanto, sejam extremamente valiosas para o JCR, os SNS vêm com uma sobrecarga e complexidade substanciais para o repositório.
Qualquer caminho no repositório de conteúdo que contenha um SNS em um de seus segmentos de caminho se torna muito menos estável, se um SNS for removido ou reorganizado, isso terá impacto nos caminhos de todos os outros SNS e seus filhos.
Para importação de XML ou interação com SNS XML existentes, talvez seja necessário e útil, mas nunca usei SNS, e nunca usarei em meus modelos de dados de "campo verde".
Exemplo
Utilização
/content/myblog/posts/what_i_learned_today
/content/myblog/posts/iphone_shipping
em vez de
/content/blog[1]/post[1]
/content/blog[1]/post[2]
Regra nº 5: Referências consideradas prejudiciais.
Explicação
As referências implicam integridade referencial. Eu acho importante entender que as referências não apenas aumentam o custo para o repositório que gerencia a integridade referencial, mas também são caras do ponto de vista de flexibilidade de conteúdo.
Pessoalmente, tenho certeza de que só uso referências quando realmente não consigo lidar com uma referência perigosa e, de outra forma, usar um caminho, um nome ou um UUID de string para fazer referência a outro nó.
Exemplo
Vamos supor que permita "referências" de um documento (a) a outro documento (b). Se eu modelar essa relação usando propriedades de referência, significa que os dois documentos estão vinculados em um nível de repositório. Não consigo exportar/importar documento (a) individualmente, pois o destino da propriedade de referência pode não existir. Outras operações como mesclar, atualizar, restaurar ou clonar também são afetadas.
Assim, eu modelaria essas referências como "referências fracas" (no JCR v1.0, isso basicamente se resume a propriedades de sequência que contêm o uuid do nó de destino) ou simplesmente usaria um caminho. Às vezes, o caminho é mais significativo para começar.
Eu acho que existem casos de uso em que um sistema realmente não pode funcionar se uma referência estiver em perigo, mas eu simplesmente não consigo encontrar um bom exemplo "real" mas simples de minha experiência direta.
Regra nº 6: Os arquivos são arquivos.
Explicação
Se um modelo de conteúdo expor algo que remotamente cheiros como um arquivo ou uma pasta que tento usar (ou estender de) nt:file
, nt:folder
e nt:resource
.
Na minha experiência, muitos aplicativos genéricos permitem a interação com nt:folder e nt:files implicitamente e sabem como lidar e exibir esse evento se forem enriquecidos com informações meta adicionais. Por exemplo, uma interação direta com implementações de servidor de arquivos como CIFS ou WebDAV sentados sobre o JCR torna-se implícita.
Penso que, como regra geral, se pode usar o seguinte: Se precisar armazenar o nome do arquivo e o tipo MIME, nt:file
/ nt:resource
é uma correspondência muito boa. Se você puder ter vários "arquivos" e o nt:folder é um bom local para armazená-los.
Se você precisar adicionar metainformações para seu recurso, digamos uma propriedade "author" ou "description", estenda nt:resource
não a nt:file
. Raramente estendi o nt:file e estendi com frequência nt:resource
.
Exemplo
Vamos supor que alguém gostaria de carregar uma imagem em uma entrada de blog em:
/content/myblog/posts/iphone_shipping
e talvez a reação inicial do intestino fosse adicionar uma propriedade binária contendo a imagem.
Embora certamente haja bons casos de uso para usar apenas uma propriedade binária (digamos que o nome seja irrelevante e o tipo MIME esteja implícito), nesse caso, eu recomendaria a seguinte estrutura para o meu exemplo de blog.
/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]
Regra nº 7: As IDs são más.
Explicação
Em bancos de dados relacionais, as IDs são um meio necessário para expressar relações, de modo que as pessoas tendem a usá-las em modelos de conteúdo também. Principalmente pelas razões erradas.
Se o modelo de conteúdo estiver cheio de propriedades que terminam em "Id", você provavelmente não está aproveitando a hierarquia corretamente.
É verdade que alguns nós precisam de uma identificação estável durante todo o seu ciclo de vida. Muito menos do que você pode pensar. mix:referenceable fornece um mecanismo desse tipo integrado no repositório, de modo que não há necessidade de criar um meio adicional de identificar um nó de maneira estável.
Lembre-se também de que os itens podem ser identificados por caminho e, tanto quanto os "links simbólicos" fizerem mais sentido para a maioria dos usuários do que os links rígidos em um sistema de arquivos unix, um caminho faz sentido para a maioria dos aplicativos se referirem a um nó de destino.
Mais importante, é mix:referenciável, o que significa que pode ser aplicado a um nó no momento em que você realmente precisa referenciá-lo.
Portanto, digamos que apenas porque você gostaria de fazer referência a um nó do tipo "Documento" não significa que seu tipo de nó "Documento" tenha que se estender de mix:referenceable de forma estática, já que ele pode ser adicionado a qualquer instância do "Documento" dinamicamente.
Exemplo
Utilização:
/content/myblog/posts/iphone_shipping/attachments/front.jpg
em vez de:
[Blog]
-- blogId
-- author
[Post]
-- postId
-- blogId
-- title
-- text
-- date
[Attachment]
-- attachmentId
-- postId
-- filename
+ resource (nt:resource)