Tania Rascia

Skip Navigation
Basic Refactoring: Don’t Repeat Yourself

Basic Refactoring: Don’t Repeat Yourself

 /  3 responses

Refactoring is the process of editing code to improve efficiency and readability without changing the output. I made a little example to demonstrate how a beginner can start refactoring their code. This mini-tutorial covers the DRY (Don’t Repeat Yourself) concept, and might come in handy in the future.

Let’s say I have some data in the form of a JavaScript/JSON object or array. The data and how it’s formatted doesn’t matter much here, it could be much more complex, but I’m leaving it simple for example’s sake. (It could come from an API, but I’m going to leave out the step of fetching data for this example as it’s irrelevant.) Here’s our data:

data
var sessions = {
    "mobile": [1, 2, 3],
    "tablet": [3, 4, 5],
    "desktop": [6, 7, 8]
};

Now let’s say I have a function that I need to run that data through multiple times. Maybe I’m sending it through an API to map out a chart. In this case, I’m printing the data to a website (the DOM).

function
function printData(id, name, sessions) {
  var div = document.createElement('div');
  div.id = id;
  div.textContent = name + ' : ' + sessions;
  document.querySelector('body').appendChild(div);
}

So there’s my common code: data and a function.

var sessions = {
    "mobile": [1, 2, 3],
    "tablet": [3, 4, 5],
    "desktop": [6, 7, 8]
};

function printData(id, sessions) {
  var div = document.createElement('div');
  div.id = id;
  div.textContent = name + ' : ' + sessions;
  document.querySelector('body').appendChild(div);
}

Original code

So for my first try, I’m just going to run the data through the code manually. I create an object in a variable for the data I need to pass into the function.

// collapsing for brevity
var sessions = { ... }                   
function printData(id, name, sessions) { ... }

// Manually create objects and assign each one to a variable
var mobileData = {
    id: 'mobile-container',
    name: 'mobile',
    sessions: sessions['mobile']
};

var tabletData = {
    id: 'tablet-container',
    name: 'tablet',
    sessions: sessions['tablet']
};

var desktopData = {
    id: 'desktop-container',
    name: 'desktop',
    sessions: sessions['desktop']
};

And I invoke the function using the properties of each object.

// Manually invoke function
printData(mobileData.id, mobileData.name, mobileData.sessions);
printData(tabletData.id, tabletData.name, tabletData.sessions);
printData(desktopData.id, desktopData.name, desktopData.sessions);

Clearly, this code is very inefficient. I see a lot of repetition. I know the redundancy is bad, but I don’t necessarily know how to fix it. So here’s how we’re going to do it.

Refactoring

First, I’ll create an array that contains all the key values with Object.keys.

var sessions = { ... }                   
function printData(id, name, sessions) { ... }

var devices = Object.keys(sessions); // returns [ "mobile", "tablet" ... ]

Then I’ll make an array of objects, containing all the properties I need. I’ll do this with map().

var sessions = { ... }                   
function printData(id, name, sessions) { ... }

var devices = Object.keys(sessions);
 
var data = devices.map(function(device) {
    // returns [{ ... }, { ... }, { ... }], an array of objects
    return {
        id: device + '-container',
        name: device,
        sessions: sessions[device],
    }
});

Finally, I’ll do a forEach() loop to run the function once for each object.

data.forEach(function(device) {
    printData(device.id, device.sessions);
});

And that’s it! Here it is below.

fullCode.js
var sessions = {
    "mobile": [1, 2, 3],
    "tablet": [3, 4, 5],
    "desktop": [6, 7, 8]
};

var printData = function(id, name, sessions) {
  var div = document.createElement('div');
  div.id = id;
  div.textContent = name + ' : ' + sessions;
  document.querySelector('body').appendChild(div);
}

var devices = Object.keys(sessions); 

var data = devices.map(function(device) {
    return {
        id: device + '-container',
        name: device,
        sessions: sessions[device],
    }
});

data.forEach(function(device) {
    printData(device.id, device.name, device.sessions);
});

And here it is updated with some ES6 syntax.

fullCodeES6.js
const sessions = {
    "mobile": [1, 2, 3],
    "tablet": [3, 4, 5],
    "desktop": [6, 7, 8]
};

const printData = (id, name, sessions) => {
  var div = document.createElement('div');
  div.id = id;
  div.textContent = `${name} : ${sessions}`;
  document.querySelector('body').appendChild(div);
}

const devices = Object.keys(sessions); 

const data = devices.map(device => {
    return {
        id: `${device}-container`,
        name: device,
        sessions: sessions[device],
    }
});

data.forEach(device => {
    printData(device.id, device.name, device.sessions);
});

Now, the code may not be that much shorter now, but imagine if our data had fifty entries instead of three. Then you’d really start to see the benefit.

Note that less code or shorter code is not necessarily better code. You shouldn’t sacrifice readability and clarity for brevity.

Here is a demo of the code example above.

Note

Hi, my name is Tania Rascia. I've turned down every offer for advertisements or sponsored posts on this website. I write free resources that have helped thousands of people successfully transition into a web development career.

My committment is to no bullshit, no sponsored posts, no ads, and no paywalls. If you enjoy my content, please consider supporting what I do.

Support my work

Newsletter

New articles on web development every two weeks.

Write a response

Your email address will not be published.

All code will be displayed literally.

Discussion

  • Orderacustomessay says:

    The book “The Pragmatic Programmer is good. I read it last year, although, as my story illustrates, I am not walking the talk. But I am doing better than I used to, and that”s something. “Clean Code is also supposedly pretty good, haven”t read it. Another thing that helps is to look at good code. Actually maybe this is better than any book. My partner, Sam, is a good programmer, so all I have to do is look at the functions that he writes and try to figure out what it is that makes them more compact, readable, and understandable than mine. And when I had Sam helping me on the Sunday and Monday that I described above, one of the things he did was to clean up some of my code: break chunks of code into functional blocks and turn them into functionssimple refactoring, really quick to do. Of course I am used to doing this for any code that needs to be used more than once, but in this case it would be ten or twenty or thirty lines of code that just have to be run through in order, so why bother moving it out of the main program? The answers are: (1) it makes it much easier to see the dependencies – this block of code depends on these specific variables, and its entire purpose is to generate these other variables, (2) it gives you a function that you can test independently if you want to, (3) it reduces the cognitive burden of keeping track of what happens where in the program. Any one of these would be reason enough to do it.

  • Manuel Romero says:

    div.textContent = name + ‘ : ‘ + sessions;

    Maybe could be:

    div.textContent = `${name} : ${sessions}`;