
Today a question of a colleague put me back on one of my hobby horses: the danger of static. I have a true abhorrence for class members. For C#: static fields and properties, for Java static attributes and for Visual Basic .NET: Shared fields and properties. To me ‘static’ is one of those things that should have never been allowed in the (modern) object oriented languages. Let me explain my concerns.
Static means that the property is an attribute of the type. Unfortunately this is commonly explained as a shared value across all instances of the type. Even worse, starting programmers interpret this as: “I have to use static when a property of a class has the same value for all instances of that class”. Which is different because it illegally inverts the ‘rule’.
Let’s have a look at a classic example: a bank account class and its interest attribute. All accounts must have the same interest level and it would be pretty hard to implement this requirement by keeping the values synchronized across all instances. It would appear that this attribute is a good candidate to become a static property of the bank account class. Now suppose you implement the requirement by using a static property. All seems fine until that dark day comes when the program needs to be adjusted to accommodate not just the bank accounts of a single bank but of multiple banks. These banks do not share the same interest level. So what to do? Change the static to an instance property? Create a bank account class for each bank?
Every time I run into questions like these I know there is a flaw in my design. In this case I think that the assumption that the interest is an attribute of the bank accounts is wrong. I think that it is an attribute of the bank or an attribute of the association between bank and its bank accounts. Suddenly I can do without the static.
Another thing that has been bothering me for a long time is the static main. C#, Java and Visual Basic .NET have all inherited (pun intended!) this entry point from C. Which, in my humble opinion, is pure nonsense. Instead of explaining what is wrong with it, let me propose a more object oriented solution. As you may know a Java program is started (on the command line) by starting the virtual machine and passing it the name of the class that contains the static main. Like this: java MyFirstBank I propose a tiny adjustment: instead of having this line calling the static main of the class have it call the constructor of the class, optionally an overload of the constructor with fitting parameters. As much as this seems trivial it will take away the strange requirement of the static main and on top of that this will allow you to run any class as a program.
My final worry: many programmers that have a lot of experience with procedural programming in C or in VB6 or other, similar languages have trouble understanding object orientation. So two things happen: 1. The first thing they are confronted with is the static main, a (sort of) global function. You know, that evil thing we are trying to unlearn. 2. Static allows these starting OO programmers to fall back to old habits.
I think that in 99% of the cases we can do without static properties (if you use them make sure you use some kind of synchronization/locking scheme because you share the property across all threads!!)
In short: Static invites bad design.
If you feel like replying to this post with examples of code that can only be implemented by using static please do so AFTER you have tried to solve the problem without using statics 😉 For example: do not assume that you really need a static to create a singleton. First be creative and try to create a singleton without using static and after you have done that investigate your solution and try to find what you have learned about statics and singletons…
4 comments
Very good points!
I am not 100% opposed to the use of statics in all contexts — their use can be defensible in certain low-level technical situations, such as when a class wants to maintain a cache of data across its object instances, for performance reasons, but that caching is an implementation detail which should be transparent to the calling code.
Mind you, I’m not saying that statics are *necessary*, even for that. And I agree that they get abused a lot more often than they get used legitimately, and that their very existence can encourage bad habits. Any code which uses statics tends to make unittesting a lot more painful, too. So I wouldn’t mind too much living in your world where modern programming languages simply did not have this feature.
Agree on the static main, too. Although I don’t really like the alternative of kicking off the whole program from the constructor of the startup class. A constructor should do the minimum amount of work necessary to get the object into a well-defined state, and nothing more. Teaching novice OO programmers to run their entire program from within an object’s constructor, might give them an entire *other* set of bad habits. So I would perhaps use an overloaded operator() in C++, or make the startup class implement the Runnable interface in Java and then have the VM call its run() method.
By the way, you may find this interesting also:
http://steve.yegge.googlepages.com/singleton-considered-stupid
I guess it’s fitting that the most obvious legitimate (even if not absolutely required) use for the ‘static’ keyword, is a design pattern which is already somewhat dubious in itself..
Martin Wolf
Hi Martin! Good to ‘see’ you again.
Yes, I know the debate on singletons quite well. that is why I made a concealed reference to it. I dislike singletons perhaps even more than I do statics. I wanted to keep the discussion on topic and perhaps write another post about singletons but don’t hold your breath for that; there a lot on the web about them already.
Erno de Weerd
But…
where do I leave my constants then? Or my globals? 🙂
Wouter
Static is not the solution for creating a constant. It’s like insisting that you need a nuclear bomb to scare the enemy and although a nuke can do that for you, it might not be the best or appropriate way to do that.
As for globals: how global is global? Most globals are scoped to the running process. What if the user starts multiple instances of the same program? What if multiple users start the same program? Have you ever noticed that when the day comes that they find out (as they inevitably will) that Pi equals 4 we have a serious problem updating all software that defines Pi? How global is that definition? (and how constant is Pi any way?)
😉
Erno de Weerd