By Deane Barker | May 20, 2007 | 5 Comments
Here’s something I don’t see nearly enough in content management systems: subcontent. This is when a content object contains other content objects as children. I don’t think I’ve ever built a content-managed site where I haven’t (1) used this when it was available, or (2) wished for it when it wasn’t.
It’s so common for a conceptual object in a content model to be composed of other content. This mirrors a relational database — the most common relationship between tables in a database is a one-to-many relationship where one thing in one table is related to many things in another table.
The same concept is at work here. Having a set of content objects existing within another is like an implicit one-to-many relationship. The parent is related to many children, and all of the children are related to one parent.
Most content management systems have some form of content tree, but often they fall into the “folder trap,” where they use the folder-and-file metaphor from operating systems. You can create folders, which then contain content.
I maintain that this is a mistake for a very important reason: the folder is not a content object itself. It’s a folder — some arbitrary structure thought up by the architects of the CMS, and it can’t carry content-based data or be managed like content (subject to workflow, versioning, etc.).
In practice, a content tree should effectively be made up of nothing but content objects stacked on top of one another. There are no “folders,” unless you want to create a “folder-like” content object. Each node in the tree is a content object, which has a content object as a parent and can have multiple content objects as children.
I was recently working with a magazine publisher. We discussed their content model, and it worked out like this:
A publication has multiple issues which each have multiple sections which each have multiple articles which each may have multiple subarticles. It was both highly relational and purely hierarchical — a perfect example of the need for subcontent.
With subcontent, this is simple. You have a publication content object which contains multiple issue content objects, etc. Since the tree is made up of content itself, representing these relationships is trivial. An article belongs to the issue which is its parent. Relationships are derived from their position in the tree.
If not for subcontent, then I have to maintain an explicit reference in each content object to define what other object it belongs to. Far from the simplicity of just putting content somewhere, now I have to have a content selector interface widget to go find the parent piece of content. The user experience also suffers because a piece of content could be the “child” of something way across the tree. The concept of “parentage” suffers because the parent and the child are not “geographically” related in any way in the administration interface.
Additionally, referential integrity is tightened with subcontent. Since you can’t delete a parent without deleting all of its children, you ensure there are no orphan records floating around.
Why does this all make so much sense? Because it’s correct from an object oriented perspective, with which we’re all familiar. The Composite Pattern says that an object can contain another object. Using this, you put together complex programming objects to represent complex concepts. The same is true of content modeling — you start gluing together content to create more complicated content.
To really do this right, there are some best practices:
- You need to be able to specify what type of content can go “under” what type of other content. Referring back to my magazine example, it wouldn’t do us much good to have a publication appear under an issue.
You can either make these limitations global, or build them into the permissions model. Maybe a normal editor can’t put a downloadable file under an article, but the webmaster can.
- Watch out for recursive references. If Object A is the parent of Object B, ensure there’s no way Object A can also be “downhill” from Object B.
- You need to consider the ordering of subcontent. Specifically, you need to provide arbitrary ordering. There needs to be a way for a content manager to specify the order in which subcontent appears under a parent.
(For the record, you need to allow arbitrary ordering even if you’re using file-and-folder organization. Content often needs to be ordered in non-derivable ways. I’m convinced content management systems try to sweep this fact under the rug simply because the interface issues are a pain.)
- If your system supports a content tree made up of content nodes, then you’re doing really well. However, there’s one more level of abstraction you can make if you like:
Ideally, your content tree is not made up of actual content. Instead it’s made up of “nodes” which are then linked to content objects. What’s a node? Nothing, really — they’re just things you can stack on top of each other to make a tree. Each node has a link to a content object, and one of those links is the “main” link. (Why do you need a main node? See this post.)
Why do this? Because now a content object can exist in more than one place in the tree. This is because a node is linked to a content object, and multiple nodes can link to the same object. One location is considered the “main” location, but it can appear in hundreds of places, if you like. This just means that hundreds of nodes are linked to the same content object.
This is a very powerful content modeling feature, and it lets you model content as accurately as possible.
What This Links To
What Links Here
You need to look at Sitecore: http://www.sitecore.net They do EVERYTHING in this post, it’s a killer app.
I’m impressed! :> Again you wrote about all the traps I’ve nearly fallen into :)
But I have a few questions… You wrote:
Since you can’t delete a parent without deleting all of its children, you ensure there are no orphan records floating around.
But what if the child item is also linked under other parent items? E.g. an illustration image linked under two articles. When you delete one of the articles with subitems, you’ll delete the image which is a subitem of that other article and it’s not good. How to solve that problem? Referrence counting? Or maybe there is a better way?
You need to be able to specify what type of content can go “under” what type of other content. Referring back to my magazine example, it wouldn’t do us much good to have a publication appear under an issue.
I’m thinking over the same problem now. Can you write something more about this one? [or maybe you've done it already? :D]
You need to consider the ordering of subcontent. Specifically, you need to provide arbitrary ordering.
I’ve went to the same thing and I saw that some CMSes uses “weights” for that – e.g. if you want to differ an order of appearance of some items, you have to apply more weight to the proper items to lower it down, or take off some weight to raise it upper. But the hell why they have done it so complicated? Couldn’t they use numbering from the first place?! :P It takes one integer field whatsoever, but it’s way more easier to implement and for the user! :-J It should be another “common practice” or “design pattern”.
hi, am new in content management concepts. so give me some steps to create a simple content management systems. am using only on label. so send me a code
hi, am new in content management concepts in asp.net. so give me some steps to create a simple content management systems. am using only on label. so send me a code
I’d have to agree with Rick – Sitecore’s content tree follows the inheritance and composite pattern quite well. Great article. (Reddot’s tree does as well, to a degree).