Monday, March 17, 2014

Classification With Lodash groupBy()

It's seldom that the API data returned by your application server will have everything you need to render the user interface you're after. Do you ask the API team to extend the data schema to fit your front-end design? Not unless the rewards are huge. And sometimes that's the case. For example, if there's a field that the front-end code needs, and has to jump through hoops in order to get, then you obviously benefit from having the field as part of the API. Especially if it's used everywhere in the UI. What's more common, however, are the edge-cases where we need some piece of data that just isn't part of the API. Extending the API is just way too much effort — much greater than the reward. An example of this type of front-end manipulation is classifying data with the help of lodash.groupBy().

The function takes an array of objects and groups them by some condition. For example, I can write a callback function, and pass that to groupBy(). The callback takes the current object of the array as an argument, and returns the classification, or group, of that object. The resulting object returned by groupBy() uses the keys returned by our callback function. For example, consider the following code.

var objects = [
    { age: 1, name: "name1" },
    { age: 2, name: "name2" },
    { age: 3, name: "name3" },
    { age: 4, name: "name4" },
    { age: 65, name: "name5" },
    { age: 35, name: "name6" }
];

_.groupBy( objects, function( value ) {
    if ( value.age < 35 ) {
        return "young";
    }
    return "old";
});

Despite the controversial classification of 35 as old, this code is a condensed, and self-contained way to expand upon our application API data. The API gave us exactly what we needed here, actually. The age property is something that's used all over the user interface, and so it makes logical sense to include that as part of the API data schema. Determining whether someone is "old" or not, probably has no bearing on the API schema at all. And it's these little properties that we don't necessarily want as part of the API. They add unnecessary weight to the application.

With this simple little chunk of Lodash code, we're able to get what we need from the existing API model. Something else you might notice about this approach is that it's transient — we're not computing something to store on the client either. For example, sometimes in Backbone applications, we have to define a Model.parse() method to add additional model properties. The UI probably needs these, I hope, but then they exist throughout the duration of the model. That might be a bad thing, depending of the lifetime of the model, and t's how the property is used by the UI. You don't want to compute a new property, store it indefinitely, only to use it in one place throughout the user interface.

Something else that's useful about this transient approach to grouping objects is that it allows me to easily change business rules. These are often what define how the classifications, such as the one above, work. Being able to easily change this logic in one place in the front-end is a huge bonus for me.