CodeFirst Post-Mortem

Friday, December 12, 2014 9:00 AM umbraco

Each CodeGarden traditionnaly hosts a CodeFirst open session, and every six months or so a project or package is born that aims at providing the ultimate CodeFirst solution—yet none has really succeeded so far.

Pete Duncanson started to express doubts about CodeFirst in his May '14 blog post. Basically, he says, it looks easy to do and cool to use, but in the end it ain't neither. Fast-forward to Nov '14 and the UK Festival: Pete's gone beyond doubts, and his talk about CodeFirst basically puts a final nail to the coffin.

RIP CodeFirst.

Post-Mortem

What killed CodeFirst? In my mind, it is trying to solve too many problems with one unique solution, and ending with complex beasts that are only 80% complete and do not, ultimately, solve anything. So, CodeFirst is not the right solution, and we're left with the problems. We want:

  1. A way to apply changes to an Umbraco site (add a property, migrate a property, modify a content type, create a template...) in a way that can be controlled (I can see what's going to happen) and reproduced (I can trigger the same set of changes on a production environment).

  2. Strongly typed models in our views, so we can render @Model.PublishedDate and not @Model.GetPropertValue<DateTime>("publishedDate") and have Intellisense in Visual Studio.

Anything else? I'm not sure: what's your take? Because, taking these problems one at a time, it becomes easier to address them.

Strongly-typed models

That one is actually almost solved already. Umbraco version 7.1.4 introduced a builtin models factory that can map any cached content into a strongly-typed content model.

Those models can be fully generated, using eg my own ModelsBuilder which essentially is a code generator. Or you can write simple POCOs by hand and use tools such as Lee Kelleher's Ditto POCO mapper to do the mapping.

There are various solutions, depending on how you like to code and do your MVC, and these solutions will still probably evolve in time. They need you to fiddle with some code—but they work, now.

Change management

"Change management" might well become more and more important as clients want to make evolutions to that nice website you created for them two years ago, and you need to add a property here and there, and maybe re-organize those content types...

At the moment, "change management" consists in doing changes in the developer's back-end, and carefully writing down each change on a sheet of paper (or the back of an enveloppe), and reproducing those changes in the production back-end when going live, and hopefully it works.

The way CodeFirst tried to solve it, was by having one giant definition of what the site should be, and comparing the site against that definition, and applying changes. In the database world, that would be comparing the production database against a "reference" database and apply changes. And it does not work, because it cannot understand simple things such as renaming a field. So we use scripts that alter the database in a controlled way.

We want the same sort of thing for Umbraco. We want to be able to use the UI when we feel like it (because the fastest way to fix a typo in the description of a property may be to edit it on the live environment), and yet to be able to script some changes.

How can we get there?

Aaron Powell introduced his tool Chauffeur in a June '14 blog post and although I haven't been able to find time to review it, I do believe it goes in the right direction.

The uMigrations tool proposes to "enable the developer to make changes to the Umbraco database from code using the available API's from Umbraco" by running "migrations" in sequence.

On some websites I maintain, I use my own Zbu.Yol solution which basically is a simple state machine that executes code on each transition, and that code uses the new Umbraco services API to do changes.

The good thing about using Umbraco's API is that is reduces the amount of code to write—and to maintain—in each tool. Ideally, the tools would take care of triggering the changes, while the Umbraco API would natively execute them.

It still is a bit cumbersome (because the Umbraco API is a bit cumbersome...) but it works. And, as the Umbraco API gets cleaner and cleaner, those types of solutions are going to make more and more sense. What do you think?

comments powered by Disqus