DEV Community

Cover image for Code Smell 18 — Static Functions
Maxi Contieri
Maxi Contieri

Posted on • Updated on • Originally published at maximilianocontieri.com

Code Smell 18 — Static Functions

Yet another global access coupled with laziness.

TL;DR: Don't use static functions. They are global and utilities. Talk to objects instead.

Problems

  • Coupling

  • Testability

  • Protocol Overloading

  • Cohesion

Solutions

Examples

  • Static class methods

  • Static attributes

Sample Code

Wrong

class DateStringHelper {
   static format(date) {
     return date.toString('yyyy-MM-dd'); ;    
  }
}


DateStringHelper.format(new Date());
Enter fullscreen mode Exit fullscreen mode

Right

class DateToStringFormatter {
   constructor(date){
      this.date = date;
   }

   englishFormat() {
     return this.date.toString('yyyy-MM-dd');    
  } 
}

new DateToStringFormatter(new Date()).englishFormat()


Enter fullscreen mode Exit fullscreen mode

Detection

We can enforce a policy to avoid static methods (all class methods but constructors).

Tags

  • Global

  • Libraries

Conclusion

Class are globals disguised. Polluting their protocol with "library methods" breaks cohesion and generates coupling. We should extract static with refactorings.

In most languages we cannot manipulate classes and use them polymorphically, so we can't mock them or plug them on tests.

Therefore, we have a global reference too difficult too decouple.

Relations

More info

Credits

Photo by Alex Azabache on Unsplash


There is no programming problem that can't be solved with one more level of indirection.

John McCarthy


This article is part of the CodeSmell Series.

Last update: 2021/06/28

Discussion (4)

Collapse
mt3o_23 profile image
Teodor Kulej

Why exactly is this a "code smell"? Typescript linter in WebStorm suggests moving out "looks like static" methods to independent functions.

Your "wrong code" could be a standalone function, at least in javascript. Not in java as it requires everything to be in a class. And, regarding java, creating an object on the stack, just to launch a method, and then destroy that object - it's a waste of resources. It could be inlined by the compiler, it introduces unnecessary mental overload on the developer (there is nothing to do in the constructor aside except for copying the state, and the state is evil as we all know).

Collapse
mcsee profile image
Maxi Contieri Author

INMH, Typescript linter is wrong.

Code must allways be in classes. We are doing POO here . So if the responsability is not in a class, who must carry it on?

I love structured paradigm. There you can put utility functions in a coupled library of uncohesive crap. But this is not true for real OOP.

Regarding waste of resources. I am not a premature optimizer. Unless we are doing mission critical code, I will always favor readability over performance.

I don't see why state is evil.

I think we are programming under different paradigms, and I am perfectly fine with it.
To me it is still a code smell.

Collapse
mt3o_23 profile image
Teodor Kulej

Why does the code need to be in a class? Who said so? There are languages with no classes, and they are perfectly fine. You are into DDD, you should have taken it into consideration.

I will always favor readability over performance.

If you say that new Qwe().rty() is more readable than querty() you have weird understanding of readability :-)

To me it is still a code smell.

Ok. To YOU. You are not spreading generalized common knowledge, but YOUR opinion. That's fine.

Thread Thread
mcsee profile image
Maxi Contieri Author

I am fine with prototype based languages.

neither Qwe().rty(), nor querty() are readable to me.

I am spreading my opinions :)

We agree to disagree