Code Smell 22 - Helpers

Maxi Contieri - Nov 12 '20 - - Dev Community

Do you need help? Who are you gonna call?

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

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';
  }
}
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

Right

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();
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .