Wednesday, 20 March 2013

View Driven Data Design; don’t let your view shape your data

Recently I have found myself coming across a couple of view to data scenarios where you can see that the view has driven the data model. This makes my spidey sense tingle as this strikes me as too tight coupling between data and view.

So what am I actually talking about? I’ve called it “View Driven Data Design”.

So an example to make things clearer; any developer who has been in the business long enough will have had the opportunity to work with a UI which involves category and sub category dropdowns / pickers. These values are usually driven by a data source (database, xml definition etc.) which are dynamic. What do I mean by dynamic? I’m referring to none hard coded values which require recompilation to be available. Either through an administration function, a nightly batch job updating the data or through a configuration file. These can have some cascading / restriction functionality built in to improve usability but are dynamic. These values can be stored by id – usually Foreign Keyed to the source – to allow for normalisation etc. This is fine for this scenario however there are times when this approach is overkill and can cause future issues and frustrations.

Imagine a scenario where you have an single data item (entity) which is modelled as a single class definition. An instance of this class requires classification. Unlike our earlier example the “category” is driven by a list of hard coded enum values. The UI designer has specified that on a specific value of category there will be another option to further categorise the entity. This is also driven by a distinct number of values in another enum. Further more there is a specific correlation between category and sub category options. So like before these values can be stored on two properties of the entity. What’s wrong with this I hear you ask? On the face of it nothing is wrong. It is however when you come to use these categorisations in other parts of the system when the problems creep in.

So you’ve created the instances in your CRUD section of the application and it’s all running fine however you now have another requirement to use them in a different form and you require to run some logic depending on classification – this is where the issue raises it’s ugly head.

When trying to classify an instance of the entity you now need to check different combinations of two properties. This involves the same business logic being put in, potentially, multiple places in the code base which is bad. If there are other values to check as well this adds unnecessary noise and complexity to the business logic. So how do we make the developers life easier and keep the UI designer happy at the same time?

It all starts at the data model level and answering “what value(s) do we actually have to store and how can this improve code clarity?”.

Start off by looking to see if the distinct list of defined combinations between the two enum sets can be merged into one set. If there are two many options then leaving them split will probably need to remain, however if the sub categories only apply to a small number of main categories then making one set may be on. This will need to be determined on an implementation case by case basis.

Right we have one property on the entity and the UI designer still wants their category and sub category dropdowns with visibility rules etc. This is where we need to loosely couple the data model away from the view. This is the exact reason why we have the concept of a view model. Using the entity data model we can define and populate a specific model to drive the view. In this case this will probably include like for like property mapping where nothing special needs to happen (eg. simple text values such as names) but for the single category enum it will need to get mapped to the two different options and can then drive the visibility rules etc. On the save action a conversion can map from the two options back into one ready to save.

This allows for the UI to be driven with the user experience the designer/analyst required while also making further business logic simpler and clearer to understand for the developer; both to write originally but also for future code maintenance.

So in the future when your designer wants fancy dropdowns and categorisations take a moment to ask does it need to be stored that way? Your future self will thank you instead of taking your name in vein.

No comments: