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
Class Single Responsibility Principle is to create instance. Honor it.
Delegate method to instance.
Create stateless objects. Don't call them helpers.
Examples
Static class methods
Static attributes
Sample Code
Wrong
class DateStringHelper {
static format(date) {
return date.toString('yyyy-MM-dd'); ;
}
}
DateStringHelper.format(new Date());
Right
class DateToStringFormatter {
constructor(date){
this.date = date;
}
englishFormat() {
return this.date.toString('yyyy-MM-dd');
}
}
new DateToStringFormatter(new Date()).englishFormat()
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
Software Engineering Great Quotes
Maxi Contieri ・ Dec 28 '20
This article is part of the CodeSmell Series.
How to Find the Stinky parts of your Code
Maxi Contieri ・ May 21 '21
Last update: 2021/06/28
Top comments (4)
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).
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.
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.
If you say that
new Qwe().rty()
is more readable thanquerty()
you have weird understanding of readability :-)Ok. To YOU. You are not spreading generalized common knowledge, but YOUR opinion. That's fine.
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