Auld Lang Refactoring

New Year’s is filled with resolutions to work out, diet, exercise, and get more organized. This year, I’d like to get my knee in order so I can run again, continue on my vegan endeavors, and keep our apartment decluttered now that we have an infant.

Tidying up got me thinking about code and refactoring. Frameworks like React and Rails offer structures to encourage code to stay clean and tight with their uses of modules and components. But sometimes when writing JavaScript from scratch, refactoring and keeping clean code can quickly get out of hand. I wanted to create a before and after example using plain JavaScript as an exercise in refactoring.

The program is simple: use an input to add an item to an array and show the results on the page.

Here is the “before” starter code:

HTML:

 <div class="container">
  <h1>Add Item to Array</h1>
  <form id="form">
    <input type="text" id="item">
    <input type="submit">
  </form>

  <pre id="output">Ouput here...</pre>
</div>

JS:

let list = []
let form = document.getElementById('form')
let output = document.getElementById('output')

form.addEventListener('submit', (e) => {
  e.preventDefault()
  let item = document.getElementById('item')
  list.push(item.value)
  output.innerHTML = list
  item.value = ''
})

First I created an empty array named list. I grabbed the form and output using getElementById() then setup an event listener on the form. When submit is detected, I grabbed the input id (item) and pushed the value onto the list array. Once the list was updated, I populated the pre tag with the array. Finally, I cleared the input.

The code works! But much like the Cleveland Browns, just because they have uniforms, a team name, and a quarterback, doesn’t mean the organization is streamlined and firing on all cylinders.

The problem with our code is that we have three variables floating around in the global scope, which could have implications in the future if we add new variables. All of our functionality, adding the item to the list, clearing the input, and outputting the array, is packed inside our event listener, making it confusing to understand and hard to read. And if we want to add more features in the future, we’re going to have lots of cluttered code to sift through.

I learned to always write the code I wish I had, then work backwards. So in this case, I’d like to have a function to call like this to start things off:

const formListener = (form) => {}

formListener(form)

This function nicely wraps our code so we don’t have any stray variables outside roaming around like a lost Browns receiver running the wrong route.

I added our list array inside and created our event listener on our form:

const formListener = (form) => {
  let list = []
  form.addEventListener('submit', (e) => {
    e.preventDefault()
  })
}

formListener(form)

I wanted my event listener to only deal with grabbing the input value and clearing:

const formListener = (form) => {
  let list = []
  form.addEventListener('submit', (e) => {
    e.preventDefault()
    let item = document.getElementById('item')
    item.value = ''
  })
}

formListener(form)

Next, I wanted a function to add our input value to our array. Something like addItem():

const addItem = (item, list) => list.push(item)

const formListener = (form) => {
  let list = []
  form.addEventListener('submit', (e) => {
    e.preventDefault()
    let item = document.getElementById('item')
    addItem(item.value, list)
    item.value = ''
  })
}

formListener(form)

Finally, I created another function to show the array on the page, show(), and then called our formListener() function with our form:

const addItem = (item, list) => list.push(item)
const show = (list) => document.getElementById('output').innerHTML = list

const formListener = (form) => {
  let list = []
  form.addEventListener('submit', (e) => {
    e.preventDefault()
    let item = document.getElementById('item')
    addItem(item.value, list)
    show(list)
    item.value = ''
  })
}

formListener(document.getElementById('form'))

While this may be a silly example, I hope it sheds some light on the thought process that goes into refactoring, even if the un-refactored code is simple. Refactoring is a lot like writing — you write a horrible first draft, then go back and rewrite, rewrite, and rewrite until it’s clean and streamlined. Unless you’re the Browns, of course.

See the Pen LeyJgp by Daniel Warren (@danielwarren) on CodePen.

<-- Back to blog list