Static function design paradigm

Started by
11 comments, last by Ravyne 12 years, 8 months ago
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?
Advertisement
Recommend two articles,

Why Singletons are Evil Old but still worth read.

Dependency injection A way to avoid singleton.

In brief you should forget and avoid singleton.

https://www.kbasm.com -- My personal website

https://github.com/wqking/eventpp  eventpp -- C++ library for event dispatcher and callback list

https://github.com/cpgf/cpgf  cpgf library -- free C++ open source library for reflection, serialization, script binding, callbacks, and meta data for OpenGL Box2D, SFML and Irrlicht.


Recommend two articles,

Why Singletons are Evil Old but still worth read.

Dependency injection A way to avoid singleton.

In brief you should forget and avoid singleton.


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?
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.
Preface: Sorry sad.gif
...for the managers that would usually be singletons
Managers should not usually be singletons... but even if you were using singletons for some reason, your proposed alternative is almost exactly the same.
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.
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.
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.
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.

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?


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.

https://www.kbasm.com -- My personal website

https://github.com/wqking/eventpp  eventpp -- C++ library for event dispatcher and callback list

https://github.com/cpgf/cpgf  cpgf library -- free C++ open source library for reflection, serialization, script binding, callbacks, and meta data for OpenGL Box2D, SFML and Irrlicht.

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.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]


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.

I'll just write it the standard way with pointer passing. I didn't think about the dependency problem.



[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.

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?


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.


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 security risks of global pointers, which of course includes singletons. They usually back off then.


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


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

This topic is closed to new replies.

Advertisement