Best Practice


Last week someone asked me to email them a list of tips for improving code quality and I thought it would make a nice blog post; I picked just three areas and only made a few bullet points for each one:

Automated code quality

  • Resharper + StyleCop Plugin – This is a fantastic product that will both spot common programming mistakes and suggest improvements. With the stylecop plugin it will enforce the Microsoft formatting standard ensuring code consistency and readability.
  • FxCop – Scans your compiled dlls for known issues recorded by Microsoft, it’s a bit noisy but some of the potential problems it spots can be incredibly useful.
  • GhostDoc –Auto-generates and scaffolds out your comments based on the code naming, so a method called GetCustomerRecords will create a comment that simply says “Gets the customer records”. Still requires you to fill in the comments but does the initial legwork.

Training

  • MCPD training – Sadly rife with cheating due to the answers been freely available online the MCPD certification are still a really fantastic certification, not so much for the depth of information but rather the breadth.
  • Transcender – The intention of Transcender is to help people prepare for exams but I would recommend using it for people who have already passed. It will often show up gaps in their training and areas they need to work on.
  • Blogs – I would recommend that every developer has a rss reader which they check every morning, my personal favourite is google reader. Below are some of the blogs I’d recommend:
  • Books – A great idea is to setup a company library and regularly stock it with new books on topics like Linq, MVC and C#/SQL/HTML reference material etc. The one book I would recommend as a “must buy” is Code Complete (2nd edition) by Steve McConnell, I couldn’t recommend it enough.
  • Knowledge sharing – Naturally over time developers tend to become the expert, or go-to person for a particular topic, MVC, SQL or maybe an internal system. It’s great to have someone with a deep understanding of a topic but all too often this results in everyone else having zero understanding of it. Regular knowledge sharing sessions where that expert gives a 15 minute presentation on the topic helps everyone fill in the gaps and prevents disaster occurring if that expert leaves or is unavailable.
  • Code review – Formal code reviews can be quite time consuming and by extension expensive, in situations where this isn’t possible you can still encourage quick peer review of code. Before checking in the final version of their code each developer should ask a co-worker to look over their work and see if they can spot any areas for improvement. Quite often glaring mistakes can be spotted that are otherwise invisible to the person who wrote them.

Testing

  • JMeter – Stress testing during development is a must to ensure that performance issues don’t creep into a project only to be found after launch. It will also help you estimate infrastructure requirements and meet any agreed upon response times.
  • Continuous Integration – CI is a broad topic but I’ll steal the definition from Wikipedia: “CI implements continuous processes of applying quality control – small pieces of effort, applied frequently. Continuous integration aims to improve the quality of software, and to reduce the time taken to deliver it, by replacing the traditional practice of applying quality control after completing all development.”
  • Watin – Automated testing is typically restricted to just integration or unit testing of code. Watin allows you to write tests in C# that check the webpage itself, at the minimum I would recommend a recursive Watin test that checks the entire site for 500 errors and XSLT rendering warnings.
  • Nunit – Since Sitecore is so tightly coupled to the HTTP context it’s difficult to write true unit tests but integration tests can be just as useful. Coupled with Watin running on a dedicated build server you can see real leaps in code quality and a massive reduction in unseen problems been deployed to production servers.

The topic itself is massive and many books have been written on it (as I mentioned my favorite been Code Complete by Steve McConnell), make sure you post your favorites that I missed in the comments ;)

Workmate of mine Adam Rambridge sent around an excellent survey on monday asking what best practices we recommend for sitecore projects. Instead of writing up a blog post this week I’ve taken the easy route and just copy/pasted the results ;)

Question Answer
Your name Steve Green

Information architecture

