Sitecore Development in the real world - Organizational Strategies
There is a bit of a delta between understanding Sitecore development after taking training and understanding Sitecore development after delivering a project. Training doesn't discuss design best practices and tradeoffs. Training doesn't cover the use of source control in managing Sitecore artifacts, nor how to best package and deploy them between environments. Training doesn't explain the use of tools like Team Development for Sitecore (TDS) or ORM's like Glass Mapper.
Having spent close to the last year figuring it all out while developing solutions with Sitecore and seeing other developers go through the same process I did to get to the point when things "really clicked," I thought to capture some of my thoughts and lessons learned.
Your Sitecore Instance isn't part of your Project
In some training courses, you actually will put a visual studio project in the same place where your Sitecore instance is installed. This leads to a fundamental misunderstanding about what Sitecore is and its relationship to the code you write. Sitecore is a platform, and you need to think of it as such. If you think about it like it's only purpose is to house your specific solution, you are going to make design decisions that will make sure that's all that will be possible.
Instead, think that every Sitecore artifact you create and every piece of code that you write will have to be deployed to an environment you may not entirely control. An environment where other code, other sites created by other developers, may run at the same time. This will impact the way you develop with Sitecore from the way you structure your Visual Studio solution to the way you organize Sitecore items in the content tree and more.
Flexibility and Isolation in VS Solution Configuration
From a visual studio perspective, this means that you need to think about your web projects being deployed to a Sitecore instance via xcopy. This means all existing files in the target Sitecore instance will be over written every time you deploy and more to the point, other projects may overwrite your files every time they deploy. This kind of thinking is both limiting and freeing at the same time.
Don’t use "Sitecore" in your project namespaces. This will just cause collisions when you need to use Sitecore's API's. Instead make your namespaces relevant to your domain. If it is Sitecore specific, use SC instead. Libraries like Glass do this.
It feels limiting in the defensive measures you will need to take to fend off such issues. Making extensive use of custom Sitecore configuration files and avoiding making changes to the web.config ensure your configuration doesn't get lost and even helps avoid issues when you have to upgrade or patch your Sitecore instance. Putting your layouts, sublayouts, renderings, scripts and css files in subfolders named with your project will ensure their paths are unique and avoids overwriting collisions when multiple solutions have common file names like "header.ascx."
You have a few options to facilitate builds to your local Sitecore Instance. If you're using Team Development for Sitecore (TDS), it makes it extremely easy as it will automatically deploy your web project to your Sitecore instance root on build. If you don't have TDS, you'll need to configure web deploy and a post build step to automate deployment. With either approach, I also recommend "AttachTo," a visual studio extension that will allow you to debug your local IIS instance in one click.
It feels freeing, because by keeping all the pertinent code changes isolated from each other, you can actually break your Sitecore solution into many smaller projects, which can be deployed together or separately, giving you a level of code reuse you wouldn't have otherwise. If you have a feature, a pipeline component or even just a set of templates that have high reuse potential, you can segment each into their own set of projects and package them together (code and artifacts).
Avoiding Sitecore Item Collisions
Lucky for us it is pretty straight forward to avoid other projects overwriting your custom Sitecore items. Simply create subfolders with your project's name before adding any custom items. You need to do this everywhere you create Sitecore items.
In the Layout folders: Layouts, Sublayouts, Renderings, Placeholder Settings etc, you should first create a subfolder to contain your layout items. In the media library you should not only create a subfolder for you project, but ensure every Image field in related data templates use that folder's path in that field's data source. In the dictionary, you should not only create a subfolder for your project, but use a consistent prefix in all your dictionary keys to avoid collisions. Workflows and Validation Rules should also employ the same project folder tactic. This ensures that other projects or packages will not overwrite your Sitecore items unless they are explicitly trying to do so.
Organize your Content Tree
Content organization matters a lot in Sitecore development, and though it's straightforward to move things around after the fact, it is a pain if you have live content that has been indexed, and it's not worth the hassle of dealing with redirect rules if instead you just put the effort to get it right the first time.
By default when you install Sitecore, you simple see a home item under the Content node. I generally recommend deleting that node and creating a structure that makes sense and can scale easily to meet you requirements now and in the future. Sure, you'll need to adjust the Sites configuration ( use a custom include config file ), but it will be more convenient in the long run to manage.
I'll tend to create at least 3 folders for every site hosted in Sitecore I create as well as a Global folder to store content and configuration that impacts multiple sites.
The Home folder is what will be mapped in the sites configuration for the url binding used for the site. In general the nodes under this will have configured presentation details and accessible via url.
The Data folder is basically the root of the "content library" specific to that site. Every type of content you need selectable in your page templates should be organized into subfolders to make it easy to find and select content that is referenced by multiple pages. Your droplink, multilist and treelist fields should reference to paths here to make reusable content selectable. The data folder under global should similarly be used, but for content that can be selected and reused across sites.
There is a tradeoff when you put content in the data folder. It makes it a little more difficult to see the relationship between your page instances and the data it references. An alternative would be to make the data template instances children of the page instance itself, and this is a viable approach if and only if the content wont and never will be used by any other pages. Any benefit of association to the page template would immediately be lost if you needed to duplicate content or try to connect content under one page with another.
The configuration folder should hold Sitecore Items that control how the sites behave. In general, these are global static items that help configure things like layout and impact everything on the site. I'll often create a navigation subfolder here to help organize menu items for global navigation. The configuration folder under global should similarly be used but for configuration items that impact multiple sites.
Data Template Organizational Strategy
Besides creating a root folder for your custom data templates, you should give some thought to how to best organize your custom data templates. Every solution will have its own nuances, but I generally recommend a minimum of 4 key folders to give a logic separation to all the templates you will create:
- Base Templates - here is where I put templates that are meant to be inherited. This includes not only base page templates, but templates that group common fields together for reuse. If you have more than a few base types, consider creating subfolders to make it easier to understand the organization.
- Page Templates - here is where I define the templates that will be populated in the content tree and available as insert options.
- Component Templates - here is where I define templates that drive data that is selectable by page templates. Instances of these templates will either be stored in a subfolder of the "data" folder or as a direct descendant of a page template.
- Configuration Templates - here is where I define templates that control global site behavior. Avoid creating monolithic templates that encompass all possible settings. Instead try to group the configuration settings to logical groups and create instances of them in either the sites or global configuration folders.
You should also carefully consider how you name each template you create and the fields within them. If you are using an ORM like glass and using code generation to create classes, the names of your templates will become the names of your classes and the names of your fields will become the names of that classes members. Remember that at least with fields, you can give a developer friendly name to the field and a content author friendly name by leveraging the fields "title" property (you'll need to click on the field in the content tree instead of the builder tab of the template).
A lot of what I discussed in this post relates to just thinking through your solution and understanding the impacts of the decisions you make on the maintainability of your Sitecore project. In the end, understanding what you are trying to accomplish and how will it be executed before beginning to make design decisions will save time spent on rework.
What do you think? Share your tips for organizing Sitecore items in the comments.