Skip to main content

Command Palette

Search for a command to run...

Code Smell 22 - Helpers

Updated
2 min read
Code Smell 22 - Helpers
M

I’m a senior software engineer loving clean code, and declarative designs. S.O.L.I.D. and agile methodologies fan.

Do you need help? Who are you gonna call?

TL;DR: Helpers don't help. They are a non-cohesive bunch of messy subroutines.

Problems

  • Readability

  • The Least surprise principle

  • Bijection Fault

  • Static methods

Solutions

  1. Find a suitable name

  2. If the helper is a library, break all the services as different methods.

  3. Methods should always be fulfilled by objects. Static methods are another code smell.

  4. Avoid extracting the helpers to Anonymous Functions.

Sample Code

Wrong

export default class UserHelpers {
  static getFullName(user) {
    return `${user.firstName} ${user.lastName}`;
  }

  static getCategory(userPoints) {
    return userPoints > 70 ? 'A' : 'B';
  }
}

Notice static methods.

import UserHelpers from './UserHelpers';

const alice = {
  firstName: 'Alice',
  lastName: 'Gray',
  points: 78,
};

const fullName = UserHelpers.getFullName(alice);
const category = UserHelpers.getCategory(alice);
class UserScore {  
  //This is anemic class and should have better protocol

  constructor(name, lastname, points) {
    this._name = name;
    this._lastname = lastname;
    this._points = points;
  }
  name(){
    return this._name;
  }
  lastname(){
    return this._lastname;
  }
  points(){
    return this._points;
  }
}

class FullNameFormatter {
  constructor(userscore) { 
    this._userscore = userscore;

 }
  fullname() {
    return `${this._userscore.name()} ${this._userscore.lastname()}`;
  }
}

class CategoryCalculator{
  constructor(userscore1){ 
     this._userscore = userscore1;
 }
  display() {
    return this._userscore.points() > 70 ? 'A' : 'B';
  }
}


let alice = new UserScore('Alice', 'Gray', 78);

const fullName = new FullNameFormatter(alice).fullname();
const category = new CategoryCalculator(alice).display();

or we can make the former Helper stateless for reuse...

class UserScore {  
  //This is anemic class and should have better protocol

  constructor(name, lastname, points) {
    this._name = name;
    this._lastname = lastname;
    this._points = points;
  }
  name(){
    return this._name;
  }
  lastname(){
    return this._lastname;
  }
  points(){
    return this._points;
  }
}

class FullNameFormatter {      
  fullname(userscore) {
    return `${userscore.name()} ${userscore.lastname()}`;
  }
}

class CategoryCalculator{
  display(userscore) {
    return userscore.points() > 70 ? 'A' : 'B';
  }
}  

let alice = new UserScore('Alice', 'Gray', 78);

const fullName = new FullNameFormatter().fullname(alice);
const category = new CategoryCalculator().display(alice);

Detection

  • Code naming standards should forbid classes with this name on them.

Tags

  • Namings

Conclusion

This is a well established cultural name and a legacy habit from structured programming.

Most developers are reluctant to let old habits go.

We must be aware of the damage this kind of names are bringing us.

Relations

Also known as

  • Utils

More Info


This article is part of the CodeSmell Series.

Last update: 2021/07/04

Y

Great article! a few small typos:

-the function getCategory() gets the user's score, but in its usage, you're passing the entire user object.

  • In the right example, the naming function gets userscore as the paramer, while it should (for the best of my understanding) be user.

  • Same goes for the score that in the right approach accepts userscore1 as parameter (which for me also feels a bit like a code smell as there is only 1 parameter)

S

Hi, just stumbled across this post. A question came to mind after I read this post.

Why not just single functions, instead of creating new instances?

1
M

Hy Sy Hung Doan. Thanks for asking.

That would be another smell

Single functions are harder to unit test, to read, to reuse and to compose. They may be the first option, but once system gets serious they should be reified

S

Hi Maxi Contieri, Thanks for the prompt response. However, I am still on the fence. In my current project (React & Redux), we exclusively use (anonymous) functions as they are small and writing unit tests are just a breeze. I just feel like they've been convenient enough.

The code is well maintained from time to time, but no one talked about switching to use Class helpers.

I doubt if it's just a matter of preference or the scope of the projects. Mind if I ask for some more examples for the Problems you mentioned in the Code-smell-21? I'd be very glad to have a better view and understanding.

M

hi Sy Hung Doan

Some quick questions

  • How many functions are?

  • How large is the team?

  • How do you unit test it?

  • Do you have good coding names?

Can you embed an example?

D

From all the beasts, helpers and utils are the most uncouth.

2

Code Smells

Part 1 of 50

In this series, we will see several symptoms and situations that make us doubt the quality of our developments. We will present possible solutions. Most are just clues. They are no hard rules.