DEV Community

Cover image for 
One thing you must keep in mind when refactoring code.
Jack Shen
Jack Shen

Posted on

One thing you must keep in mind when refactoring code.

Recently, I found myself building a JavaScript-based animation within a front-end project I was working on. Here's a simplified version of the code:

const animate = () => {
  // some sort of DOM update here
  requestAnimationFrame(animate);
}

animate();

After a short while, I decided I wanted an FPS counter -- just something presentational that shows inside the browser. My first thought was to write a similar function, but for updating an FPS value shown on the page:

const ONE_SECOND = 1000;
let fps = 0;

const getFPS = startTime => {
  window.requestAnimationFrame(() => {
    const currentTime = performance.now();
    if (currentTime - startTime < ONE_SECOND) {
      fps++;
      getFPS(startTime);
    } else {
      fpsDisplay.innerText = `${fps} FPS`;
      fps = 0;
      getFPS(currentTime);
    }
  });
};

getFPS(performance.now());

There is nothing seriously wrong with this approach. It updates properly and produces the correct value.

However, I quickly realised this solution was far from ideal: a second use of requestAnimationFrame would make no sense if my project had animation-heavy code.

In fact, it was superfluous given that animate() already included a requestAnimationFrame call. I could achieve the same functionality by refactoring my getFPS() function so that it shared the same call:

const ONE_SECOND = 1000;
let fps = 0;

const animate = () => {
  // some sort of DOM update here
  fps++;
  requestAnimationFrame(animate);
}

const  getFPS = () => {
  setInterval(() => {
    fpsDisplay.innerText = `${fps} FPS`;
    fps = 0;
  }, ONE_SECOND);
};

animate();
getFPS();

This is what's called colocating. The principle of colocation is simple: group like code with one another.

A good analogy for the above example is measuring the speed of a car. It would be an absurd waste of time and money to purchase a second car, match its speed with the first, and use a radar gun on the second. In comparison, the colocated code would be like installing a speedometer in the first car.

Colocating, in addition to decreasing code length and increasing readability, boasts significant computational savings. By refactoring the bulk of getFPS() inside of animate(), only a single instance of requestAnimationFrame() was needed.

There are a myriad of benefits to colocation, including but not limited to easier readability and maintainability, better predictability, improved performance, and closer adherence to DRY principles.

Top comments (0)