2007-12-18

How not to use static class members

Recently I came across a new experience which I consider a good example of "How not to use static class members".

Static class members are members (attributes and methods) which are shared between all instances of a class.

I.e.: If one instance changes the value of a static attribute, all other instances know this new value immediately.

Static members -particularly attributes- are shurely useful for configuration purposes, where all instances share a really really common knowledge with each other.

Static members are also indeed necessary for patterns like Singleton or Factory.

They are absolutely necessary to declare constants.

BUT: Static members are fatal if their usage include a runtime aspect.

I experienced that, when I inherited some code which extended the JUnit Framework to do validation on a loaded Model. Each validation was declared as test method of a so called "ValidationCase". As JUnit implicitly creates new instances for each test method to be called as test case.
So when running a specific test class, there are a bunch of instances of this class. For the validation now they had to share the model element to be tested.

The quick answer to this problem was: put it into a static member, all instances will know it then. Advantage: The location where these instances were created was inside the JUnit framework and didn't need to be touched.

BUT:
The error in this notion was: Not all instances of a test class share this model element. (As there are more model elements which are tested later and before by the same test class).

So the rule is: Only all instances of the test class which exist at a given time share this knowledge. At other times the share contains other information, shared by all instances actually existing then.

It worked well as long as only one model element was validated at a time.
The problem of this approach occured when once the validation system was extended to call a validation of one model element out of a validation of the other.

Now there were two groups of instances, one for element A, one for element B. But when B was under test, all instances shared the reference to B. And the reference to A was lost. Overwritten at a point in time.

Even this worked, as long as the validation of B happened to be the last action in the test of A, and the A reference was never needed afterwards.

But it was obvious that this card house once would collapse....

So: Everytime you introduce a static variable into a class, check carefully if its value is really valid for all instances of this class, even over time.
Avoid using static members out of well known pattern (like constants, Singleton, Factory ...).