Each Private Static Method Is a Candidate for a New Class
Do you have private static methods that help you break your algorithms down into smaller parts? I do. Every time I write a new method, I realize that it can be a new class instead. Of course, I don’t make classes out of all of them, but that has to be the goal. Private static methods are not reusable, while classes are—that is the main difference between them, and it is crucial.
Here is an example of a simple class:
class Token { private String key; private String secret; String encoded() { return "key=" + URLEncoder.encode(key, "UTF-8") + "&secret=" + URLEncoder.encode(secret, "UTF-8"); } }
There is an obvious code duplication, right? The easiest way to resolve it is to introduce a private static method:
class Token { private String key; private String secret; String encoded() { return "key=" + Token.encoded(key) + "&secret=" + Token.encoded(secret); } private static String encoded(String text) { return URLEncoder.encode(text, "UTF-8"); } }
Looks much better now. But what will happen if we have another class that needs the exact same functionality? We will have to copy and paste this private static method encoded()
into it, right?
A better alternative would be to introduce a new class Encoded
that implements the functionality we want to share:
class Encoded { private final String raw; @Override public String toString() { return URLEncoder.encode(this.raw, "UTF-8"); } }
And then:
class Token { private String key; private String secret; String encoded() { return "key=" + new Encoded(key) + "&secret=" + new Encoded(secret); } }
Now this functionality is 1) reusable, and 2) testable. We can easily use this class Encoded
in many other places, and we can create a unit test for it. We were not able to do that with the private static method before.
See the point? The rule of thumb I’ve already figured for myself is that each private static method is a perfect candidate for a new class. That’s why we don’t have them at all in EO.
By the way, public static methods are a different story. They are also evil, but for different reasons.
You may also find these related posts interesting: Object Behavior Must Not Be Configurable; Can Objects Be Friends?; There Can Be Only One Primary Constructor;
Reference: | Each Private Static Method Is a Candidate for a New Class from our JCG partner Yegor Bugayenko at the About Programming blog. |
So what if we create new class (for example Utils) that will hold public static methods (in this case it will be encode), so we will be able to call it wherever we want and we do not have to create new instance of class every time. In example above we have to create new instance of Encode class every time there is a need for encoding something, isn’t it memory leak?
The main problem is that the logic is happend in the toString method, and every call on that call the encode method again and again. toString should be used to give back the object inner state. The class name is Encoded so the encode should be called in constructor, and hold the encoded value, with this, the class can be immutable. Another solution is that you create an Encoder class, and make a method encode(String raw), so you can reuse the class. To Damian, its not memory leak, but use more memory, but static is not pure OO. Anyway my… Read more »
We can go further – all methods witch not modify object state could be extract to separate classes – it is make any sense?