Helix - The Sitecore Structure

A major part of architecture and patterns are about communication. You put a label on something and hereby your fellow developers and engineers immediately get a idea of what structure you are building, (some of) your intentions, and maybe even some of the trade-offs that have been considered. Not by magic, persisted brain waves or any non-human science - but pure professionalism and craftsmanship.

In context of Sitecore development it is evident for developers to know Helix. Sitecore has put up a nice Helix documentation site1 with lots of details. It is basically a layered component architecture (but read the actual documentation), what I find real important is that we have some common definitions/names that are shared across the Sitecore community so you can expect this when taking over a solution form another vendor and during a Sitecore Review it will be mentioned of this architecture is not used.

Here I will discuss Helix in general for pure Sitecore implementations. There are more considerations in more specific scenarios, such as for a ASP.NET MVC site implementation, a NextJS site implementation, when using SXA, etc.

The basics

There are three layers, dependencies should only go “downwards”.

Diagram of three layers: Project, Feature, and Foundation. An arrow pointing downwards from Project to Feature and Foundation to indicate dependencies Layers in Sitecore Helix (source: Sitecore Helix site)

Why this is great and important

A major struggle in Software Engineering (especially as an agency, but also for in-house development) is the need for multiple developers working on a solution. It is a given, a condition, people switch jobs or positions, will be involved with new exciting stuff they want to focus on, or are just overwhelmed with work due to the constant demand for software engineers.

Hereby it is very important to communicate between developers where to find a certain functionality, it should be easy too understand that functionality as a whole, and there should be as few other worries as possible.

  • By ensuring you have everything related in a feature module, you make it easy to understand for the next developer, that is the high coherence.

  • By ensuring that you don’t have to worry about the other feature modules, you reduce the mental load to get into the project and work on a feature, that is the low coupling.

  • By ensuring that your modules don’t affect other modules you reduce the risk of introducing bugs in other parts when making changes in a module. Of course there are no guarantees, but we help ourself by making the modules independent.

It is not that important for me that a certain feature potentially could be used in another solution, but the mental exercise is valuable when evaluating those architectural goals.

Is this really specific for Sitecore

Well, the layer names with foundation, project are inventions within the Sitecore community. However, making smaller isolated meaningful groups are definitely not just Sitecore specific - and luckily I am not the only one with this opinion.

Here about Vertical Slice Architecture2

Vertical Slice Architecture diagram

How do you make this in reality

I want to be very strict on there should not be any dependencies between feature modules. We should aim for making as much functionality as possible in feature modules.

In other words, don’t group your source code by types (controllers, views, repositories). Group by logical groups (“feature modules”) so a developer can find the expected functionality and file by going through the folder structure in the solution. When working on a functionality, there should be as little friction as possible, so you should not be required to go back and forth in the folder structure.

Whenever we put functionality in the Foundation layer, we also say that every future developer that are going to work on a feature will also need to understand this - it is the foundation, right. It always have a lower cost to add something in the Feature layer instead of the Foundation layer, because we don’t increase the burden for every future developer.

Still, we should not give a worse experience for the editors due to the underlying architecture, we must as always ensure an easy to understand and smooth editor experience. Hereby is also, that it is ok to have dependencies between feature modules if it is purely references in Sitecore.

Ok, so we have some functionality, maybe a component, that we have need to develop. That functionality consists of potentially:

  • Some data fields - on a template item
  • A model implementation reflecting those fields
  • A rendering definition item
  • A rendering implementation (backend, frontend)
  • Styling

Create all of those with exactly what is needed for this functionality: One specific template with just the fields used by this rendering. Create the rendering implementation so the context data source is used.

The functionality can now be used as an individual component that you insert in a placeholder on a page and the template is the data source.

In the project layer you can now choose what is the best way to use the functionality. It might be that there are certain type of pages on the website that are similar so to make the best editor experience you create a template for this Page Type. This Page Type Template will be built upon functionality from the various feature modules. The Page Type template use the multiple inheritance functionality in Sitecore and create a “composition” by inheriting those data sources templates. In the standard values for the Page Type template, insert the corresponding renderings for functionality

Everyone is doing this, right?

It is my understanding that for several years Sitecore have, during reviews, commented if a solution was not using Helix principles. I want that implementations should be easy to find (I have also seen Helix solutions where we could find nothing, so there are no guarantees).

image of functionality grouped by intent with several different types related to the same feature grouped in folders, eg. article

Way too often I see projects grouped by type. I say, you should really group by intent - that is what your fellow developer will be looking for. It might be meaningful to subdivide by type for a bigger feature module (if you can still keep high cohesion).

image of functionality grouped by type with the same type of implementation and not related to the same feature grouped in folders, eg. controllers, handlers, attributes

Well not really, I think the problem is that often you have “starter kit” or initial setup with a very limited number of items - and of course there should only be few items for an example or starter kit - but you need to consider how to scale. Eg. ASP.Net MVC website initializes with Controller, Models, and Views folders. Perfectly fine when you only have a very limited number of concepts - and fine within a feature module. There is the concept of Areas within a single ASP.NET MVC project to solve this, which is very similar.

What is the right size of a feature (module)

Well of course it depends…

We want a high coherence so if there are parts that are unrelated to each other, have different dependencies etc. it is an indication that it should probably be different features.

On the other hand, you should not just have a single component in a feature and there should not be hundreds of different features, that is an indication that you should group the functionality in fewer and larger groups.

Considerations to keep in mind

Keep focus that it should be easy for the following developer to get into the project, find a specific functionality, and change it without (too many) unexpected surprises

Hereby it also follow that we should be really careful about adding implementation to the Foundation layer. Whenever we add something here, any future developer will need to know and understand it to be able to safely add new features.

Consider if your foundation layer can just be general abstractions with a specific implementation in a feature module. Hereby it should be possible to add new features by just understanding the abstraction and not necessarily the actual implementation - and you can still provide functionality that can be used across the application.

The grumpy man’s thoughts

Ok so I have hopefully explained that I see and love the good intentions in Helix. I have to admit that I have been very slow to adopt this. I think this was mostly due to the implementations I saw.

A crucial point for me in any architecture is that it should be easy and effective in use. If that is not the case, then we are failing as architects.

Helix describes properly that you can even create group(s) of similar features. The separation between feature modules can as well be handled with namespaces, it doesn’t have to be individual assemblies.

I think the summary of this is just that you should always consider your architectural goals and not just blindly copy something from the internet…