loading...
Cover image for Utils files are not so useful and helper classes are not so helpful!

Utils files are not so useful and helper classes are not so helpful!

dvddpl profile image Davide de Paolis ・3 min read

We have a drawer in our kitchen where my wife and I keep all sorts of things: old knives or odd forks, rubber bands, matches, garlic press, old corks, pins, scissors, half packs of chewing gum, scotch tape, partly used birthday candles, coasters, watch batteries, toothpicks and so on.

Basically, everything that lies around and could somehow/somewhen be of some use, but does not really belong anywhere end up in that drawer.
We have of course a box with candles, a drawer with cables and old tech parts, a drawer of tools and many cupboards for kitchen utensils, but all those little things would not fit in there because they are smaller orphans single items that we could not group with anything else that deserves a special container or we simply did not have time to sort and organize it.

Ehi dear, while vacuuming I found this tiny bolt under the couch - do you know from where it fell?
I don't know, just put it in the drawer in the kitchen so we won't lose it.

This is how it normally starts.

Of course if some weeks after we find out that a tiny bolt is missing from our office chair there are few options:
1) we don't remember at all that we found a bolt under the couch and we put that in the drawer
2) we remember but we cannot find it there unless we completely empty the drawer on the table and sort all the mess we have there

too much junk in there

Something that usually happens is also that once a year we try to fix that mess and spend a couple of hours going through all the content of that drawer.

Why is a bolt even in here?!? and it's thrown away.
Do we even need 10 different coasters that we collected during over many years of pub crawls?
Is this watch battery full or empty? And most of all, do we even have watches that require these?

Can you start seeing the connection with programming now?

When we are coding, we often end up in situations where we write a small function that could be used in other places. Where do we put it?

It is not generic enough, or complex enough, or tested enough, to deserve an own class or even its own npm module. We just wrote that to remove some logic from a bigger function (and just eventually to avoid some code duplication if we happen to reuse it elsewhere).

It can be phone-number formatter, a wrapper for Http-request adding custom headers, a small method that prettifies error messages. I notice that trying to write smaller and smaller functional methods, I end up with more methods that I am not so sure where to put.

Let's put them into a shared.js
Or better call it helpers.js
Mmmh, but the HTTP wrapper is not really just helping, it's a needed functionality for every request, let's put that in commons.js
Naah, than rather http-utils.js

The temptation is very big. But try to resist that.

It will spread and in a few weeks, it will contain even more unrelated functions and become bloated. Or, especially if in your project work more than 3 people, you will end up with many commons / shared / helper files. And many of those will contain similar functions.

Yes, there will still be duplication, because when you need to write a small function in a big project you won't be aware of all the small functions written one year ago from a colleague in a completely unrelated part of the application.
And when you look at the file, you will always be wondering, as when I am staring at our junk drawer. What the heck is in there? How am I supposed to find stuff there?

too much junk in there

Yes, naming things is hard and so is organize them and try to group them together.
Try to name your packages/files after what they provide and not what they contain (because if they contain a miscellaneaus sorts of things they might end up named misc.js which is not telling much at all..) and learn to live with the fact that some duplication is unavoidable, and that some duplication is better than the wrong abstraction.

Posted on May 15 '19 by:

dvddpl profile

Davide de Paolis

@dvddpl

Sport addicted, productivity obsessed, avid learner, travel enthusiast, expat, 2 kids. πŸ‚βœˆπŸšžπŸŒπŸ“·πŸ–₯πŸ€˜πŸ‘¨β€πŸ‘©β€πŸ‘¦β€πŸ‘¦πŸš€ (Opinions are my own)

Discussion

markdown guide
 

I have a theory that all stuff unrelated to current should be in the external library because chances are I will need them for other stuff.

Saying that I've never forced myself to create this library yet.

Insightful article, indeed.

 

What about stuff that is so specific to your project that it can't be exported as a library on it's own? Most of the helpers on my projects are very small and contain only few methods - I can't see how you would export such helpers as libraries and keep their usability.

 

It depends.
In my recent project, I keep in my utils only things that are not specific for given application, well about from 80% to be honest, so I would have no problem to separate them and put them to the outer library because I am trying to keep project-specific stuff in the other files.

Basically, I consider the utils module or package as project independent stuff.

But of course, there are rules:

  1. my utils do not (or should not) import stuff from the project,
  2. I am using small objects, ideally data types and functions,
  3. importing only standard library and framework

As for project-specific stuff, I am trying to build it on my utils; the utils provide the general thick solution whereas project-specific stuff thin concrete implementation to tackle the problem.

My workflow is ideally:

  • I write specific code,
  • extract the pattern, if there is any,
  • this abstraction comes to utils,
  • and for the project, I import and build upon this abstraction.

Of course, I am far from perfect but sometimes I do even follow my own advice :)

 

Yes, yes, yes!
Thx for writing this.