Contact Us

Case: Make Names Robust to Future Changes

Writing clean, maintainable code is an art and a science---it is a challenging skill that is difficult to learn except through experience. We have collected a number of coding examples that demonstrate good coding practices.

Background

Naming is one of the most important parts of writing clean code. Vague variable names are not helpful. Inaccurate variable names are misleading!

As a codebase evolves, variable names that were once appropriate can become stale and subtly inaccurate. Good coders will update variable names to keep them precise and correct as the codebase evolves. Updating the names frequently can be a headache, especially if the “name” is used in several different entities through out a codebase.

Try and make names as “future proof” as possible. To do this, try and consider how the code might evolve in the future, and see if you can think of a variable name that will continue to be precise even as the codebase changes. Of course don’t ever sacrifice precision or clarity for the sake of future proofing!

Problem

The following snippet of code glues together a component, NodeDescription, to a global store of lazily-loaded HTML snippets, loadedNodeRefs. It also provides a function that allows the component to trigger loading a new snippet using the URL for the snippet.

These HTML snippets come from sections of external webpages that may be referenced in the NodeDescription. In some cases the references refer to entire external web pages. These external references are listed in a list of sections inside NodeDescription.

  import React from 'react'
  import { connect } from 'react-redux'

  import NodeDescription from 'components/NodeDescription'

  import { loadSectionReference } from 'actions'


  const mapStateToProps = (state, props) => {
      return {
          nodeDetails: props.node,
          loadedNodeRefs: state.loadedNodeRefs,
      }
  }


  const mapDispatchToProps = (dispatch) => {
      return {
          loadRef: sectionRef => dispatch(loadSectionReference(sectionRef))
      }
  }


  export default connect(mapStateToProps, mapDispatchToProps)(NodeDescription)

How would you improve the names in this code base to be more precise, consistent, and “future proof”?

Solution

In this snippet of code, the same “concept” is referred to in several different ways:

  • loadSectionReference
  • loadedNodeRefs
  • loadRef

Furthermore, the name sectionRef is misleading because it is actually referring to the URL for a given reference, and not the reference itself!

The abbreviation “ref” for “reference” is not necessary. We write code once, and read it many times, so it is usually good to optimize for readability. With really long names, standard abbreviations can be powerful, but in this case it is clearly not worth saving the extra six characters.

Two different prefixes are being used to refer to the same concept–nodeReferences and sectionReferences. Which is appropriate? It turns out that neither is.

These URLs usually point to a section of a page but they may refer to an entire page, thus the prefix “section” is inaccurate and should not be used.

Individual nodes refer to these URLs, however given that this is a global store, it seems feasible that the references will be referred to by other entities. Thus, although at the moment nodeReferences may be accurate, it would become inaccurate once another non-node entity starts using the references.

We could simply use references, however this is pretty vague, and does not feel particularly “future proof” either–what if we start keeping track of internal references between different nodes in our site?

After thinking through these naming issues, we arrive at:

  import React from 'react'
  import { connect } from 'react-redux'

  import NodeDescription from 'components/NodeDescription'

  import { loadExternalReference } from 'actions'


  const mapStateToProps = (state, props) => {
      return {
          node: props.node,
          externalReferences: state.externalReferences,
      }
  }


  const mapDispatchToProps = (dispatch) => {
      return {
          loadExternalReference: url => dispatch(loadExternalReference(url))
      }
  }


  export default connect(mapStateToProps, mapDispatchToProps)(NodeDescription)

The use of the name externalReferences is more precise and future proof.

We change the misleading name sectionRef to url. As a rule of thumb, the smaller the scope of a variable, the less precise its name needs to be to avoid confusion. In this case, it is apparent from the context that url refers to the external section’s url.

We dropped the prefix “loaded” from the global store’s name—it is implicit that they would be loaded because they exist, hence is not necessary to mention that they have been loaded because they wouldn’t exist if they hadn’t been!

Finally, we change nodeDetails to simply node–“details” is vague and doesn’t add any useful information. Furthermore, if node was sufficient at a higher level of abstraction, then it seems even more sufficient as we drop down into a lower level component.