Skip to content

Commit

Permalink
[#33] updated Template References section for Helix Examples
Browse files Browse the repository at this point in the history
Also:
* fixed #26 - Use static classes instead of structs
* fixed #19 - Clarified language around referencing across modules
  • Loading branch information
nickwesselman committed Oct 22, 2019
1 parent c7771d0 commit 54edd4b
Showing 1 changed file with 70 additions and 43 deletions.
113 changes: 70 additions & 43 deletions helix/principles/templates/references.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,77 +12,80 @@ field names if needed. Furthermore, hardcoded GUIDs tend to stick out in
code and views and therefore makes it easier to detect and avoid
implicit dependencies to templates and fields.

Define constants for a module’s templates in a single struct named
Templates. This struct is located in the root namespace for the module.
Define constants for a module’s templates in a single static class named
``Templates``. This static class is located in the root namespace for the module.
This makes it easy to explicitly reference a template in the business
logic or views and makes it easier to discover references to a template
or field. The conventions define this as structs to clearly signal the
Templates type’s unique function as a constants holder only.
logic or views of the module and makes it easier to discover references to a template
or field. The conventions define this as a static class to clearly signal the
``Templates`` type's unique function as a constants holder only, following the
`conventions for Constants in the Microsoft C# Programming Guide <https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/how-to-define-constants>`__.

Each Templates struct should have a nested struct for each template
which each contains an ID member and a nested struct, Fields, which
The ``Templates`` static class should have a nested static class for each template
which each contains an ID member and a nested static class, Fields, which
contains all fields in the template.

.. admonition:: Habitat Example
.. admonition:: Sitecore Helix Examples

The following shows the Templates struct for
Sitecore.Feature.Navigation:
The following shows the ``Templates`` static class for the *Feature / Basic Content* module in Helix Basic Company.

.. code-block:: c#
namespace Sitecore.Feature.Navigation
namespace BasicCompany.Feature.BasicContent
{
using Sitecore.Data;
public struct Templates
public static class Templates
{
public struct NavigationRoot
public static class PromoCard
{
public static readonly ID ID = new ID("{F9F4FC05-98D0-4C62-860F-F08AE7F0EE25}");
public static class Fields
{
public static readonly ID Link = new ID("{B788E8BC-E944-4A2B-A4BE-3424643D322B}");
public static readonly ID Image = new ID("{21249F44-5F0F-4CFA-9474-8D72930D6575}");
public static readonly ID Headline = new ID("{4F73C02B-93CC-4C96-B9FF-9D0D8E853ED6}");
public static readonly ID Text = new ID("{13EB8DCA-281D-4E75-B6E1-701CA719BCD1}");
}
}
public struct Navigable
public static class SectionHeader
{
public static readonly ID ID = new ID("{A1CBA309-D22B-46D5-80F8-2972C185363F}");
public struct Fields
public static class Fields
{
public static readonly ID ShowInNavigation = new ID("{5585A30D-B115-4753-93CE-422C3455DEB2}");
public static readonly ID NavigationTitle = new ID("{1B483E91-D8C4-4D19-BA03-462074B55936}");
public static readonly ID Text = new ID("{59D24D0A-F955-4988-B26F-92039B4DF8BD}");
}
}
public struct Link
public static class HeroBanner
{
public static readonly ID ID = new ID("{A16B74E9-01B8-439C-B44E-42B3FB2EE14B}");
public struct Fields
public static class Fields
{
public static readonly ID Link = new ID("{FE71C30E-F07D-4052-8594-C3028CD76E1F}");
public static readonly ID Title = new ID("{5179186C-B95E-4E97-95AB-7958721A9AEB}");
public static readonly ID Subtitle = new ID("{89B0A8ED-0EE8-4512-B518-AB2C4C2A0B9E}");
public static readonly ID Image = new ID("{B5F61442-FF0F-46A5-90A8-D6D387DE24A0}");
}
}
public struct LinkMenuItem
public static class AccordionItem
{
public static readonly ID ID = new ID("{18BAF6B0-E0D6-4CCE-9184-A4849343E7E4}");
public struct Fields
public static class Fields
{
public static readonly ID Icon = new ID("{2C24649E-4460-4114-B026-886CFBE1A96D}");
public static readonly ID DividerBefore = new ID("{4231CD60-47C1-42AD-B838-0A6F8F1C4CFB}");
public static readonly ID Title = new ID("{5718E787-142B-41D9-B5A1-0B18F45B8236}");
public static readonly ID Content = new ID("{45EFE66E-5AD2-4F1D-BAD5-FDF281688681}");
}
}
}
}
A templates class should never define constants for templates that are
not created in the module itself. If a module needs to reference a
template or field in another module, it should reference the Templates
struct in that module.
A ``Templates`` class should never define constants for templates that are
not created in the module itself. In cases where Sitecore Helix conventions
allow a module to reference another (e.g. *Feature* to *Foundation*, or *Project*
to *Feature*), if a module needs to reference a template or field in that module,
it should reference the Templates struct in that module. Or better yet, that
module could expose an extension method or other means of consuming that template,
to avoid directly referencing the ID constants, as this dependency could make future
refactoring more difficult.

The practice of referencing different fields across modules by their
shared name – an equivalence to *duck typing* – is discouraged.
shared name – an equivalence to *duck typing* – is strongly discouraged.

.. note::

Expand All @@ -107,9 +110,33 @@ inheritance object-oriented programming, it is important that, when
querying an item’s template, you not use the *equals* operator but
rather an *is* operator.

.. admonition:: Habitat Example
.. admonition:: Sitecore Helix Examples

The *is* operator in the Sitecore Item API is the `DescendsFrom`
method on the `Item` class, which accepts a Template ID. This allows
you to determine whether an item directly or indirectly inherits from a
template. You can see this used in Helix Basic Company's `HeaderBuilder`
class:

.. code-block:: c#
// Collect home/root item and its children which are navigable
var items = new List<Item> { navigationRoot };
items.AddRange(navigationRoot.Children.Where(item => item.DescendsFrom(Templates.NavigationItem.Id)));
When querying for a specific base template via Content Search query, you
will need to enable the ``_templates`` computed field. See the
``Sitecore.ContentSearch.[SearchProvider].DefaultIndexConfiguration.AllTemplates.config.example``
example patches in your Sitecore installation, or the ``Feature.Products.ContentSearch.config``
in Helix Basic Company.

With this computed field available, you can map and query it in Content Search code:

.. code-block:: c#
The *is* operator is not native to Sitecore items and templates.
Sitecore Habitat introduces the IsDerived extension method for the Item
class. This method is located in the
Sitecore.Foundation.SitecoreExtensions.Extensions.ItemExtensions class.
var results = context.GetQueryable<ProductSearchQuery>()
.Where(product => product.Paths.Contains(parent.ID) && product.Templates.Contains(Templates.Product.Id))
.Select(x => new {
Uri = x.UniqueId,
Database = Factory.GetDatabase(x.UniqueId.DatabaseName)
}).ToList();

0 comments on commit 54edd4b

Please sign in to comment.