maestros

What's in a Utils file

27 January, 2020 • 5 min read

I can easily recall myself in the past struggling where to put that helper function which serves a general purpose that might be needed in various places within the app.

I am talking about that function that was neither component-specific nor too generic to put in a separate module and include it as a dependency in the project.

Most of the time that I came across to this where-to-put-that-helper-function problem I ended up like this...

- Aha Let's put it in a utils file and then import it from there!

But let me tell you my story about why I started using utils and why I'm not anymore...

The "Don't Repeat Yourself" day

Back in the days, when I was a junior to mid-level developer, I had the chance to be part of a highly-skilled engineering team. There was that period where every day was like a new lesson for me. I was trying to pay attention to every single thing they were saying so that I could get better as a software engineer.

I still remember that day where a team member said to another during a code review:

If you have to repeat a block of code, then it should be a function. Don't repeat yourself.

I bet if you're a senior engineer this is a fact. For me, it was a crucial moment that meant to change the way I code.

Eventually since that moment, whenever I was detecting repetitive patterns of code I used to extract them as reusable functions. Those functions were usually going into a file whose name was either utils or helpers.

Things I used to put into Utils

Allow me to straighten things up.

By saying that I used to extract reusable blocks of code, I don't really mean all of them.

What I was trying to accomplish was to end up with smaller if statements or hide the complexity of a block which for instance was trying to extract some value from the query params of a URL.

In fact, one of my favorite was this one:

// utils.js
export const isNotEmptyArray = (value) => {
  return Array.isArray(value) && value.length > 0;
}

So instead of doing this:

// userForm.js
if (Array.isArray(user.roles) && user.roles.length > 0) {
  saveUserRoles(user.roles);
}

I liked this version:

// userForm.js
import { isNotEmptyArray } from 'utils';

if (isNotEmptyArray(user.roles)) {
  saveUserRoles(user.roles);
}

That's just an example of what a utility function was to me.

In general, whenever I wanted to eliminate a repetitive validation or calculation, I liked to introduce a new entry into the utils file. That was my way of reducing noisy code blocks.

As it turned out I changed my mind

Over the years, evolving into a senior engineer I started deviating from the utils practice.

There were two main reasons why this happened.

Reason #1

Most of the times they felt more of a comfort approach rather than a proper solution.

As I already mentioned at the beginning of this post, there were moments when I was struggling where was the most suitable place to put a function that was meant to be used from other components in the project too.

It didn't feel right anymore to create a utils.js file and throw everything in there without hard feelings. It was my responsibility to structure the project in a way so that it would make sense of how common logic could be shared across different components.

There was that web application we had to develop and the requirements were that users should have the option to export any table view in CSV format.

Then I realized that instead of having the exportToCsv function in a utilities collection and import it multiple times I could create an exportButton component and use it accordingly. In that way, I was able to implement the export functionality once without having to use it as a utility.

What I'm trying to say is that although the utility approach for the export logic was a working solution I found it more reasonable to create a dedicated component for that.

Reason #2

Another reason why I'm not still a fan of the utils is that they seem too generic.

Either I was working in a team environment or on my own, every time I came across to a utils.js -or something like that- it was a real headache. I had to guess what's in there.

Especially if I hadn't touched a codebase for a long time, it was hard to scan all of the utility collection files to find if there's any implementation that fits my needs or not.

The way I see it is so much better to have a dedicated file per context such as validationService.js which is way more prominent that it hosts handy validation stuff like checks for email validity, non-empty arrays and things like that.

Are Utils good or bad practice after all ?

Well, the inspiration for this article came up from this Stack Overflow question where a user asked whether a Utils file is good practice or not.

It wasn't the question itself that motivated me but the fact that Stack Overflow closed it.

By the time I'm writing this article, there is a disclaimer on top of that question explaining that it is an opinion-based one and no longer accepts answers from users.

I liked the idea of telling my own story about this topic and share it with you.

To be honest, I'm not sure whether Utils is a good practice or not. It depends. If I had to choose I'd probably go with a hybrid answer saying that I try to avoid them whenever possible for clarity's sake.

If I were to introduce a utility function in a project now I'd try to do it in a more clear way. For instance, I would have placed the aforementioned isNotEmptyArray method in a helpers/array.js rather than in a utils.js file which could contain anything.

My Conclusion

It's up to us whether and how to use utils, helpers and things like that but try to be as specific as it gets to ensure that the codebase stays discoverable reducing the possibilities of duplicate code to be introduced.

It's very important to make a good project scaffolding from the beginning.

It's something we find it in our way as the codebase scales up.