128

I submitted an application I wrote to some other architects for code review. One of them almost immediately wrote me back and said "Don't use static. You can't write automated tests with static classes and methods. static is to be avoided."

I checked and fully 1/4 of my classes are marked static. I use static when I am not going to create an instance of a class because the class is a single global class used throughout the code.

He went on to mention something involving mocking, IOC/DI techniques that can't be used with static code. He says it is unfortunate when 3rd party libraries are static because of their un-testability.

Is this other architect correct?

update: here is an example:

APIManager - this class keeps dictionaries of 3rd party APIs I am calling along with the next allowed time. It enforces API usage limits that a lot of 3rd parties have in their terms of service. I use it anywhere I am calling a 3rd party service by calling Thread.Sleep(APIManager.GetWait("ProviderXYZ")); before making the call. Everything in here is thread safe and it works great with the TPL in C#.

16
  • 49
    static is fine; static fields need to be treated very carefully Commented Aug 13, 2012 at 22:00
  • 3
    @Артём fields are class-level variables; static fields are class-level variables that are per-type rather than per-instance Commented Aug 13, 2012 at 22:03
  • 3
    That particular objection is bit too general for me. In most cases you wouldn't mocj the static class, you'd mock the arguments. Static field where it was an aggregate class which needed mocking, then yes.
    – Tony Hopkinson
    Commented Aug 13, 2012 at 22:12
  • 8
    Clearly your colleagues have a serious condition - an acute systemic OOPus erythematosus. They need a treatment ASAP!
    – SK-logic
    Commented Aug 17, 2012 at 7:31
  • 6
    There's an answers section for providing answers, I don't understand why people comment in an attempt to give someone an answer/suggestion... It defeats the purpose of the StackExchange, surely a comment would be to request more information.
    – peteski
    Commented Sep 11, 2012 at 9:35

10 Answers 10

129

It depends on whether the static classes maintain state or not. Personally, I have no problem with stateless functions thrown together in a static class.

10
  • 125
    Correct. Static functions which have no side effects are the most testable functions of all. Commented Aug 13, 2012 at 21:58
  • 12
    +1 to that, but with a safety clause: Almost every abstract algorithm is stateless, but that does not mean you should implement it as stateless static class or method. Implementing it in such way causes all the code using it to be hardly-linked to it. This means for example that if you implement sorting algorithm as a static method and thn use it through the project - that you cannot temporarily replace the sorting to another algorithm i.e. for testing purposes and for narrowing the problem area. This a huge hindrance in many cases. Aside of that, static is totally OK if used reasonably.
    – quetzalcoatl
    Commented Aug 14, 2012 at 1:36
  • 15
    In short: they are the most testable functions, but not necesarilly they make the other code more testable! This is what the architect meant probably.
    – quetzalcoatl
    Commented Aug 14, 2012 at 1:37
  • 4
    @tereško: The C# language requires static methods to be part of a static class, if you don't want to have to create an instance of the class to call the method. Perhaps you mean "instance," and not "class." Commented Aug 14, 2012 at 15:06
  • 8
    @quetzalcoatl: It's perfectly legal to pass a delegate (i.e. a different algorithm) to a static method; the extension methods in Linq are all static methods. Example: msdn.microsoft.com/en-us/library/… Commented Aug 14, 2012 at 15:09
102

He is too general about it. He is correct, it hinders testing. However, static classes and methods have their place and it really depends on the context. Without code examples you can't really tell.

I use static when I am not going to create an instance of a class because the class is a single global class used throughout the code.

This can be severe code smell. What are you using the classes for? To hold data? To access a database? Then he is correct. You should look in to dependency injection in that case, as such a static class is effectively an implicit singleton.

If you are using them for extension methods or helpers that don't change the state and just operate on the parameters you provide, those usually are fine.

3
  • 4
    +1 for mentioning that the statement was to general and mentioning extension methods, which also can be tested and dependencies can still be mocked as far as I know.
    – Nope
    Commented Aug 13, 2012 at 22:02
  • 6
    Aye static as single class instance as an implicit singleton, that's going to get messy....
    – Tony Hopkinson
    Commented Aug 13, 2012 at 22:16
  • "To access a database?" why not ? if table adapter is not static then creating a static class @ strongly typed dataset, nothing wrong with it.... unless you prove your point with reference or example ? Commented Oct 16, 2015 at 13:24
