Sitecore Continuous Deployment: Conditional sublayout logic
In a previous post, I discussed handling the continuous deployment of templates and layouts, but mentioned that you also need to worry about conditional business logic in your sublayouts. The primary issue is this: if the data model is constantly in flux and the system is in a state of needing to maintain current functionality while also supporting testing of new functionality, how do we avoid sublayouts blowing up when they render to the user?
Backwards compatibility
Anybody who has ever tried to write a system that always works for any version of a database schema knows that you will lose your mind trying to build up a data layer that safely handles all of the possible scenarios, never mind trying to maintain that beast over time. Still, with a continuous deployment model, your code that is being deployed needs to work if new features, templates, or fields are not yet enabled for public consumption. At any given point in time, you essentially have two modes:
- Stuff that we know works, and
- Stuff that we know is being tested.
If you want to get really complicated, you might even start tiering your acceptance of features so that some features are in ‘alpha’ versus ‘beta’ versus ‘delta pi omega force’. I don’t advise that :).
This means that sublayouts need to be written to handle both scenarios. It needs to handle the new state of things that we hope will work, but also be backwards compatible to present the stable state to users who are not in the test group.
A new field, as an example.
Imagine a developer has just introduced a new field to a page component template. This field is intended to allow the author to provide a teaser below a linked title in a small component on the page. Following some of the recommendations given before, the developer has secured this field to the test group so that only those testing the new field will see it. The markup has been added to the component sublayout to display the teaser in the appropriate position, with the proper styling and positioning.
At this point, however, there is a scenario where users who are not in the test group will visit a page with this sublayout on it and not have access to the field. Without any additional code, the browser receives an extra set of markup without the data from the field in the teaser area.
<a href="#" class="list-group-item">
<h4 class="list-group-item-heading">List group item heading</h4>
<p class="list-group-item-text"></p>
</a>
This can be particularly a problem with headers and other types of tags when supporting accessibility. Instead, the sublayout code needs to make this markup conditional. If the field is available, then the teaser information is displayed. If not, no markup is displayed and the interface appears as it did before the developer introduced the new field.
This approach can be applied to generally any section of your presentation where you need to present two views. Things start to get more complicated as you go beyond simple ‘yes/no’ presentation decisions.
Conditional Behaviour
With Sitecore implementations, it is rarely only the data model that is in flux. In addition, new business logic or integrations are often being introduced to enhance the website functionality. In these cases, simply testing for the availability of a field for the user is not enough.
Let us take as an example a simple listing sublayout that uses a repeater on a set of data. Regardless of the set of data, the output to the user is always the same format. However, new business logic has been introduced to optimize the retrieval of the data using a caching layer. The development team wants to test this caching layer out and ensure all use cases are covered before switching over to it. The unit tests seem to pass, but the final manual scenario testing needs to occur.
In this case, the sublayout cannot test using Sitecore security on an item. Instead, there has to be some sort of boolean indication that will inform the sublayout logic whether it should retrieve the data using the caching manager, or using the previous data access layer.
The easiest way to do this is to base it on the Sitecore.Context.User properties. By using the current visitor’s group membership, IP address, usernames, etc. you can build a utility to inform sublayouts of the level of access the user has. This could be as simple as testing if the user is in the Tester role.
if(Sitecore.Context.User.IsInRole("sitecore\Tester")){
return CacheManager.GetData();
}
else{
return EntityManager.GetData()
}
Going forward
There are a lot of scenarios to be covered, but the general approach that will be needed is to build a utility for your application that will be able to test if the current user should access test content/functionality or not. From there, code is built to flow through one path or another.
This will become incredibly complex to manage if you are not abstracting away the important business logic into layers so that you can provide different access points to the same data. Avoid embedding all your logic into your sublayouts, and it will be easier to choose one path over another.
Just remember to clean up the old code once things pass testing!
1 Comment