How best to structure templates? Typically I would break the templates down into 3 folders, field sections, page types and meta data.Field sections are reusable collections of fields such as title/text, meta tags, navigation that are inherited by page types.Page type templates are for items that are under the home node, ideally they are the only templates to have presentation values.Meta data templates are for items outside the web context which are typically stored in the global folder. These cover things such as reusable rich text blocks, control labels and configuration, dropdown menu sources and other content that doesn’t ‘belong’ to the content items.
How should the content structure be organised? I’d recommend prefacing your template names with a short signifier, so ABC_ or Comp_, this is so the client can later develop other websites and easily distinguish between the templates meant for one over the other.All content under the home item should represent a page and have valid presentation. All other content should be stored within the global folder which is a sibling item to the root home node.
Is this good practice that we should use on all projects? 90% of the best practices we typically use can be applied as-is without modification. I would prefer to see at least some attempt made to consistency.
Are there disadvantages to this scheme? None, you should only be doing it if it makes sense, if it doesn’t then you’re not doing anyone any favours.
Are there better ways? Indubitably, I hope to find them out ;)
How should you decide when to store items in a global folder rather than under the home node? Only content that “belongs” to the item should be present. The approach to organising sitecore content should be functionally similar to database normalization. It should be in global folders if the content in question isn’t “owned” by the context item, this covers both things like sidemenu RTE blocks, control labels or if there is a many-to-one relationship of some sort.
Text that goes with a control or sublayout We did try name/value pairs for a while but frankly these suck. I’ve now switched to a set of custom configuration templates, one per rendering or sublayout. They have 2 sections, one for labels and one for configuration. The configuration node is set at the top of the renderings as a variable and as a private property on the sublayouts. I’ve been planning on automating this at some point however.Something which I don’t do but it worth considering is using the parameters templates which were introduced in 6.1. I’m not sure how usable this is for the content editors however, letting them go into the presentation interface is dangerous at the best of times.

Naming

Naming fields and field sections Field names should be programmatically sound with friendly names added later.
Naming templates, layouts, renderings etc. ProjectAcronym_TemplateName typically. Folders used as much as possible (note, not supported in workflows).
Name prefixes See above.
What other advice would you give on naming items? Clear, concise and SEO friendly. In the case of sublayouts and renderings make sure the item name matches the file name.

Project structure

What is the ideal structure for a Sitecore project? Start with the standard 4, Website, Business, Data and Tests. You’ll almost always end up creating them so why not do it from the start. Otherwise you tend to bloat up the website project with helper classes only to have to refactor later.
What are the worst mistakes that should be avoided? Omnidirectional project references, untilize dependency injection where possible.

Sitecore ORMs

What do you think about Sitecore ORMs? Tears, wailing, gnashing of teeth. Contentious issue but personally I think the issues it’s trying to solve are not as big as the problems it causes.
What problems does it solve? Very very good question. It’s can be cool that’s for sure. Templates as object, intelisense on your fields, that’s lovely. Then you run into the hell of lazy loading, caching and often a gradual and inexplicable delta between the database and the in memory objects.
Does it cause any problems of its own? See above.
Would you use shared source Domain Objects instead? Why? Never tried it to be honest.

Sublayouts and renderings

How do you decide whether to use one over the other? It’s not very scientific but I use the rule of thumb that if it’s not easy it’s time to switch to a sublayout. XSLT should make your life easier, not harder.
Are there dangers of too much reliance on XSLT? There can be issues with refactoring, due to its reliance on referencing items by paths and fields by names. I’ve got some grand ideas to help resolve that however via xslt helpers.
Are there dangers of too much reliance on sublayouts? Sitecore is designed with xslt in mind, if you use sublayouts where a simple xslt rendering could have done you’ve missed a trick.
Is one easier to maintain that the other? Loaded question. Ask someone who needs to rename every reference to an item by path and you’ll get one answer. Ask somone who needs to pull out a faulty ORM and you’ll get another. I think like most things you need a healthy balance really.

Testing

Can Sitecore projects benefit from unit testing? Strictly speaking no, Sitecore itself is impossible to properly unit test. Integration and stress testing however is vital.
WatiN? A recursive Watin test for the whole site to check for standard errors (missing presentation, failed xslt etc) should be standard on all sitecore sites.
What holds us back from doing more testing? Time, and occasional false perception of there not been enough time.

What else?