34

I checked and fully 1/4 of my classes are marked "static". I use static when I am not going to create an instance of a class because the class is a single global class used throughout the code.

The best thing to do is to try and unit-test your code. Try designing tests that are repeatable, independent, simple and test only one method at a time. Try running your tests in different randomised order. Can you get stable "green" build?

If yes, that's a valid point to defend your code. If, however, you have difficulties, then maybe you should go for instance-based methods.

3
  • 10
    This is the point that struck me too. A few static and stateless 'helper' style classes are fine, but if you've got a full 25% of all your classes as static, it's unlikely that your efforts are limited to that case. Commented Aug 14, 2012 at 0:57
  • 3
    @MatthewScharley - he probably got 4 classes, and 1 of them is Static :)
    – Alexus
    Commented Jun 23, 2015 at 20:25
  • 1
    Watch out that if you use such stibcs (like singletons), that later creating more instances might be a hard job. Like e.g. making an application that handles a document, you run into problems later when you want to manage multiple documents. Commented Aug 5, 2016 at 12:34
15

The answers already posted cover a lot of really good points, but there is one that seems to be missing:

Static fields are never garbage collected.

This is really important if you have an app with a lot of memory constraints, and this pattern can be very common when people try to implement a cache.

Static functions are not nearly as bad, but everyone else has covered this in enough detail already.

3
  • Oh really? If I have Cache.LanguageList (LanguageList is static field) which has 5 items and then I do Cache.LanguageList = new List<Language>(), is my previous 5 items will not be garbage collected? Do you know how to remove the previous 5 items from memory?
    – Sam
    Commented Jun 12, 2020 at 8:57
  • 2
    This is a very old answer, and you are correct--they would be garbage collected. The better way to say it is that the fields never fall out of scope, and therefore managing memory usage is an extremely manual process.
    – riwalk
    Commented Jun 12, 2020 at 14:51
  • Thank you for clarifying... Now, I can relax a bit... LOL...!
    – Sam
    Commented Jun 13, 2020 at 10:39
11

One of the advantages that you get from IoC/DI is that most interactions between classes are negotiated between interfaces. This makes unit testing easy because the interfaces can be mocked automatically or semi-automatically, and therefore each of the parts can be tested for inputs and outputs. Furthermore, beyond testabilty, putting interfaces between everything allows you to have the most modular code possible -- you can easily replace one implementation without quite so much worry that you're screwing up dependencies.

Because C# doesn't have metaclasses, a class can't implement an interface using static features, so static features of classes end screw up any effort to implement a pure IoC/DI object model. That is to say, you can't create a mock to test them, and you have to create real dependencies.

If your company/project is invested heavily in doing IoC, this of course is a reasonable concern, and the pain you're going through is for the gain of all. From an architectural standpoint, however, I personally don't think that any model should be followed to the grave. There are some things that make sense to implement using static methods -- the singleton design strategy, for instance. I'm less inclined towards static classes myself because I think they tend to start to lose the advantages of OO, but there are times when a library class is probably a more natural expression of something than an engine.


Commenter reminds me of extension methods, which of course have to be in static classes in C#. That's legit, and is an example of how pure IoC doesn't work super well in C#, at least if you're trying to take advantage of the breadth of the language.

4
  • 1
    If a class is made static for the right reasons and correctly implemented such as for example extension methods they are still testable very much as they would have no external dependencies and are self-contained and as such should not require mocking. Should the need for an interface not be driven by the design requirement to best full-fill a business requirement not for the sake of keeping a pure IoC/DI project?
    – Nope
    Commented Aug 13, 2012 at 22:12
  • 1
    You and I agree on the general point that you should choose the right tool for the right job and not be handcuffed by philosophy. If, however, there is a well established culture in place in your project of pure IoC/DI, it'll hurt just as much as converting a traditionally top-down solution to IoC/DI. Engineering needs to consider the transitional costs. By the by, I don't think extension methods quite get you there. I think a better solution for IoCish behavior with static classes would be to have multiple classes chosen between at compile time with preprocessor directives, C style
    – jwrush
    Commented Aug 13, 2012 at 23:43
  • 1
    Er. I'm dumb. You meant a static class for HOLDING extension methods, which, of course, is how you have to do them. Yes, of course, you want a static class for that purpose. That slipped my mind: and this goes to show that C# was not intended for IoC. :)
    – jwrush
    Commented Aug 13, 2012 at 23:46
  • Yes, you are right, if an existing culture in an existing project exists it would be more damaging than helping to change the way things are done.
    – Nope
    Commented Aug 13, 2012 at 23:58
