« Clarification: Quatloos vs. Man-Days | Main | Globals underrated - fight! »

July 23, 2009

Comments

Tipa

1. Instantiate beans with various information and attach them to the global session object, where they are available if needed, and not if not. Java doesn't use header files, so you're all good there.

2. Use Java :)

Okay, yes, I understand Java isn't (yet) fast enough -- but it almost is, and for many applications, it probably actually is fast enough now, as well as being a LOT LESS system dependent than C++. I write games in various flavors of Python, and there's very little speedy about THAT language (though I have written some bits in C++). Isn't EVE Online written in Stackless Python?

Maybe it's time for the game industry to look more into the possibility of using slightly more modern and portable languages?

Noel

I have you say, I completely disagree, Jamie.

Let me get one easy one out of the way: Having an App.h file is NOT going to make any appreciable difference. Having one thousand of those is probably not going to make much of a difference with proper forward declarations and header guards (just don't include templates, STL, or Windows.h).

But apart from that, I despise gobals and go out of my way to avoid having them in my code. Not out of a sense of "proper software engineering" (that's long gone) but simply because globals get in the way.

They get in the way of optimizations (harder to cleanly replace some code)

They get in the way of testing (no way to test without those globals)

They get in the way of refactoring

They get in the way of understanding the program flow.

And... the biggest of all if the globals are data... they get in the way of the data flow. Now you call a function and you have no idea what it is going to affect in memory. I prefer to have a very clear input data and output data parameters. You can easily take that and vectorize it, parallelize, schedule it, or whatever we have to do these days with our fancy hardware.

So yeah, you can say I feel pretty strongly that globals are evil :-)

Noel

Oh wait, I'm not done! (and the first line of the previous comment was supposed to be "I have TO say" BTW).

Singletons vs. globals.

Another huge problem with globals is initialization time. You have no guarantees about what else (globally) has been initialized. That's not purely academic, it's a big deal if you start needing graphics, or sound, or network, or the log system or...

Singletons with auto-initialization and shutdown are pretty pointless, and more counterproductive than anything.

If you really, absolutely must have singletons, please use explicit ones. I guess at that point it's no different than new and delete the global. Just don't use global variables that are actual class instances!

Patrick

I'm with Noel on this one, particularly on testability. Please do yourself a favor and see Misko Hevery's info on this. He's a little Java centric, but he gets the point across.

http://www.youtube.com/watch?v=-FRm3VPhseI

http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/

Parveen Kaler

It's not about global state. Ith's about how that state is accessed and where it's accessed from.

This debate raged for the last 5 years on the web: RESTful vs RPC.

RESTful won.

When designing a service these are the principles that you want to take into account:
- client/server
- layered
- cacheable
- resource based
- stateless protocol (VERY, VERY important)
- support CRUD type operations consistently and uniformly

All of this makes your code easier to read, testable, etc. And most importantly, it makes it will work in the many-core future.

More info here:
http://en.wikipedia.org/wiki/Representational_State_Transfer
http://www.xfront.com/REST-Web-Services.html

greggman

I used to believe like Jamie but on my latest project someone introduced me to the Service Locator pattern and it's been pretty awesome.

No globals, much less dependencies, easy to test things in isolation.

Originally we effectively had this App class that had a ton of dependencies and almost everything depended on it.

Now we have 10-12 mini classes separated by responsibility. Most of them depend on almost nothing and each higher level thing in our app only needs to include the small interface class headers for the particular services they need.

The only thing that has to be passed around is a pointer to the ServiceLocator or that can be the only global (as it is in our unit_tests).

greggman

Oh, btw, because of this ServiceLocator we don't have any Singletons. The advantage to this is for example in a unit test, like I mentioned before we do have a global service locator with a few services on it that lots of tests need so those tests will do something like

Renderer* renderer = g_serviceLocator->GetService();

But, even with the global service locator, in many tests we can create another service locator, add some services do it and the tests in that unit will use that one as in

// Create a new service locator
ServiceLocator localServiceLocator;

// Add a service to our local service locator.
MockRendererer mockRenderer<&localServiceLocator>;

// Call some test with our local serivce locator.
DoTest(&localServiceLocator);

...

void DoTest(ServiceLocator* serviceLocator) {
Renderer* renderer = serviceLocator->GetService();
... // Do something with the renderer.
}

Since DoTest takes a pointer to a SerivceLocator we can hand it the global one or one with our MockRenderer and it will find the one we want it to find.

I wish I could point you to more easy to follow examples but our code is open source if you want to browse

http://src.chromium.org/viewvc/chrome/trunk/src/o3d/core/cross/?dir_pagestart=150

service_locator.h is the class to find services.

service_implementation.h defines a class you put in another class if you want that class to be a Service.

service_dependency.h is a class that helps deal with to services that are dependent on each other.

Otherwise, features.h, renderer.h, object_manager.h, class_manager.h, error_manager.h, event_manager.h and others are all examples of services.

Those and about 10 others all used to be in client.h

If you want instructions on how to build see
http://o3d.googlecode.com

Otherwise, this pattern is apparently also called Dependency Injection but I don't know any good articles on it. The one on wikipedia is way to abstract.

greggman

Grr, your blog ate all my less than signs.

The GetService lines should look like

serviceLocator->GetService<IRenderer>();

The comments to this entry are closed.

Jamie's Bragging Rights

  • Spider-Man 2
    The best superhero games of all time Game Informer
    Top five games of all time Yahtzee Croshaw
    Top five superhero games of all time MSNBC
    Top 100 PS2 games of all time Official Playstation 2 Magazine
    1001 Games You Must Play Before You Die Nomination for Excellence in Gameplay Engineering Academy of Interactive Arts & Sciences
  • Schizoid
    Penny Arcade PAX 10 Award
    Nominated for XBLA Best Original Game
    Nominated for XBLA Best Co-Op Game