What factors cause sitecore projects to go well? When the site is been developed as a sitecore site, see next question for more.
What factors cause sitecore projects to go badly? When a site is been developed as something else. Sitecore projects typically fail when someone is trying to code something else into the system. Sitecore can be an application framework, but you’d be better off with MVC. Sitecore can be made to act like any other CMS or legacy system, but you’d be better off not doing it that way. Sitecore always *CAN*, but you probably shouldn’t.
What other questions should this survey have asked? I’m sure we can think up enough for a sequal at some point. This survey though was exhaustive and excellent, cheers ;)

 

 

Love to see what other peoples answers would be, if you do end up posting your answers online make sure you post a link to in the comments :)

layoutnotfound

Layout not found, never a good look. Despite all efforts to not link to items lacking presentation the only sure-fire way to prevent this is to simply not have any; everything under the home node should have *some* kind of presentation applied. In every case where someone has said “don’t worry, there is no way they could reach that item” they always have linked to it or found that users actively change the urls to it (happens more than you’d expect).

The biggest offender for zero presentation is the common garden variety /sitecore/templates/Common/Folder. It’s not uncommon to see deeply nested sets of folders in order to create more content rich urls, it is after all part of the SEO holy trinity of url, title and header. My replacement for this is what I call the bump folder, not the best of names but it has stuck. It’s straightforward to implement and dead easy for content editors to use, the bump folder simply 301 redirects the user to either the parent item or the item selected in a droplink.

First step is to create a new template in your solution and add the following field:

bumpfoldertemplate

