Some thoughts about Helix and Habitat
Following my previous article which introduced Helix and Habitat - which was a (hopefully) fairly factual account of what Sitecore have put out there - I thought I’d add some thoughts, opinions and questions. I'll focus on:
- Overall impressions of Helix and Habitat
- Some of my general concerns
- Some thoughts on starting to use Helix principles
I think it's great that Sitecore have produced Helix and Habitat, if for no other reason than encouraging debate and discussion around Sitecore architecture and standards generally. Whilst it's easy to find endless books and articles describing modern software principles and practices in an abstract sense, it's less often that concrete examples are provided in a target technology set (for instance, .NET and Sitecore!)
Some things I like about Helix/Habitat:
- Helix has a very “anti-coupling/high-cohesion” attitude (even if this approach may allow some duplication) - from experience I've seen far worse things coded in the name of “removing duplication” than I've seen done to limit coupling
- The attempt to focus the minds of developers more on the business value of features (rather than a developer-centric attitude to implementation) is something I think will produce better modularisation and hopefully more relevant code-level testing
- The DevOps focus is welcome
- The Helix documentation is really good - http://helix.sitecore.net
- There's some useful bits of reusable implementation included with the Habitat solution
I'm a little uncertain about the layer boundaries - the Helix documentation implies that the Feature layer is an equivalent of the Domain layer in DDD - but to me this doesn't seem quite right:
- The Domain layer typically has no knowledge of how the Domain model is used to create useful features for users - the Domain layer is there only to capture core business rules
- A DDD approach typically defines an Application layer in which application logic resides - usually this will need to call into the Domain layer
As prescribed, the Helix Feature layer looks more to me like an Application than Domain layer - the Feature modules are entirely geared towards a business-specific function of the application.
So if you still wanted to use a DDD approach, would your Domain code sit perhaps in the Foundation layer instead? Actually, Helix also allows Feature level code to live in a Foundation module, if it is shared between more than one feature - so from a DDD perspective, Application modules live in both the Feature and Foundation Helix layers.
However, Foundation layer modules are allowed to depend on other Foundation layer modules. So you could create Domain layer Foundation modules, which are used by other Foundation modules and Feature modules! In reality your Foundation layer would probably have a semantic split between Application, Domain and Infrastructure modules - suddenly the Helix 3-layer hierarchy is not so simple anymore!
Obviously if you eschew the DDD approach and store your domain logic feature-by-feature, these concerns go away - and for many brochureware-heavy Sitecore applications without too much of Domain Model, this might be your best bet.
Aside from the these thoughts about layering, a few other concerns are:
- Helix promotes dynamic binding of page components wherever possible - but unless your CSS creators have been very diligent with their work, it's worth being aware of the risks of content editors having a large amount of flexibility with rearranging page components - it may not look great if it's not been designed to work that way! The upside is that it's easy to revert presentation changes which don't look right
- If you went down the Habitat route of one Visual Studio project per Helix module, I can see there being quite a bit of setup overhead, although there are ways to automate a lot of the repetitive setup. It remains to be seen how much of this overhead is paid back through increased maintainability!
- Following on from some of my thoughts about Helix layers, and ignoring DDD for a second, it seems like the Helix Foundation layer is a little vague, as it can contain a multitude of different module types - so it could be hard to decide what goes in Feature and what goes in Foundation for certain cases. Although a DDD layering system is more complex, with more layers, the rules for each layer are more clear!
- I'm a big fan of unit tests which cover as many layers of the application as possible (as opposed to routinely testing individual classes, or only a system of classes in one logical layer at a time) - primarily because this enables you to aggressively refactor (i.e. create and destroy classes and internal interfaces). The tests will enable you to make such refactorings with confidence. However, with Helix you might be convinced to temper this approach to restrict your tests to one module at a time. While this is great for reusability of modules (no need to retest the module if it's reused in a different application) beware of what happens when code gets moved between layer boundaries due to refactoring. Your tests may well no longer be valid...
- Identifying correct module boundaries seems to be the key developer skill in applying Helix principles - beware that if this isn't done well, most of the benefits of Helix are unlikely to materialise!
Starting to use Helix principles
As with any new way of working with a software project, the easiest time at which to start using the new principles is with a new build. This is especially true with Helix, as you have the Habitat application as a starting point.
As always with software, an incremental approach might be best - that way you can always back out if you change your mind! What methods might you use to incrementally introduce some Helix to your solution?
- You may well need to start with looking at the Habitat local build setup, and switch to developing outside the web root - add some build scripts to push assemblies, config, files etc to the correct destination folder. This could also be a good time to optimise your DevOps process across all environments
- Perhaps implement the next new business feature as a Helix “Feature”, making it as self-contained as possible. The danger here is that the mix of implementation styles across the application could cause confusion!
- Or you could start a more gradual process from a higher level - for instance, by defining a strict naming convention for each existing feature, then continuously refactoring existing code and data to be contained in similarly named namespaces/folders. Although you are unlikely to achieve anything that looks like the Habitat setup, you will at least have a more feature-driven mentality in your code
- Or you may look to introduce more isolated aspects of Helix individually, such as customised code to enable decoupling between sites and features (especially relevant if your application contains many sites) - such as the Habitat code to vary rendering datasource template/location per site
- Also, there's probably nothing stopping you from starting to use Helix terminology, even if it's just in informal discussions and not in code
Basically, you're not going to be able to adopt Helix overnight! But it's worth considering which aspects of Helix you could adopt incrementally and in isolation.