One of the most important things when designing a Sitecore solution is how you intend to deliver aspects of the solution. In many cases this could be large scale releases of the whole implementation, but in my experience this only serves to limit cadence and increase complexity of delivery over time.
“Modularity refers to the concept of making multiple modules first and then linking and combining them to form a complete system.”
In the case of many Sitecore projects, it can be considered that Helix shows one approach for a component based software solution (strictly speaking in c# is by nature modular as a module is considered to be a an assembly).
From this wikipedia article on Modularity: “Modularity is the degree to which a system’s components may be separated and recombined.
Since Sitecore is a multi-tenant and modular system by design, I believe that modularity can and should be be considered as part of the wider solution. This is embraced in the OSGI architecture for example, with the idea of bundles. I believe the helix documentation is either very unclear or the architecture needs to be modified to better encompass these ideas, as the layer based approach it takes does not represent how each bundle may be composed in the real world, which in turn renders (for me at least) large parts of the Helix architecture as little more than a naming convention on the principles of Uncle Bob, and one of the reasons I choose not to follow it.
With this idea in mind, it is logical even at a basic level each bundle within a Sitecore implementation should be modular in nature and allow deployment independence whilst ideally having the option to share functionality. At the most basic level, this may be simply each tenant (website) within the implementation, at more advanced levels this will often be bundles of components that build up functionality. To this end, I thought I would detail some techniques that can help with your solution structure.
Almost every solution will require at some point a bunch of stuff that is common to all bundles that are to be delivered within your solution. At a basic level this will contain all the most hardcore dependencies of your application. Generally I would say this comprises of at least the following:
- The sitecore vendor files (the original sitecore website folder in essence)
- Any modules that are used
- One or more core projects controlled by the senior developers containing foundation functionality / shared assemblies such as Tweetsharp, Glass Mapper (shameless plug), Unicorn etc
Agreed platform by design should be the only part of your overall application that MANDATES a complete re-deployment and test.
Codebase independence for me is possibly the hardest thing to achieve, even at the most basic level, the decision on where you split the code can lead to anything ranging from tight coupling to repository explosion and all paths in between.
Generally, the aim should be to actually not have your bundles deploy anything that would conflict with other bundles. This means, as a team you agree on a version of Newtonsoft.Json for example – that is delivered by the platform and therefore by design, referenced without copying local and destroyed by the deployment process (just in case). There is of course odd occasions whereby you may choose to deliver something very specific – like a third party integration. By making these hard to modify (i.e. you have to ask the very nice folk in devops for a change), it forces developers to think about what they are doing and whether it is in fact a Platform dependency.
To my mind, a foundation component (to use the Helix naming convention) is almost always the concern of the platform solution. After this, there should be no further sharing of foundation components as you should be considering modules as slices of functionality in your solution and therefore not sharing across concerns. “Foundation” components for me also (by design) should also be delivered by nuget packages – ideally with appropriate noreference versions for use in bundles) and NEVER in the codebase that is actively being worked on. I think this is a massive design smell in the versions of Habitat and reference Helix implementations.
The simplest way I have found to deal with this is to utilise Subfolders within the app_config/include solution specific to ensure they are owned by a bundle. This goes so far as to ensure your deployment process actively deletes any configuration folders it does not recognise, so if a developer tries to get creative the deployment will press stamp the hell out of their creativeness and put them back in their box.
This as a simplistic example would be the likes of
/App_Config/Include/zProjectX – Project X’s configuration
/App_Config/Include/zProjectY – Project Y’s configuration
Mindfulness should always be given to the fact you are deploying to a shared platform.
Binary independence is usually again tricky to achieve, but in the main can be achieved with a mix of the following:
Naming convention (this allows the build / deployment process to clear much of the binaries related to a specific bundle)
Deployment process – it will destroy anything it doesn’t know about
One approach to allow better independence between your modules is to use a tool such as the RazorGenerator. By using this approach, you remove the need to worry about clearing down views or have them cross pollenate
Front end independence
I as a developer am all up for making something someone elses issue to solve – let those who do it best do it. In the case of front end assets, I am still the same (please read Front end independence). I believe with the prevalence of Headless CMS solutions increasing, this will increasingly be the case naturally anyway.