This is a single droplink field called Target and I’ve ticked shared as it’s language invariant (or at least likely to be, just untick if it’s going to change based on language). The interesting bit to note here is the source, you can not only supply paths but also sitecore queries. In this case the query used is “query:./*[@@tid!=../@@tid]” which means “Select all child items which are not bump folders”. The reason I avoid linking up to bump folders is to avoid 301 daisy chaining or even worse 301 loops (where the folder linked to has no target set and 301 redirects to the parent item). I’m also using a drop list instead of a general link so as to avoid the folders turning into aliases and creating the website equivalent of spaghetti code.

The only thing to add now is a layout item (and aspx file) and assign it to the presentation for the bump folder. In the codebehind for the layout add the following:


protected void Page_PreInit(object sender, EventArgs e) { 
  LookupField target = Sitecore.Context.Item.Fields["target"]; 
  if(target.TargetItem != null
    Response.Redirect(target.TargetItem.GetFriendlyUrl()); 
  Response.Redirect(Sitecore.Context.Item.Parent.GetFriendlyUrl());
}

Done, I know it’s not exactly ground breaking stuff but it’s little things like this that can really make a big difference to a Sitecore project.

Update: 27th September 2009

Doh, forgot to add that I’m using a set of extension methods alongside my solution, GetFriendlyUrl() in this case is actually an extension method.

public static string GetFriendlyUrl(this Item item)
{
    return LinkManager.GetItemUrl(item);
}

Also as pointed out by Thomas Eldblom these bump folders shouldn’t preclude the development of “fit for purpose” container items. They’re simply for content editors to organise their content into more useful hierarchies. Thomas also has some good pointers on how to manage your errors in general, see the comments for more details.

Adding little “traffic light” labels to the top of your renderings and sub-layouts can really help both the customer and other developers see how the site is progressing. Just a small span at the top of the file containing its name and a css class for its status will do the trick:

<span class="devlabel red">homepage_flashbanner.ascx</span>

The problem you run into is that the style tags often interfere with the layout of the page or just don’t show up correctly at all:

before

It can be worse than this, often you’ll find that simply adding these spans will throw the whole page into a shambles.

The solution is to turn to the as always awesome jQuery. Start by adding the following script to the bottom of your main layout file:

<script type="text/javascript">
jQuery(document).ready(function() {
   jQuery(".devlabel").each(function(n) {
      var label = jQuery(this);
      var target = label.next();
      var pos = target.offset();
      var left = pos.left + "px";
      var top = -12 + pos.top + "px";
      label.css({
         zIndex: 5000,
         left: left,
         top: top
      });
   });
 });
</script>

Make sure the CSS class for the label is set to absolute positioning as so:

.devlabel
{
	font-size:8px;
	position:absolute;
}
.red
{
	color:red;
}
.orange
{
	color:orange;
}
.green
{
	color:green;
}

What that jQuery will do is search for any labels with the ‘devlabel’ class and position them directly above the very next element. It should end up looking more like this:

after

Then of course as your project progresses you can change the color of the traffic lights, red for not started, orange for in progress and green for finished (and tested!). Quite satisfying to watch them slowly turn green one by one :)

progress

I’ve been adding these ‘traffic lights’ to my projects for quite a while now, the only issue really is having to remove them at the end of the project (for SEO purposes they’re a big no no). This has given me inspiration for possibly writing a pipeline handler to automate the process, instead of using the traffic light colors it could instead output the name and Sitecore UI icons of the various renderings and sub-layouts. Once I have the details sorted I’ll be sure to post an update.

This is something I see come up a lot when developing Sitecore websites, how best to reference your items, by path or by guid. Almost every method in the Sitecore API will accept both path and guid as will xslt (paths often been XPATH statements in that case). Both have their pros and cons and both are more suited for particular situations that the other.

The biggest benefit of paths is their human readability, even a non-technical person can find an item based on its path. If however you’ve spent a whole project referencing items by path and you need to change the site item hierarchy you’ll run afoul of a potential refactoring nightmare, doubly so if those paths are created dynamically. Guids on the other hand are the exact opposite, they’re essentially immune to 90% of those refactoring issues but they’re otherwise uttering incomprehensible (i.e. 5EBC6046-5012-4C78-BAC9-5852A8E26918)

So the long and short of it is that it would be nice to use guids everywhere for more robust code but you’ll need to hope everyone remembers to put a friendly comment in explaining what the guid is for. The middle ground solution I’ve found which really nails the issue for everything but xslt (more on that later) is a static settings class like below:

using Sitecore.Data;
namespace Example.Business
{
    public static class SiteSettings
    {
        public static class TemplateIds
        {
            public static TemplateID Client { get { return new TemplateID( new ID("5EBC6046-5012-4C78-BAC9-5852A8E26918"));} }
            public static TemplateID Branch { get { return new TemplateID( new ID("{35E75C72-4985-4E09-88C3-0EAC6CD1E64F}"));} }
            public static TemplateID Fees { get { return new TemplateID(new ID("{334CA6C3-B6CB-4A86-80C4-1BD1892408BB}")); } }
            public static TemplateID Service { get { return new TemplateID(new ID("{2FB9F53A-CCE2-4873-A376-BE1984FE0DDB}"));} }
            public static TemplateID Section { get { return new TemplateID(new ID("9F9AE8B7-159D-468E-9732-68BB7E9D53A4")); } }
            public static TemplateID Article { get { return new TemplateID(new ID("CCDAE7B5-656C-4E64-90D1-7A6BDC66C697")); } }
            public static TemplateID Author { get { return new TemplateID(new ID("D3B7113E-639E-494C-8F4D-65A4CADCE11A")); } }
        }
        public static class ItemIds
        {
            public static ID ArticleRoot{ get { return new ID("7438EA73-B93A-476E-B6A0-9FE4C382AE66"); } }
            public static ID Branches { get { return new ID("BAD98E0E-C1B5-4598-AC13-21B06218B30C"); } }
            public static ID SiteRoot { get { return new ID("D3978CE5-BBC7-4201-9D53-46B53E039365"); } }
        }
        public static class WorkflowIds
        {
            public static ID NewSection { get { return new ID("1FE1D278-6463-47AD-9813-E82C82F87753"); } }
            public static ID NewComponent { get { return new ID("777348EE-A748-47EC-B771-9BC0F5A0C636"); } }
        }
        public static class WorkflowStateIds
        {
            public static ID LoginDetailsSent { get { return new ID("DE94B240-198D-40BE-8621-236EF74DB395"); } }
            public static ID Approved { get { return new ID("3521F34D-F15D-404D-9EAB-DF124F89EE56"); } }
        }
    }
}

Straight forward and simple, the only downside is that it cant be used for your xslt renderings but more on that later…

Follow

Get every new post delivered to your Inbox.