Life Through a Lens – Mappers and Wrappers

Mike Edwards (at SUGCON 2015) did an awesome presentation on data modelling (I would highly recommend you check it out if he re-runs it) on the pros and cons of how to model data. Glass Mapper (unlike wrapping frameworks – Synthesis / Fortis) is uses the Data Mapper pattern to represent data. He also wrote a great post here – http://www.glass.lu/Blog/TemplateVsRendering

This gives distinct advantages in the functionality it can provide in terms of its exposure of native .net types, its ability to be able to read / write between databases, control of serialization, non-reliance on code generation, mocking, testing, caching etc.

It does also have the downside of being heavier on instantiation in comparison to simply wrapping the item and performing casts on demand. It is also further away from the originating record. This also means that unlike wrapping frameworks, the number of mapped properties will actually also impact the overall performance.

Mike also talked quite heavily about what he termed to be bloated models. A ‘bloated’ model is where your code is using data models that have a much greater number of properties than are required by the code (i.e. 20 properties where you use only 2). This is similar to the Interface Segregation Principle. Many developers use models that represent their Sitecore template structure (a practise that I heavily disagree with) and as such will invariably work with bloated models for this reason. However, this is not the case for all developers and I would always advise spending the time researching modelling of your data.

As Mike, Kam and Jason Bert would probably all agree. The options for a wrapper to be lazy with it’s loading are much more easily solved than with a mapper. This can be demonstrated at a basic level if you look at what a wrapper does – which is very broadly like this:


public class MyItem
{
    private readonly Item item;

    public MyItem(Item item)
    {
        this.item = item;
    }

    public string Name
    {
        get { return item.Name; }
    }

    public string Field1
    {
        get { return item["Field 1"]; }
    }
}

A mapper on the other hand does something more like the following:

public class MyItem
{
    private readonly Item item;

    public MyItem(Item item)
    {
        Name = item.Name;
        Field1 = item["Field 1"];
    }

    public string Name { get; set; }

    public string Field1 { get; set; }
}

In the case of the mapper, the work is done up front (this can include casting, children, parents etc). The wrapper has the luxury of doing this on demand.

This would result (to be a fair test for the level of work) as similar to:


items.Select(x => new MyItem{ Property1 = x["Property 1"], Property2 = x["Property 2"] .... all the way to 20 }).Select(x.Property1);

Which is why it is important to figure out what your choice of ORM is doing.

Impact

Having watched Anders Laub’s (also fantastic) presentation at SUGCON also on component based architecture, he mentioned a simple principle from Uncle Bob (Robert C. Martin) called the Stable Dependencies Principle (SDP). The gist of this is that your code should only really depend on code that is more stable than itself. This lends weight to my argument against code generation on the Sitecore platform. By being reliant on templates that are prone to change, you are in effect creating a dependency on changable code. Also, because you cannot reliably extend upon these classes, it could easily be argued that you are breaking OCP, since they are not really (by implicit design if nothing else) open to extension (since their name / template / whatever can be changed) or indeed closed to change. I think this is the biggest reason that wrapping based solutions on the Sitecore platform don’t sit so well with my development ideals (though I do like the idea of being lazy and not having to write a tonne of properties πŸ˜‰ ).

Conclusion
I love what all of the ORM’s in the Sitecore space do for us in simplifying our daily development lives, I would recommend you think about modelling your data. Also, and more importantly – think about how you represent the data in your database inside your application.

Advertisements

