Monday, June 18, 2012

The Mikkelsen Component Model

I recently worked through Jens Mikkelsen's excellent series on building a Sitecore site.  In his article on architecture, he makes an argument that the classic N-Tier approach of separate presentation, business, and data layers is not well suited to Sitecore development:

The problem with a layered architecture for a complete solution was, that when clients had used our solutions in sometime, they came back to us wanting new functionality or changes to existing functionality. As all functionality was packed into the same layer in one big complex solution, it meant that we couldn’t just pull out parts of the functionality and replace it, as it was bundled together. Not knowing what functionality was using special parts of the code, meant that the developers didn’t dare to change existing functionality, as they were afraid what side effects it might have.
Mikkelsen defines a component as:
[A]n independent group of classes, renderings, templates, database and/or items, which represents a logically grouped set of functionality and is independently deployable.
Each element of functionality, such as navigation, authentication, or search, is placed in a separate project, complete with any renderings, templates, or database calls necessary to implement the solution.

Separation of Concerns

Further, there should be no dependencies between one component and another.  For example, a navigation project would contains the renderings for drawing navigation elements, and also the template elements that mark an item for inclusion in the navigation.  No element outside of the navigation project needs to have any knowledge of the workings of the navigation components, and the only dependency that navigation has on outside templates is that they must inherit the _NavigableItem template.  It is immediately apparent that a Navigation component so designed could be dropped in to any Sitecore project and be functional in short order.

The article recommends the following structure:

  • Group component projects inside Website/Components.  For example, Website/Components/Navigation, Website/Components/Design.  Use a post build command to copy the DLL up to Website/bin.
  • Use the same structure for templates. Instead of placing custom templates in the classic "User Defined" folder, put them in Templates/Components/.
  • Templates are broken out into inheritable chunks, such as _documentHeader and _documentBody.  The field names are prefixed with the name of the component (Document_Header, Document_Abstract).  This works as a kind of namespace to avoid conflicts with other templates.
  • Rendering and sublayouts also have a Component folder tree for their content items.  The associated files go into the component projects themselves.  So a Breadcrumb.xslt would go under Website/Components/Navigation, and the related content item would go under Layout/Renderings/Components/Navigation
  • A special PageTypes component ties the different elements together.  A PageType template is assembled through template inheritance from the templates defined in the other components, and the presentation uses the renderings, web controls and sublayouts defined in these other components. The other components form the building blocks, and the PageType is where they are put together.

Why This Works

This approach has a number of advantages:

  1. It enforces a logical, consistent structure on the placement of templates and presentation components.
  2. Presentation source files are logically grouped with the entities they present,  rather than arbitrarily placed in an XSL or Sublayouts folder.
  3. It encourages decomposition of templates into specific functional areas.
  4. It sidesteps the problem of where to place Sitecore elements.  Sitecore offers both presentation and data, so it breaks the classic N-Tier approach.  A rendering is clearly a presentation component, but the fields of the context item are arguably a data element.   
  5. It groups things together things that will be changed together. Imagine a trip pricing wizard that needs to present back-office data on a website.  Having the presentation, logic and  data elements grouped together in the same project will clearly simplify maintenance and enhancements.
An Endorsement from the C.I.G.
What really sealed the deal for me was using the Custom Item Generator with templates that were organized in this manner.  Select Generate Custom Items on the Template/Components folder:

Now set the Custom Item Root Path tooutput to "Website/Components":


Now the CIG will magically drop the generated class files inside the appropriate projects:


Pretty sweet! That's the power of following exactly the same organization for templates, renderings, layouts, data entities and projects.

No comments:

Post a Comment