Sign in to follow this  
3DModelerMan

Static function design paradigm

Recommended Posts

3DModelerMan    1173
I was thinking about game engine architecture today and had an idea. If you wrote most of the game engine code for the managers that would usually be singletons (like the application layer, the event manager, etc) using static functions and static member variables. Would it be able to scale well as a clean efficient code base? I can think of a few benefits of such a design but I want people to help point out some flaws. First, it would remove the need to write any singleton classes (which are not thread safe). Second, it might make multi threading easier because you could have critical sections/locks on each system, and it would also cause the code base to be easier to work with because you could access static functions without cumbersome pointer passing through the constructors. What flaws can you think of in a system like this that would need to be thought about before implementation?

Share this post


Link to post
Share on other sites
wqking    761
Recommend two articles,

[url="http://blogs.msdn.com/b/scottdensmore/archive/2004/05/25/140827.aspx"]Why Singletons are Evil[/url] Old but still worth read.

[url="http://en.wikipedia.org/wiki/Dependency_injection"]Dependency injection[/url] A way to avoid singleton.

In brief you should forget and avoid singleton.

Share this post


Link to post
Share on other sites
3DModelerMan    1173
[quote name='wqking' timestamp='1313293456' post='4848849']
Recommend two articles,

[url="http://blogs.msdn.com/b/scottdensmore/archive/2004/05/25/140827.aspx"]Why Singletons are Evil[/url] Old but still worth read.

[url="http://en.wikipedia.org/wiki/Dependency_injection"]Dependency injection[/url] A way to avoid singleton.

In brief you should forget and avoid singleton.
[/quote]

So the static idea wouldn't be good? I was noticing that Unity had alot of static functions and I was thinking of doing something like that. Or is it just the scripting system that has all the static functions? Would the C++ side actually implement them that way?

Share this post


Link to post
Share on other sites
rip-off    10979
Moving from singletons to static functions won't make your code thread-safe. When people talk about singletons being thread-unsafe, what they really talk about is the typical implementation of a "lazy" singleton. You still have a lot of work ahead of you to make any shared mutable state thread safe, whether it is in a singleton or not.

One massive flaw with such a system is that it is impossible to unit test components in isolation.

Other flaws are mostly stylistic and subjective. I believe that such a design will promote poor dependency management. I believe that explicitly specifying dependencies (e.g. pointer passing) is preferred to control this aspect. I believe such a design will result in hard to debug errors when these components interact in unexpected states.

I think that such as design is usually proposed by people who don't have enough experience in designing large systems. The appeal of being able to call a particular piece of functionality from anywhere isn't tempered with the knowledge that this isn't a good idea.

Share this post


Link to post
Share on other sites
Hodgman    51324
Preface: Sorry [img]http://public.gamedev.net/public/style_emoticons/default/sad.gif[/img]
[quote name='3DModelerMan' timestamp='1313292767' post='4848846']...for the managers that would usually be singletons[/quote]Managers should not usually be singletons... but even if you were using singletons for some reason, your proposed alternative is almost exactly the same.
[quote]Would it be able to scale well as a clean efficient code base?[/quote]If you're relying on class-static members, then they're just another name for global variables. Global variables are almost always not clean.
[quote]First, it would remove the need to write any singleton classes (which are not thread safe).[/quote]A class-static member is not thread safe in the same way that a singleton is not thread safe.
[quote]Second, it might make multi threading easier because you could have critical sections/locks on each system[/quote]Locks are not composable, so doing this will lead to deadlock bugs.
Also, ensuring thread safety by putting on locks on every system is terrible for performance.
[quote]it would also cause the code base to be easier to work with because you could access static functions without cumbersome pointer passing[/quote]Allowing you to easily and constantly violate the Principle of Least Knowledge may seem like it makes things easier in the short term, but in the long term, it makes for an unusable code-base of circularly dependent spaghetti.

Share this post


Link to post
Share on other sites
wqking    761
[quote name='3DModelerMan' timestamp='1313328269' post='4848945']
So the static idea wouldn't be good? I was noticing that Unity had alot of static functions and I was thinking of doing something like that. Or is it just the scripting system that has all the static functions? Would the C++ side actually implement them that way?
[/quote]

I never read Unity code and have no idea what its static functions do.
In my opinion about static function,

1, If the static function holds states globally, then it's a variation of singleton. Not good.
2, If the static function is just a utility, such like sin, cos, it's good.
And now sometimes I would prefer extracting member functions as static functions.
e.g, change A::func to globalFunc(A *), etc. It gives the potential to make globalFunc templated to hold different type.
No means to encourage to make all member functions to global, just an example.

