Definition of code smell (from Wikipedia): "any symptom in the source code of a program that possibly indicates a deeper problem." In Java, static methods allow you to execute code at a "class scope" as opposed to an instance scope like member methods.
If you're making all the methods static, then all the variables outside methods should be static as well. About threading, as per my knowledge, the difference would be when you would want to synchronize your code.
Classes tend to be big to huge Since classes with static methods have nothing to do with objects, they don't know who they are, what they should do and what they should not do. The boundaries are blurred, so we just write one instruction after another. It's hard to stop until we're done with our task.
There are two kinds of common static methods:
There are a few common uses of "unsafe" statics -- for example, in the Singleton pattern -- but be aware that despite any pretty names you call them, you're just mutating global variables. Think carefully before using unsafe statics.
An object without any internal state is a suspicious thing.
Normally, objects encapsulate state and behavior. An object that only encapsulates behavior is odd. Sometimes it's an example of Lightweight or Flyweight.
Other times, it's procedural design done in an object language.
This is really only a follow up to John Millikin's great answer.
Although it can be safe to make stateless methods (which are pretty much functions) static, it can sometimes lead to coupling that is hard to modify. Consider you have a static method as such:
public class StaticClassVersionOne {
public static void doSomeFunkyThing(int arg);
}
Which you call as:
StaticClassVersionOne.doSomeFunkyThing(42);
Which is all well and good, and very convenient, until you come across a case where you have to modify the behaviour of the static method, and find that you are tightly bound to StaticClassVersionOne
. Possibly you could modify the code and it would be fine, but if there was other callers dependent on the old behaviour, they'll need to be accounted for in the body of the method. In some cases that method body can get pretty ugly or unmaintainable if it tries to balance all these behaviours. If you split out the methods you may have to modify code in several places to take account of it, or make calls to new classes.
But consider if you had created an interface to provide the method, and given it to callers, now when the behaviour has to change, a new class can be created to implement the interface, which is cleaner, more easily tested, and more maintainable, and that instead is given to the callers. In this scenario the calling classes don't need to be altered or even recompiled, and the changes are localised.
It may or it may not be a likely situation, but I think it is worth considering.
The other option is to add them as non-static methods on the originating object:
i.e., changing:
public class BarUtil {
public static Foo transform(Bar toFoo) { ... }
}
into
public class Bar {
...
public Foo transform() { ...}
}
however in many situations this isn't possible (e.g., regular class code generation from XSD/WSDL/etc), or it will make the class very long, and transformation methods can often be a real pain for complex objects and you just want them in their own separate class. So yeah, I have static methods in utility classes.
Static classes are fine as long as they're used in the right places.
Namely: Methods that are 'leaf' methods (they do not modify state, they merely transform the input somehow). Good examples of this are things like Path.Combine. These sorts of things are useful and make for terser syntax.
The problems I have with statics are numerous:
Firstly, if you have static classes, dependencies are hidden. Consider the following:
public static class ResourceLoader
{
public static void Init(string _rootPath) { ... etc. }
public static void GetResource(string _resourceName) { ... etc. }
public static void Quit() { ... etc. }
}
public static class TextureManager
{
private static Dictionary<string, Texture> m_textures;
public static Init(IEnumerable<GraphicsFormat> _formats)
{
m_textures = new Dictionary<string, Texture>();
foreach(var graphicsFormat in _formats)
{
// do something to create loading classes for all
// supported formats or some other contrived example!
}
}
public static Texture GetTexture(string _path)
{
if(m_textures.ContainsKey(_path))
return m_textures[_path];
// How do we know that ResourceLoader is valid at this point?
var texture = ResourceLoader.LoadResource(_path);
m_textures.Add(_path, texture);
return texture;
}
public static Quit() { ... cleanup code }
}
Looking at TextureManager, you cannot tell what initialisation steps must be carried out by looking at a constructor. You must delve into the class to find its dependencies and initialise things in the correct order. In this case, it needs the ResourceLoader to be initialised before running. Now scale up this dependency nightmare and you can probably guess what will happen. Imagine trying to maintain code where there is no explicit order of initialisation. Contrast this with dependency injection with instances -- in that case the code won't even compile if the dependencies are not fulfilled!
Furthermore, if you use statics that modify state, it's like a house of cards. You never know who has access to what, and the design tends to resemble a spaghetti monster.
Finally, and just as importantly, using statics ties a program to a specific implementation. Static code is the antithesis of designing for testability. Testing code that is riddled with statics is a nightmare. A static call can never be swapped for a test double (unless you use testing frameworks specifically designed to mock out static types), so a static system causes everything that uses it to be an instant integration test.
In short, statics are fine for some things and for small tools or throwaway code I wouldn't discourage their use. However, beyond that, they are a bloody nightmare for maintainability, good design and ease of testing.
Here's a good article on the problems: http://gamearchitect.net/2008/09/13/an-anatomy-of-despair-managers-and-contexts/
That seems to be a reasonable approach. The reason you don't want to use too many static classes/methods is that you end up moving away from object oriented programming and more into the realm of structured programming.
In your case where you are simply transforming A to B, say all we're doing is transforming text to go from
"hello" =>(transform)=> "<b>Hello!</b>"
Then a static method would make sense.
However, if you're invoking these static methods on an object frequently and it tends to be unique for many calls (e.g. the way you use it depends on the input), or it is part of the inherent behavior of the object, it would be wise to make it part of the object and maintaining a state of it. One way to do this would be to implement it as an interface.
class Interface{
method toHtml(){
return transformed string (e.g. "<b>Hello!</b>")
}
method toConsole(){
return transformed string (e.g. "printf Hello!")
}
}
class Object implements Interface {
mystring = "hello"
//the implementations of the interface would yield the necessary
//functionality, and it is reusable across the board since it
//is an interface so... you can make it specific to the object
method toHtml()
method toConsole()
}
Edit: One good example of great use of static methods are html helper methods in Asp.Net MVC or Ruby. They create html elements that aren't tied to the behavior of an object, and are therefore static.
Edit 2: Changed functional programming to structured programming (for some reason I got confused), props to Torsten for pointing that out.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With