Avoiding main class to be static. Opinions about this lousy hack

Hey!

I think I’ve done something smelly, but not sure. I want to access some of my main class, Game, fields (SpriteBatch, change current state, etc.). The solution I was using prior libGDX is to make all fields and methods of Game static (smellrometer overflowing!). But libGDX uses an instance to start the game loop, so I had to change the way I do things.

Now I have a Overlord static class which stores all the important instances (right now is only Game) and provides public static methods for accessing its fields.


public class Overlord
{
    private static Game game;

    public static Game getGame()
    {
         return game;
    }

    public static void setGame(Game game)
    {
        Overlord.game = game;
    }
}

I have global access to the SpriteBatch (the canvas where I draw) via Overlord.getGame().getSpriteBatch().

In a scale from “good idea” to “worse than unjustified GOTO”, what do you think about it?

My game isn’t static at all. I just pass references to the object around to those instances that need a reference. Not sure if this is any way better than what you’re doing though. :slight_smile:

According to your motivational speaker kevglass:

  1. Make it work
  2. Make it fast enough
  3. Make it pretty

in that order.

All my games work more or less like this and I’m making a living from it. QED

Cas :slight_smile:

You can make the game even smaller:

This class does not even need a main function to run:



public class Badbad
{

static {
		System.out.println("Bad Coding");
		for (int i=0;i<8;i++) System.out.println(i);
		}

}

Java will wimmer that there is no MAIN! (oh no) function, but it still runs.

@Regenuluz: Thanks! I used to keep a private reference to Game in all the classes that made use of it. But there are two problems:

  1. it escalates really bad (just imagine you have to access to other two classes, more getters/setters, more fields…)

  2. it breaks certain symmetry that my OCD didn’t allow to happen. Imagine you use game states. Menu is a child of GameStates which in turn is parent to all kind of menus (pause, game over, main menu, etc.). Probably some menus will make use of Game while others don’t. Then what? Include special Game fields in the ones that use it (apart from special constructor and/or getters and setters) which makes every Menu child different, or include a Game field in Menu, which is under-efficient.

So I ended up using a static Overlord XD

@Riven, @princec, @Damocles: Thanks for the advice! I knew about kevglass uber-rules that rule (I still have to improve GettingStarted.part 5…) and it certainly is a relief to know that important gamedevs like yourself think it is not too bad not to use it :_)

Having a global Game is perfectly fine. But you should be aware of where you use it. Consider passing data in as parameters to methods or to the constructor instead of getting the data threw the global Game object. It will reduce coupling. So it would be ok to use it in the Menu screen but maybe avoid it in the Font class.

Also, some personal preferences:

Avoid using setter and getters. Just make the fields public if it is a data heavy class, like tuples. If the data is read only then pass it into the constructor and make the field final.

Avoid using inheritance. Especially if you use it as a way to reuse code.

Yes! someone got this when using libgdx :smiley:

@OP I’ll share my current structure

GameWindow
Game (has Bitmapfont, main loop and SpriteBatch)
|> all states (Game as constructor ref)
|
> entities (Game as constructor ref too, so each entity can grab delta time, keyinput, SpriteBatch which is public)

I don’t understand that, especially: “Consider passing data in as parameters to methods or to the constructor instead of getting the data threw the global Game object”. Do you mean something like this example?


// good
public void draw(SpriteBatch sb)
{
    mySprite.draw(sb);
}

// smelly
public void draw()
{
    mySprite.draw(Overlord.getGame().getSpriteBatch());
}

Or do you mean to have Overlord to return data instead of an instance of Game?


public void draw()
{
    mySprite.draw(Overlord.getSpriteBatch());
}

I agree. By default I always use getters/setters and never public fields (Effective C++ can be really convincing), but for some read-only fields I think the final field + value passed as constructor parameter could be 1) logically better, 2) prettier :slight_smile:

I mainly use it because of polymorphism (I have a GameState field, but store a Menu, a Level, or Cinematic, which are children of GameState).

But also for code reuse. Menu has the methods to check whether the user has touched a menu entry and to call the appropriate Command to execute. So MainMenu, PauseMenu, GameOverMenu, and so do not have to repeat that piece of code.

What is your alternative?

What do you accomplish by using a local reference to Game instead of having it accessed globally? For an entity-heavy game you could end up with 100+ local references to Game. Isn’t it better to use only one reference that is globally accessible?

Thanks for your comments, I’m enjoying very much knowing how other people have dealt with these problems :slight_smile:

I use a fairly reasonable amount of inheritance - usually no more than 3 or 4 levels deep - because composition in Java is ugly boilerplate and basically slower to code and a bitch to maintain vs. inheritance.

Cas :slight_smile:

Honestly, not much. I use the global method. Not only is it used by just about every class in the system, it’s also effectively a singleton; it simply doesn’t make a lot of sense to pass it around everywhere unless you’re of a mind to do unit testing. If you’re doing unit testing for your game you’ve already wasted half your time making the game.

Cas :slight_smile:

You know, we should have a thread where everyone post their structure. Especially from mods.

I think it’s a fantastic idea! I would learn a lot from other people structures and from other people complains about mine.

I meant the first one.

I meant the opposite. I consider getters/setters as a bad smell and can often be symptomatic of bad design.

Composition. Google around and you’ll find that most people favor composition over inheritance.

But if all your making is a small game and you don’t do unit testing and don’t refactor much, then it doesn’t matter. Just make it work.

First hit on google: http://www.artima.com/designtechniques/compoinh.html

1998 article but should still apply.

Now wondering where should the thread be made, post about class structure can be long.

There is always a conflict between the right way and the easy way. Atleast its impotant to know the downsides if you go the easy way. e.g. maintaining a large Application without units test or reading Code with deep inheritance hierachy is a pain.
For me the only way to go fast is go well.

@yuma
global state is bad see why: http://www.youtube.com/watch?v=-FRm3VPhseI

That’s good in this case, because all the draw methods are called from Game.draw() and I can pass the SpriteBatch parameter on them. But when things go the other way around (imagine Entity.update() needs information of SomeOtherEntity.getPosition()) then I don’t see how to make it. It’s just the way I know how to make things work :frowning:

That’s weird, I consider accessing the field directly to be a bad habit. You are breaking encapsulation for good. I understand that sometimes, when modifying great amounts of data, passing a heavy input parameter to a setter could be less efficient. But accessing the field directly by norm…

Hmm, I thought composition was preferred to inheritance when there is no clear is-a relationship, but in my case, MainMenu is-a Menu and Menu is-a GameState. It really don’t go further than two/three levels. Also, composition has the great disadvantage of delegating all methods to the implementation (is it more tedious to maintain though might be less coupled to the superclass).

Thanks! I keep it in mind and have to read about composition with interfaces, which the author claims is the real replacement to inheritance.

Maybe it looks I’m just rejecting by default all your advices, but it’s not the case. I’m reading and learning with them, even though I might not follow them too strictly. Thank you!

I’ll buy the first, but the second doesn’t compute for me at all.

I agree with you, completely. But sometimes we can’t choose the “right way” because we don’t know where it is :frowning:

[quote]Thanks! I keep it in mind and have to read about composition with interfaces, which the author claims is the real replacement to inheritance.
[/quote]
Honestly I agree with him. Look how easy problem can be solved by interface, and I use interface a lot. Basically it tells you to avoid inheritance and code separately then use interface when you need polymorph.