Advertisements
Posted by: jsonmez | January 29, 2010

Static Methods will Shock You

I’ll be frank.  I don’t like static methods.  They make me cringe.  In the universe of OO static methods are anti-matter.

They don’t have to be bad, but they are dangerous, because they are used incorrectly.

When static methods can be good

There are only two situations when static methods or variables are being used, which is not an abomination.

  1. Declaring a true global constant, not a global variable.  A global constant.  Example: Math.PI.  This is a fair shorthand for really saying that there is one instance of the universe, and that universe singleton contains a mathematical concept singleton in which there is a property PI which does not change. This concept seems strange to us, because we are used to not thinking about PI in the context of object oriented responsibility.  It would become more obvious if we were designing some strange game where there were alternate universes with different mathematical concepts and constants.
  2. Object creation.  Static methods are a valuable and valid method of object creation.  Overloaded constructors that take different arguments are not very clear and are often made clearer by replacing them with a static constructor.

public void BlogEntry(string title, string contents);

public void BlogEntry(string fileName);

is made much more clear when written as

public static BlogEntry FromTitleAndContents(string title, string contents);
public static BlogEntry FromFile(string file);

it becomes really clear in the usage

BlogEntry newEntry = new BlogEntry("Hello World", "I like to write programs");
BlogEntry newEntry = new BlogEntry("helloworld.xml");
// vs.
BlogEntry newEntry = BlogEntry.FromTitleAndContents("Hello World", "I like to write programs");
BlogEntry newEntry = BlogEntry.FromFile("helloworld.xml");

When static methods are bad

Aside from those two uses.  In my opinion, any other use is an abomination.  (I suppose I let C# extension methods slide here, because they are so useful under the right conditions, but I reserve the right to make judgement on a future date.)

Static methods usually indicate a method that doesn’t know where it belongs.  It is sitting out there trying to belong to the class it is on, but it doesn’t really belong, because it doesn’t use the internal state of the class.  When we look at our classes from the Single Responsibility Principle (SRP) viewpoint, a static method is usually a violation because it tends to have a responsibility that is not the same of the class it is attached on.

One way to think about static methods is as global procedures.  Essentially a static method can be called anywhere from anywhere.  It just pretends to be part of a class, when really the class is only used as a “tag”, which organizes the method by some logical division.  I look at static methods in these terms, because creating global procedures is the exact opposite of object oriented design.

Another major problem with static methods is the testability.  Testability is a big deal when building software.  Static methods are notoriously difficult to test, especially when they create new instances of concrete classes.  If you have ever worked in legacy code and tried to write a unit test for a static method, you know my pain.

Static methods also are not polymorphic.  If you create a static method on a class, there is no overriding that behavior.  You are stuck with a hard coded reference to that implementation.

Finally, static methods increase the complexity of an application.  The more static methods there are, the more a programmer working in the application has to know about.  When instance methods are used in a class, having an instance of that object will allow a programmer to determine all the actions that can be taken.  When static methods are used the programmer has to know about the secret methods that may not even be on the object he is working with, but manipulate that object.  Let’s look at one common example:  Date and DateUtilities.

In more than one application I have worked on, Date and DateUtilities existed.  Date existed to provide an implementation of date and time, and DateUtilities existed to manipulate the date and do things like figure out the first day of the month, or determine holidays, or see if two dates overlap.  I don’t know how many times I would try to write a method to do one of the things DateUtilities already did, because I didn’t know to look for a static class called DateUtilities with static methods that did what I wanted.  As a programmer, I have to remember to always check all the methods in DateUtilities to see if there is one that does what I want.  This can be a large amount of overhead when you are working in a large application, with many static methods hanging around in helper classes.  Perhaps I am spilling over into another problem here, but the point is that it is much more difficult to remember what utility methods exist floating out there than it is to use a method on a class that the functionality really belongs to.  (Side note here: C# extension methods kind of solve this problem, by allowing you to type “.” and see the static methods that can operate on that class).

Final words

So just remember when you create a static method to think about it carefully.  I am not advocating never using them.  I am advocating having a really good reason and checking first to see if the static method really belongs to another class where it can use state information.

Advertisements

Responses

  1. Hey man, I just heard about your site from the Stackoverflow podcast. Kewl tattoo!

    • Thanks! It is actually a Henna tattoo from on vacation in Hawaii. 🙂

  2. The dark blue border colors make these posts virtually unreadable!

    • Hmm, I am not sure what you mean there. I am not seeing anything that is hard to read. What browser are you using? I am looking at the page through Chrome and IE.

      • Not sure what was going on, but on another machine – Windows7-64 IE8 – the text ran all the way from the left edge of the browser window to the right. ie, over the borders. So the black text on the indigo panels was virtually unreadable. Interestingly, on another PC – Windows7-32 IE8 – it works as you intended, with a white central panel. I’ll reboot the other machine tomorrow and see if it is still misaligned.

  3. How do you feel about System.Math? And about System.IO.Path, File and Directory?

    • Good questions.

      System.Math: PI and E meet my requirements of being true global constants. Those values are never going to change, the context for them in almost any application we would build would be universal.

      As far as the other methods in Math (and even PI and E to some degree), they are not discoverable by being in System.Math. They are OK as static methods, because they are truly functions, which do not touch other components of the system. They just do their thing and don’t have dependencies. They are also part of the base framework, which makes them less of a problem to be static.

      But, I would still rather see a syntax like “32.Math.Cos(3)” which would be extension methods+ a grouping to make it so that I can discover the Math functions available that operate on an integer. This creates a cohesion to the data the static methods operate on, which makes them less “global”.

      For System.IO.Path, File and Directory: I would prefer to see those as concrete classes. There really is not a need for them to be static. For example, lets say these classes were to be concrete and implement and interface. Then in your code, you could mock out the interface calls and not have to try to unit test classes that would have to write to the file system.

  4. Do you plan on passing judgment on Extension Methods anytime soon? Our developers got in a argument about helper classes today and one developer is certain that extension methods are better. However, I think most of us agree that they are another form of helper classes.

    • Good question. I have been meaning to follow up with a post on extension methods. Perhaps I will do one this week.

  5. […] Part of the problem of utility methods is that they are not self-discoverable.  I’ve talked about before how DateUtilities like classes can get overlooked if you don’t know the utility class is […]

  6. […] the step-wise approach, you are actually getting rid of the bad and evil static methods.  When you wrap and delegate, you are still leaving them there, just hiding them behind a […]

  7. […] I’m not a big fan of static methods but in certain cases they make sense.  The alternative is to have all of this code sprinkled throughout your code base. […]

  8. […] Stop… take a breath, think about why you think static methods are bad, because I probably agree with you. […]

  9. […] a post with a different device theme, the pun, John Sonmez says: I don’t like static methods. They make me cringe. In the universe of […]

  10. […] Static Methods will Shock You: When static methods can be good […]

  11. Thanks for the post, was searching to see when static methods are useful and your post was a good summary. Keep up the blogging, helping peeps even two years after the original post!

  12. […] language like C# there’s seldom a need for a static class, and there are compelling reasons not to use them. They have their uses, but in my experience you should favor class instances over static classes […]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: