Static methods good alternative to global functions?

Started by
8 comments, last by Guthur 15 years, 3 months ago
I know it's considered bad to have a lot of global data and functions in large projects. I'm not very experienced, but I've already found a few places where they're inconvenient. Lately, instead of making a particular object global because I need access to it elsewhere, I've made select methods in it static. For example, my Renderer class has a method that converts game-logic coordinates to screen coordinates, and this needs to be called from all over. Where once I would have made a global Renderer object, now convertCoords() is static, and I can make a call Renderer::convertCoords() anywhere I like. Is this considered a good solution? I find it kind of messy and inelegant — something about making methods static just because they need to be accessed from outside the class bothers me — but I'm hoping it's better than having a lot of global objects.
Advertisement
I'd consider something like that to be just fine. There are times when helper functions are needed, and creating an object would make no sense. Personally though, I don't know if you should make it a static method part of a class, or a regular global method wrapped in a namespace. Syntacticly it's the same thing, so use your judgment and do what makes sense.
[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]
It's not considered bad to have a lot of global data and functions. It's considered bad to have a lot of globally mutable state. Constant data is pretty good. Free functions are good in certain languages and good in moderation in others.

For this case, MikeTacular is right.
Quote:Original post by Sol Blue
something about making methods static just because they need to be accessed from outside the class bothers me
Really, the question isn't whether a method that doesn't touch member variables should be made static or not. If it doesn't touch member variables then it should be static, or a free function. Unless you need it to overload a member function from the base class that is a member, that is.
Otherwise you've effectively got an unused parameter, the 'this' pointer.
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
In object-oriented programming, global objects are not a problem: global pervasive mutable state is a problem.

  • You can create global objects without creating global pervasive mutable state.
  • You can create global pervasive mutable state without creating global objects


The question you should ask yourself is, can code A and code B communicate with each other by means of this feature?

In your example, the answer is yes: code A can set the screen coordinates in the renderer, and code B can then call convertCoords() to guess the data that code A has entered. This makes code B dependent on code A through a global channel, which is bad news in an object-oriented world.

Of course, in a procedural world, none of this is an issue: make your renderer a global module that's neatly wrapped up with documented dependencies on other pieces of global state, and have fun.
Quote:Original post by ToohrVyk
Of course, in a procedural world, none of this is an issue: make your renderer a global module that's neatly wrapped up with documented dependencies on other pieces of global state, and have fun.


Where this gets gray is that C++ is a multi-paradigm language which trusts the programmer to make the right decision for the problem at hand. This is a good thing, but means that you must very carefully weight the options and ensure it makes sense with the rest of your code.

Primarily the concerns should be maintainability, extensibility, and flexibility... But not so much so that you never get anything done. Provided you bear all that in mind, do what you believe is best for your problem.
_______________________"You're using a screwdriver to nail some glue to a ming vase. " -ToohrVyk
If your function can be made a non-friend non-member function, and is likely to remain that way, then it should probably not be part of a class; ya i'm still quoting Meyers :). Following this advice should also allow you to ensure better encapsulation of your object data, which should be top of your list of priorities in OOP.

In my opinion, if possible, and it more than likely is, do not clutter the global namespace, create relevant namespaces and place code in them. Your can augnent this by having forward declaration headers if possible so decreasing translation unit dependencies. Global namespace code will most likely go against all of this; I am not overly experienced but it does make me feel uneasy like I think it should.
Innovation not reiterationIf at any point I look as if I know what I'm doing don't worry it was probably an accident.
Quote:Original post by Sol Blue
For example, my Renderer class has a method that converts game-logic coordinates to screen coordinates


Is this conversion always the same?

And if so, haven't you discovered that there are other similarly-behaved things in your program? E.g., GUI widgets that have a position in some kind of "frame", where the frame needs to be positioned (offset) within the main window.

I imagine that what you really want is to extract a Viewport class, and let what would have been the "global Renderer" instead be an ordinary instance of Viewport that gets passed around. Then your top-level rendering code can assemble a sequence of Viewports, and decide in what order to render them and how to lay them out within the window.
Quick question - if this is used "all over," what for? How many of your objects have a concept of the coordinates on the screen, and how many of them really need to have a concept of this?

I don't really consider static/global functions bad, if they're truly functions - calling them with the same parameters will always return the same result, and it is side effect free. If they're more like procedures, there's a little more reason not to.

I mean, I don't think anybody is really arguing that sin() should only be called from an object.
The C++ version of Sin() is not in the global namespace its in the std namespace. But otherwise I agree if the shoe fits.....

Theres nothing wrong with non-member functions and its cool that C++ allows them where as other OO language do not eg. C# and Java. Just don't throw them all in the Global namespace, there really is very little need or compelling reason to do it, as far as I can see.
Innovation not reiterationIf at any point I look as if I know what I'm doing don't worry it was probably an accident.

This topic is closed to new replies.

Advertisement