5

Static methods are fine to use and have a rightful place in programming. It sounds like your architect has a testing framework that does not fully support static methods. If your code is part of a bigger project, then it is important to meet the architects guidelines. However, don't let this project deter you from using static methods when it is appropriate to do so.

5

Static classes are sometimes misused and should be:

  • a singleton (where the non-static class has a static member and a public static Instance variable to retrieve/create it only once.
  • a method in another class (where the state matters). If you have a member that is using no data from that class, probably it should not be part of that class.

It also might be a so called 'utility' function, and part of a utility class. Utility classes are classes that contain only static methods and serve as helper functions without any context.

2
  • @topomorto Because the class shouldn't be instantiated by its constructor resulting in multiple objects/instances, but by a special method (normally instance())< which returns always the same instance, instantiated after the first call to instance(). Commented Aug 5, 2016 at 12:32
  • @topomorto I just checked and you are completely right, only some members are static (the instance variable and the instance function). I will change my answer accordingly; thanks for mentioning. Commented Aug 5, 2016 at 21:51
1

I have been using static properties for things that are common to all instances of a class. And I have been using static methods to get groups of class objects. I am by no means an expert but this has been working for me so far.

PHP example:

class vendorData {
  private static $data_table = 'vendor_data'; // static property
  private $id; // instance property
  private $name; // instance property

  public function __construct($vendor_id) {
    if(!self::validId($vendor_id) ) { // static method
      return false; // id doesn't exist
    }
    $this->id = $vendor_id; // id has been validated
    $this->getProperties(); // object method
  }

  private static function validId($vendor_id) {
    // send db query to find if the id exists
    // return true/false;
  }

  private function getProperties() { // object method
    $sql = "SELECT * FROM `{self::$data_table}` // using static property
        WHERE `id` = {$this->id}"; // using object instance property
    // get resultset
    foreach($result as $property => $value) {
      $this->$property = $value; // object instance properties all set
    }
  }

  // and here
  public static function getBy($property,$value) { // static method to return object array
    $sql = "SELECT `id` FROM `{self::$data_table}` // using static property
      WHERE `$property` = '$value'";
    // send query, get $ids array
    $obj_array = array();
    foreach($ids as $id) {
      // create array of current class objects using special static keyword
      // meaning of static here is different than in property/method declarations
      $obj_array[$id] = new static($id);
    }
    return $obj_array;
  }
}
1

I'll say the principles they have are ok but the statement (don't use statics) may be wrong. How much is your code coverage? if the number is high and you are comfortable with the unit testing of your app, then you are ok. If not, then I would suggest review the code. You may find static classes are the reason or not, it will depend on a lot of things.

-2

Classes with static methods abuse the principles of OOP. It's not an OOP already, it's COP -- class-oriented programming.

They rarely have clear "personality" (I use my favorite human metaphor here), or identity. So they don't know who they are. This point alone is enough to get rid of this concept in OOP, but there are more of them.

The next one is a consequence of the first point. Since such classes don't know who they are, they tend to be from big to huge.

Third one makes your code absolutely non-maintainable. The use of static methods introduces hidden dependencies. They pop up all over the place, and you never know what's happening in your class. You can't be sure in that just by looking at the constructor signature.

Slowly, but inevitably, your code's getting less and less cohesive, since hidden dependencies are poorly controlled. They seem invisible. And it's so easy to add another one! You don't have to modify any method's signature. All you have to do is to call a static method. And what an ugly code follows...

Ok, you probably already guessed. Tight coupling is an oft attendant of low cohesion. If there are a lot of clients using some class, then the coupling is getting tighter. And there is a big seduction in using an already written class or method that requires only tiny fix. Only one method flag-parameter.

What to use instead of static methods? Well, my suggestion is OOP. Why not giving it a try?

Not the answer you're looking for? Browse other questions tagged or ask your own question.