Why I Quit uSiteBuilder

If you've seen my previous articles you'll know that I'm a big fan of uSiteBuilder, a software framework that allows for code-first development with Umbraco. I didn't expect it come so soon, but I've now stopped using it on all new projects, and that's a good thing.

Why I had to change

Now I've firstly got to explain, I have not decided that uSiteBuilder is a bad piece of software; it's absolutely fantastic! My teams loved the fact that document types could be source controlled and the intellisense provided by strongly typed models eliminated those annoying typo bugs; being able to use proper object oriented programming with Umbraco was awesome!

That said, uSiteBuilder didn't come without niggles. The startup sync time was a real downside, even though the back end package reduced this problem significantly. More significantly was its refusal to play nicely with Umbraco 6. Even though the changes in version 6 weren't hugely important from a website point of view, our commercial department wanted to show that the sites we could offer clients were using the latest technology available. When I tried to upgrade our base build to v6 on multiple occasion it failed. It was then I realised that I had a problem and it wasn't necessarily uSiteBuilder's fault, it was mine; everything I built was so tightly coupled to it that my software had a massive single point of failure, and considering that the solution I was building was meant to be the base for all (or at least most) Umbraco projects in the agency, I had introduced a huge risk to all our future projects!

It helps to give a little context on what our base build is. We noticed that a lot of the functionality we build is similar from project to project, and we wanted a way to reduce build times, improve quality and offer clients a more competitive price. We decided that we would spend some time creating a project that contained some reusable components all using a common architecture; uSiteBuilder made a great candidate for this architecture because of its version controllable files and strong typing. So over the last year, me and other members of my team built this solution up and used it for a base on multiple projects.

There's always a time to change though, and with the imminent release of v7 (formerly known as Belle) I decided that we needed to decouple our base build from uSiteBuilder so that we could keep up with the rapidly changing world of Umbraco. 

Why it is a good thing

This new(ish) start meant that I could fix the errors that I made when designing the architecture we use in our Umbraco solutions, and that would start with our model project, the one with all the code representations of the document types.

Before, this project relied on uSiteBuilder, and subsequently all projects that referenced the 'Model' project had to reference uSiteBuilder too. I knew that this couldn't be the case this time round, and so a radical new design decision was made; now the 'Model' contains nothing but interfaces, the concrete implementations are in a separate project entirely. This dramatically reduces the coupling between the web application project and the actual concrete implementations of the strongly typed document type classes. The web project now doesn't care whether we use uSiteBuilder or a custom built provider, as long as they implement the interfaces in the 'Model' project. This decoupling can also future proof the base build; if a strongly typed content service makes its way into core, all we have to do is implement the interfaces in the new way, hook up the new content provider / service (especially easy if you use IOC like I do) and the project works as it did before.

Another benefit of this is that you can create as many interfaces as you like, specialised or generic, rather than using the whole document type in code. This is the I of SOLID, Interface Segregation, and will promote the creation of code that is portable, easy to maintain and easy to refactor.

So lets make a simple example of this.

Example

Disclaimer: I'm writing this code on a train with no internet and no Umbraco projects to look at, I may get class names wrong etc. This is just an illustration, not a tutorial.

Model Project

    interface IPage
    {
        string MainTitle { get; }
    }
    interface IPaginated
    {
        int AmountPerPage { get; }

        IEnumerable<IArticle> Articles { get; }
    }
    interface ISortable
    {
        string Name { get; }
    }
    interface ISortableByDate : ISortable
    {
        DateTime CreateDate { get; }
    }
    interface IArticle : ISortable
    {
        string MainTitle { get; }

        string Summary { get; }
    }
    interface IBlogHub : IPage, IPaginated
    {
    }
    interface IBlogArticle : IPage, IArticle
    {
    }

Concrete Model Project

    class Page
    {
        string MainTitle { get { return GetUmbracoPropertySomehow(); } }
    }
    class BlogHub : Page, IPaginated
    {
        int AmountPerPage { get { return GetUmbracoPropertySomehow(); } }

        IEnumerable<IArticle> Articles { get { return GetUmbracoChildrenSomehow(); } }
    }
    class BlogArticle : Page, IArticle
    {
        // IArticle
        string MainTitle { get { return GetUmbracoPropertySomehow(); } }

        string Summary { get { return GetUmbracoPropertySomehow(); } }

        // ISortable
        string Name { get { return GetUmbracoPropertySomehow(); } }

        // ISortableByDate
        DateTime CreateDate { get { return GetUmbracoPropertySomehow(); } }
    }

MVC Web Application

Controller
    class BlogListingController : SurfaceController
    {
        public ActionResult Index(int hubId)
        {
            // However you choose to get your nodes, example here uses uSiteBuilder like syntax for familiarity
            IPaginated blogHub = ContentHelper.GetByNodeId(hubId) as IPaginated;

            return PartialView("BlogListing", blogHub.Articles)
        }
    }
View
    @inherits PartialViewPage<IEnumerable<IArticle>>

    @{var articles = Model;}

    <ul>
    @foreach(IArticle article in articles)
    {
    <li>@article.MainTitle</li>
    }
    </ul>

Conclusion

As you can see, the MVC application is completely decoupled from the specific implementation of the strong document types. This design is way more maintainable and flexible, and even though it may take a fraction longer, ReSharper can do a great job of extracting interfaces from classes, so no excuses!

Now I can create my reusable components using this architecture, knowing that in the future I'm in a good position to adapt to whatever the Umbraco community throws at me, whether that's a shiny new version of uSiteBuilder, Glass for Umbraco, uSync, native code first or some other project that has not yet been devised.

Comments

comments powered by Disqus