Share this post


Link to post
Share on other sites
3DModelerMan    1173
[quote name='ApochPiQ' timestamp='1313378763' post='4849227']
You may as well just write everything with namespaces and global variables.

If you can't instantly see why this would be a bad idea, you need to get more experience implementing large-scale systems.
[/quote]
I'll just write it the standard way with pointer passing. I didn't think about the dependency problem.


Share this post


Link to post
Share on other sites
3DModelerMan    1173
[quote name='3DModelerMan' timestamp='1313414165' post='4849365']
[quote name='ApochPiQ' timestamp='1313378763' post='4849227']
You may as well just write everything with namespaces and global variables.

If you can't instantly see why this would be a bad idea, you need to get more experience implementing large-scale systems.
[/quote]
I'll just write it the standard way with pointer passing. I didn't think about the dependency problem.



[/quote]




Do you think that sending events would count as a utility function?


Share this post


Link to post
Share on other sites
L. Spiro    25638
[quote name='rip-off' timestamp='1313331714' post='4848971']Other flaws are mostly stylistic and subjective. I believe that such a design will promote poor dependency management. I believe that explicitly specifying dependencies (e.g. pointer passing) is preferred to control this aspect. I believe such a design will result in hard to debug errors when these components interact in unexpected states.

I think that such as design is usually proposed by people who don't have enough experience in designing large systems. The appeal of being able to call a particular piece of functionality from anywhere isn't tempered with the knowledge that this isn't a good idea.[/quote]

I agree so much that I voted up your post.
I have yelled at employees who made such open systems by allowing everything access a global whenever.
A lot of people have also suggested to me to make the game class, sound managers, etc., in my current engines into singletons. I basically reply with exactly what you said. Even though it is 100% correct, some people still seem convinced that I should change. It is disappointing how skilled some coders can be but just be stuck in their ways, unwilling to listen to reason.

Then I explain the [i]security[/i] risks of global pointers, which of course includes singletons. They usually back off then.


Global-related spaghetti is exactly why I stopped working on [b]MHS[/b]. It was just too much hell to maintain.


L. Spiro

Share this post


Link to post
Share on other sites
EJH    315
There really isn't much different between a singleton, static, or global class.

That said, I personally do use a fair bit of static classes in my C# code. A few examples are Random Number Generator, Audio Player, Asset Libraries, and Logging. It just seems .... dumb? .. to pass an instance of a Random Number Generator to every single class that generates random numbers (in a largely procedural game, almost everything has some randomness). But for these classes threading doesn't matter, their internal states don't affect anything else, and if I ever really cared to refactor them as non-static classes, it would be a simple matter of deleting the "static" and a bit of Search and Replace.

Share this post


Link to post
Share on other sites
Ravyne    14300
[quote name='wqking' timestamp='1313375566' post='4849205']
[quote name='3DModelerMan' timestamp='1313328269' post='4848945']
So the static idea wouldn't be good? I was noticing that Unity had alot of static functions and I was thinking of doing something like that. Or is it just the scripting system that has all the static functions? Would the C++ side actually implement them that way?
[/quote]

I never read Unity code and have no idea what its static functions do.
In my opinion about static function,

1, If the static function holds states globally, then it's a variation of singleton. Not good.
2, If the static function is just a utility, such like sin, cos, it's good.
And now sometimes I would prefer extracting member functions as static functions.
e.g, change A::func to globalFunc(A *), etc. It gives the potential to make globalFunc templated to hold different type.
No means to encourage to make all member functions to global, just an example.
[/quote]

You, and maybe the OP, seem to have a misunderstanding about what a static function is -- static is one of those funny, overloaded keywords that C++ has:

[list][*]Within the context of a function body, static means that a value is initialized once on the first call, and its state is preserved thereafter between calls.[*]Within the context of a class definition, static means that the state or function is shared between instances, and may be externally accessible through the name of the class if marked public.[*]Outside of the above-mentioned contexts, static means that it has internal linkage, rather than external (the default).[/list]

In your #1 and #2, it makes no difference that the function is static -- your statements hold for "free" functions ("free" as in global, this is what you really mean) just as well. Static functions are a subset of free functions. For example, it would make little sense to have utility functions like cos or sin be "static" because they wouln't be able to be called from outside their own module (this *could* be desirable, but not so, generally speaking).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this