9 thoughts on “Life Through a Lens – Mappers and Wrappers

  1. Pingback: Life Through a Lens – Glass Mapper Relative Performance | CardinalCore

  2. Hi Nat, great article, as always! One thing I like about code generation, and more specifically *build-time* code generation, is the consistency guarantee between your data templates and the code that works with items that are based on those templates. I can still remember the pre-annotation Java XDoclet-based code generation that was kind of doing the same thing for Hibernate, SOAP services, etc.

    Basically, your unit test coded against the non-generated model class won’t spot a change in the data template (be that a field type change, a field name change, etc.) until you run everything integrated in Sitecore. At the same time, like you said, code generation with a mapper will inevitably produce bloated models. Same with a wrapper, of course, but as you pointed out the overhead tax is a lot less. Synthesis doesn’t (yet) do build-time code generation from your serialized templates. I asked Kam just this past weekend and the yes/no question received a pull-request-would-be-nice answer πŸ™‚

    Would you still feel the same about code generation if it was built-time and wasn’t producing highly taxed models? Or maybe, with a mapper, a built-time validation of your hand-coded not-bloated models to show you where you’re behind on your mappings?

    • Hey Pavel,

      Thank you so much for your reply πŸ˜€

      I think in truth I will always be a little anti – code generation. I don’t see the overhead (additional coding) and thought that goes into is as much of an issue.

      I believe that code-gen for the wrapping model would indeed benefit from it being done at build-time under *certain* circumstances, though I still think you have issues in that (especially if you use the likes of unicorn) since when you change between branches (say in git) you risk losing data etc. So I guess in Wrapping Frameworks it is a necessary ‘evil’

      I personally (and have said to Mike several times) would like to see a ‘CanMap()’ type method to be able to check type mapping in Glass Mapper – its on the ‘wish list’ as I think it would be pretty awesome even if just for builds. But I still think the thought behind Glass models needs to be greater from the developer given the upfront costs. I think (another feature I have on the wish list) implementing increased Lazy support would allow for better codegen on Glass, since it would start to behave a little more like a mapper / wrapper hybrid.

  3. Hi Nat, great article! Would like to hear your opinion about 2 things:
    – Seeing the code generation discussion, what do you think about the code-first approach (big fan here) I suspect the whole idea about bloated models is a reason but:
    – Glass supports lazy loading, where virtual properties get intercepted, doesn’t this meet the requirements?

  4. Hey man, thanks for your feedback.

    I do confess I know less about the code first approach on Glass than I ought to, mostly since I have have never had an issue with writing models and manipulating my data as 2 operations. I think for me that stems from the fact that doing it in both locations it gives me a second chance to think about my approach (kinda self – pair programming in a way). At it’s core, code first does in theory make sense, however, I still consider it the lesser of the two evils as it would not really make you think about model / template reuse in the way I believe Glass can / should be used.

    Consider for example a template looking like this (imagine a call to action):

    MyTemplate1:
    Title Single Line Text
    Image Image Datasource=/sitecore/media library/some place in my tree

    MyTemplate1:
    Title Single Line Text
    Image Image Datasource=/sitecore/media library/some place in my tree

    MyBaseTemplate
    Title Single Line Text

    MyTemplate1 : MyBaseTemplate
    Image Image Datasource=/sitecore/media library/some place in my tree

    MyTemplate2 : MyBaseTemplate

    Image Image Datasource=/sitecore/media library/some other place in my tree

    Realistically in code I would always want to treat this as a single model as they will be interchangeable. I could also infer templates if I chose to as well (if I wanted switch logic for example).

    On your point about Glass’ lazy loading proxies:

    Its worth noting that the lazy loading only takes place (as far as I understand it) for relationships – i.e Parent, Children, Multilists etc. It still has to map every string / image etc. I am potentially going to attempt a proof of concept for more full Lazy support, though that is a different matter. In my recent performance tests on Glass – the MAJORITY of the time is spent in the Sitecore API, things like images / links / multilist parsing / urls and even just basic getting of strings all add weight. So whilst lazy loading (as it stands right now) helps, it’s not a silver bullet.

    • Nice post and interesting discussions in the comments. Adding my feedback, feel free to comment or correct πŸ™‚

      fyi: I work with EPiServer and Sitecore.

      1.
      I agree that from an Architectural perspective its always better to not have a 1-1 mapping between .net classes and your CMS/Database.
      However you can see code first or generated classes just as a separate layer. If you really want you can add another layer of .net classes which do not resemble your CMS structure. This layer would be an abstraction of any CMS or database you are using.

      2.
      If you work with a CMS and you want to enable the WYSIWYG editor feature you will always need some kind of reference to a CMS item/field, so you can never decouple from the CMS completely.

      3.
      I like the code first approach in episerver as it makes deployment so much easier.
      On a live environment you only want to push definition and rendering templates only and not content items.

      4.
      TDS is a great tool but it takes some time to sync for developers every time they take an update.
      With a small development team in the same physical location, i have used a shared database to avoid all the hassle.

      5.
      Is there a reason why code first is not so popular in Sitecore? Which Code First libraries are out there besides glass? Is anyone using it?

      • Hey there, thank you so much for your response.

        I guess to respond to your points:

        1. I agree you could see it that way, and if you wanted to achieve that intermediary layer then you might be better with a wrapping based solution. I personally choose not to write my code like that regardless of the underlying data storage (cms / nosql / sql alike), when you consider (for example) stored procedures in SQL server then you already have a modified view of the underlying tables with all the inbuilt security and speed that it affords, I see no need to recreate that again in another tier. Same goes really (for me at least) in a CMS – you already have their representation of their data.

        2. I agree you can never decouple from the CMS, but Glass for example allows you to write your code with no direct reference to the Sitecore item. I have worked with Synthesis reasonably recently and you can do fairly similar with that (though the way they achieve it is somewhat different). So yes – I agree, you cannot decouple your solution from the CMS, but you can certainly achieve most functionality without any direct reference to it.

        3. The code first approach presented by episerver is neat and for me has its advantages and disadvantages. As I understand it, in Episerver in order to change / manipulate templates you must change .net code – as you stated – great for deployments. However I feel you can achieve a lot in Sitecore / Umbraco without opening visual studio if your code is developed well which is not a luxury afforded by the code first approach. In organisations (in particular where there is no continuous delivery) then this can lead to frustration for end users.

        4. Not sure how this relates to the post, but I like both TDS and Unicorn to achieve what I need on that front. I sometimes find TDS is a sledgehammer for the nut in my developments. I don’t however recommend shared db’s as a general rule since I think it can get cluttered very quickly with people being afraid to remove stuff.

        5. I don’t actually know of any code first libraries other than Glass Mapper, code first has issues in the first instance as you are required to write a data provider to translate the c# classes into templates.

        As you will know if you read my posts in general. I as a developer have never been happy with code first / code gen approaches. I think that – dating back to sql server days, too many developers used it to avoid / absolve themselves of the responsibility of the database server and thus often made bad decisions for the database. In the CMS arena it largely depends on your approach, but for me, I still like dealing with what I need, not a collection of stuff. I understand that I differ from the views of many other developers in the space. I know several developers who use code gen on Glass Mapper and other frameworks.

  5. Hey Nat, thanks for the article!

    Would you mind going into more detail about this particular sentence? “Many developers use models that represent their Sitecore template structure (a practise that I heavily disagree with)”

    I’m researching component based architecture at the moment but historically my solutions have always used base templates which I map using interfaces in code, so would love to have more detail on why that might not be a good idea!

    • That particular phrase refers to the practise of mapping your entire template hierarchy to .net classes. I believe that in the majority of cases that the invariable growth of the templates should not be represented in your code directly – so in essence – you should write your .net classes to fulfil their purpose in the codebase, not to represent what your underlying data structure (I also believe this of SQL databases) .

      There are also a number of other advantages to this practice in the following:

      • Your codebase has no need to change due to naming / structural changes
      • You can often reuse classes that despite changes in data source locations etc
      • You have no need to maintain / regenerate classes or interfaces on change

      I am pushing for Glass Mapper to have a CanMap() type functionality for integration testing purposes.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s