Over the past months, I've been working on a idea on how to use the modular architecture in other aspects of a Sitecore solution - more specifically the content structure. In this blog post I want to share that idea with you, along with the thoughts that goes before it.
Now before doing so, you should know that I'll not go into the bits and pieces of the modular architecture, but rather use it as a reference point for my blog post. If you want to know more about the modular architecture, I strongly encourge you to go over my colleague Anders Laub's work on the subject described in his two blog posts The groundbreaking Sitecore Habitat and The Layer concept in Modular Architecture. Assuming that you got the basics of the modular architecture under your skin, let's get started by looking at the modular architecture from the perspective of setting up a data template for a given item in Sitecore.
Getting some perspective
When using the modular architecture, a data template may be composed of other data templates, that represents a component (or modules), where each of these provide the data needed by that component.
In order to avoid getting the data template bloated with all sorts of information coming from each of the component data templates, one can instead choose to let each component be a rendering that links to a data source of its own, where the data of the component will be stored. The benefit of doing so is that it enables us to decouple the data for the component from the data for the general data template, thus allowing us to have a more thin or lightweight data template that only contains the minimum of set of data needed. In my opinion, such a setup makes sense if you are developing a platform on top of Sitecore that contains a set of components (or building blocks) that enables the content editors to orchestrate page content in a number of different ways.
But how do we maintain a structure that makes sense to the content editors?
Using renderings with isolated data sources adds a cost in complexity, since data is now no longer placed directly on the item, but into different data sources. This is where things may potentially turn into a messy situation, since data sources can be placed randomly around the content tree in Sitecore. In my experience, data sources tend to end up getting spread out into different areas of the content tree, thus making a bit of a mess of the site's overall content structure and information architecture in general. As a result, the content editors will have to be careful when determining where to place data sources.
This is where I started thinking about the modular architecture, or more specifically the Common Closure principle that is deeply rooted in the principles of the modular architecture. As my college Anders Laub explains it:
What changes together, should live together, alone.
As a continuation of this, why not apply the same set of principles of the modular architecture to the entire solution? Meaning that both the code as well as the content structure of the solution should adhere to the architecture as a whole. In practice, this means that a data source should be located in either one of two options:
- Local data source, placed in a folder relatively to their usage
- Global data source, placed in a shared folder
Local data sources are good for renderings that should display content only relevant to that specific page, like a hero image of an article. On the other hand, global (or shared) data sources are good for renderings that need to present globally defined content, like the data found within a footer.
Although this seems like a good conceptual idea, there is nothing that prevents anyone from placing data sources arbitrarily in the content structure. With that in mind, what we really want to be able to do is to remove the burden from the content editors, on how data sources should be placed in the content structure. Instead we should let it be up to the the solution to automatically handle placement of data sources for the content editors, thus ensuring a high level of coherence in the way renderings and their data sources are placed throughout the solution.
In the following we'll look into how this might be achieved using data templates, standard values and branches. I'll get into the advantages and shortcomings of each approach, as well as whether or not we can solve the problem using only standard functionality in Sitecore.
Data Templates and Standard Values
In Sitecore, data templates are used to define the structure of an item. A data template consists of one or more sections that logically and visually group and separate the fields they contain. Each field represents a value on the item, whereas the field can be a text value, a number or a any other valid field type. A data template can inherit sections and fields from other data templates, meaning that it is possible to compose a data template from other data templates. When doing so, the sections of the inherited data templates are merged into the inheriting data template.
Each data template can have standard values for one or more of its fields. This means that when an item is created based on a data template, any field that doesn't contain a value will use the standard value provided for that field. In relation to this blog post, standard values can be used to configure a set of default renderings that the template should always display.
The shortcomings of using data templates and standard values
When using data templates and standard values, one of the issues is that comes to mind is that if we use standard value to configure renderings on a template, we are only able to point renderings to global data sources - that is, data sources that must exists in the content tree. Otherwise, renderings must be able to resolve their data from the item they are used on directly. This may work in some cases, but for many other cases we want to be able to point a rendering to a data source instead, in order to avoid getting in a situation where our data templates will keep growing in size, ultimately making them beasts of endless sections and fields, which is not really what we are aiming for.
Let's look at a different strategy that might be able to help in solving the issues mentioned above, next up branches.
A branch, or branch template, is a solution Sitecore have provided in order to create items with hierarchies in one click. Branches can be used to either build item hierarchies or renderings hierarchies, located under the overall item. The branch template is always built upon a given data template, from which it inherits all its fields and layout.
In terms of placing the data sources for the different renderings used on the template, we can use branches to place the local data sources relative to where they are being used. When creating the item based on the branch template, the data sources are automatically created together with the item - which is pretty awesome.
An important note on creating items based on a branch template is that, when creating an item based on a branch template, what Sitecore does is that it makes a copy of the full hierarchy under the brach, and effectively creates a new list of items. The new items have no traces back to the branch templates from which they were created, which means that changes performed in a branch will never propagate to items created from it. This is fundamentally different from data templates, where changes would propagate to items created from it.
The shortcomings of using branches
Even though branches solves a great portion of the issues I'm trying to solve, it's not all rainbows and unicorns. As mentioned, when creating items based on a branch, everything is copied over. Future changes to the branch will manually have to be applied to existing items. Therefore, the use of branches can either be a good thing, or a bad thing, depending on the customers requirements. When considering using branches one should consider the following questions:
- How often might the template change?
- Should items created out of it show future changes applied to the branch template?
If you can say that your template might never change at all, a branch should provide you with a good starting point. However, this is rarely the case, so normally you may say that changes to the template might occur, and that those should propagate to the items created from the template.
Another detail worth mentioning is that even though we are able to create local data sources, and thereby partially solve to problem we are trying to solve, there is a slight problem in doing so. The reason for this is that the renderings that are used on the item will still refer to the branch data source. In practice, what this means is that although Sitecore automatically creates new data sources for every rendering in the new hierarchy, it does not automatically replace the links to data sources for the newly created item. This is something content editors will have to fix manually.
Solutions to the different shortcomings
When I initially saw the restrictions of both data templates and standard values versus the branch template approach upon creating the content structure described in the above, I did some research in order to see how other developers solved the shortcomings.
In terms of using data templates and standard values, one blog post suggests creating the relative data source items for preset components automatically during item creation. Where the data sources should be placed reside on the data template. Upon item creation the data source folder, along with the data source items, would be created and the renderings on the item should be updated to point to the correct data sources. This could either be done using a custom save event, or perhaps by the use of a command template. When using branches, I've been able to find a few solutions that solves some of the shortcomings, but not all of them - one of those solutions are described in this blog post. However, I've yet to find any solution on how to combine the best of both approaches.
In relation to all this, I've been working on an idea that follows along the lines of branches. The idea is to provide Sitecore administrators with a mechanism on the branch template, that would effectively look over the entire content tree, find items of the same data template as the branch template (remember that items created from the branch template has no traces back to the branch template, but they are both still based on the same data template), and allowing updating of those items with the latest changes applied to the branch template. The benefits of this would be that a Sitecore administrator could determine whether or not changes to the branch template should propagate out to all inheriting items. Another usage of this might be that, when only some of the created items should be updated, the Sitecore administrator would be able to update specific items individually, such that only a selection of the items would be updated with the latest changes - or even do delta updates by specifying which version to update to.
More details, coming right up!
Over the course of the upcoming blog posts, I'll be going further into details with the idea sketched out in the above.
In this process, the goal is to provide a working prototype implementation that will allow Sitecore solutions to be more effective when it comes to creating a sensible content structure that follows the set of principles defined in modular architecture. In doing so, I'll be sharing my thoughts and experiences on what works and what fails to meet the success criteria.
What's your experience when it comes to working with relative data sources, and how have you solved the different issues with such? If you got any good pointers, or feedback in general, please drop me a much appreciated note in the comment section down below.