Jason Naso Jason Naso - 7 months ago 18
Javascript Question

Don't Repeat Yourself

Would like to know if there is a better way to write this small block of code keeping DRY in mind. I see the similarities in the functions of course, but I am not sure how to shorten it. Also, I would like to know how much of a difference the shortening would make if any. Thank you, Jason

var adminAlert = {

alert: function() {

var sumAlert = sumSupport = sumCashout = sumPhone = 0;

$.getJSON("alertFeed.JSON", function(data) {

$.each(data.alertData, function(i, allAlerts) {

sumAlert += parseFloat(allAlerts.value);
sumSupport += parseFloat(allAlerts.support);
sumCashout += parseFloat(allAlerts.cashout);
sumPhone += parseFloat(allAlerts.phone);

$(".alertPoints").html(sumAlert);
$(".support-requests").html(sumSupport);
$(".cashout-giftcards").html(sumCashout);
$(".phone-verification").html(sumPhone);
});
});
}
};



Answer

The version undernearth is more DRY. Basically, to make your code DRY, you:

  1. Identify repeated stuff. In your case it was parseFloat(allAlerts.foobar) and $(".blablabla").html(foobar);
  2. Identify what is different between those repetitions. In your case you used a series of 4 keys within the allAlerts object: 'value', 'support', 'cashout' and 'phone'. Each of those 4 keys correspond to a CSS selector, e.g. cashout corresponds to ".cashout-giftcards";
  3. Take what you identified in step 2 and put it into a declarative map. In your case:
{
    'value': 'alertPoints',
    'support': 'support-requests',
    'cashout': 'cashout-giftcards',
    'phone': 'phone-verification'
}

4. Replace what you identified in step 1 with a more unified / abstract code using the map you created in step 3. In your case, the four lines like sumCashout += parseFloat(allAlerts.cashout); can be replaced with only one line like sum[k] = parseFloat(allAlerts[k])

var
// To avoid repeatedly doing stuff like $(".alertPoints").html(sumAlert),
// we'll declare a concise map defining what will be updated by what:
    map = {
        'value': 'alertPoints', // later we will use this to update $(".alertPoints") with what comes from allAlerts.value
        'support': 'support-requests', // later we will use this to update $(".support-requests") with what comes from allAlerts.support
        'cashout': 'cashout-giftcards',
        'phone': 'phone-verification'
    },
    adminAlert = {
        alert: function(){
            var
                // Let's define an object that will hold the sums for us
                sum = {},
                // And also a variable to iterate our map;
                k;
            $.getJSON("alertFeed.JSON", function(data) {
                $.each(data.alertData, function(i, allAlerts) {
                    // So we have 4 things to sum and update.
                    // They all are defined in our map.
                    // Lets go through the map and get things done:
                    for (k in map) {
                        // The value of k will be "value", "support" etc...
                        if (!(k in sum)) {
                            // In case the `sum` object does not yet have a key equal to the value of `k`, we initiate it.
                            // This is to have a start value of 0 to start adding to it:
                            sum[k] = 0;
                        }
                        // This is effectively the same as
                        // sumAlert += parseFloat(allAlerts.value) etc. etc.
                        // but written in unified manner to cover all the four cases.
                        // So when say `k` equals to `cashout`, this
                        // will be the same as `sum.cashout += parseFloat(allAlerts.cashout)`
                        sum[k] += parseFloat(allAlerts[k]);
                        // Again, a unified version of
                        // $(".alertPoints").html(sumAlert) etc. etc.
                        $('.' + map[k]).html(sum[k]);
                    }
                });                
            });
        }
    };

In terms of difference — it is just easier to maintain / fix / debug / extend etc. Performance will probably be about the same.