or every person, then utility classes will be an anathema to you.
The Dependency Inversion Principle
Depend on abstractions, not concrete implementations
This is a simple and powerful principle that produces more testable code and better systems. If you minimize the coupling between a class and the classes that it depends upon, you produce code that can be used more flexibly, and reused more easily.
However, a utility class cannot participate in the Dependency Inversion Principle. It cannot derive from an interface, nor implement a base class. No one creates an object that can be extended with a helper class. This is the partner of the Liskov Substitution Principle, but while utility classes do not violate the LSP, they do violate the DIP.
In summary, utility classes are not proper objects; therefore, they don’t fit into object-oriented world. They were inherited from procedural programming, mostly because most were used to a functional decomposition paradigm back then.
And there are other aritcals about this topic: [Are Helper Classes Evil?][1] by Nick Malik, [Why helper, singletons and utility classes are mostly bad][2] by Simon Hart, [Avoiding Utility Classes][3] by Marshal Ward, [Kill That Util Class!][4] by Dhaval Dalal, [Helper Classes Are A Code Smell][5] by Rob Bagby. [1]: http://blogs.msdn.com/b/nickmalik/archive/2005/09/06/461404.aspx [2]: http://smart421.wordpress.com/2011/08/31/why-helper-singletons-and-utility-classes-are-mostly-bad-2/ [3]: http://www.marshallward.org/avoiding-utility-classes.html [4]: http://www.jroller.com/DhavalDalal/entry/kill_that_util_class [5]: http://www.robbagby.com/posts/helper-classes-are-a-code-smell/
Object-Oriented Alternative
Example1
Let's take NumberUtils for example:
// This is a terrible design, don't reuse
public class NumberUtils {
public static int max(int a, int b) {
return a > b ? a : b;
}
}
In an object-oriented paradigm, we should instantiate and compose objects, thus letting them manage data when and how they desire. Instead of calling supplementary static functions, we should create objects that are capable of exposing the behaviour we are seeking:
public class Max implements Number {
private final int a;
private final int b;
public Max(int x, int y) {
this.a = x;
this.b = y;
}
@Override
public int intValue() {
return this.a > this.b ? this.a : this.b;
}
}
This procedural call:
int max = NumberUtils.max(10, 5);
Will become object-oriented:
int max = new Max(10, 5).intValue();
Example2
Say, for instance, you want to read a text file, split it into lines, trim every line and then save the results in another file. This is can be done with FileUtils from Apache Commons:
void transform(File in, File out) {
Collection
src = FileUtils.readLines(in, UTF-8); Collection
dest = new ArrayList<>(src.size()); for (String line : src) { dest.add(line.trim()); } FileUtils.writeLines(out, dest, UTF-8); }
The above code may look clean; however, this is procedural programming, not object-oriented. We are manipulating data (bytes and bits) and explicitly instructing the computer from where to retrieve them and then where to put them on every single line of code. We’re defining a procedure of execution.
The OO alternative is:
void transform(File in, File out) {
Collection
src = new Trimmed( new FileLines(new UnicodeFile(in)) ); Collection
dest = new FileLines( new UnicodeFile(out) ); dest.addAll(src); }
FileLines implements Collection
and