0
\$\begingroup\$

I have been having fun learning java for years, did a little bit of OOP tutorials and this is the first time I attempt to make a real project. The project is very similar to some top down view tabletop management game with very little graphics. Oddly every thousand line of code I hit my head on a wall and wonder if I need to restructure everything. For example I restructured once to try and adopt some concept of MVC, which I had no knowledge of when I started. I am glad I did.

The wall now : I started reading how we should use global and singleton sparingly when I suddenly could not save my game since I had created a new instance that had static fields (using GSON to save my Game object).

My project structure

  • App : gameloop, has Engine class, calls Engine.updateUI() and engine.updateGame()
  • Engine is the main controller that has access to all other controllers, creates the game object and updateUI() and updateGame() methods
  • Game : contains every object that represent the state of the game so that I can save and load it
  • MyData class is a global class that just loads a bunch of text files and provides data for the game but does not need to be saved

So lately I created a class called Finances that had static fields such as cash, waterBill, electricityBill... I can only ever need one instance of Finances in my game so I thought it would be neat to be able to do something like Finances.addCash() or if Fiances.getCash() == enough doSomething from anywhere in my code, from any controller, to enable and disable buttons for example.

I have another similar class called Updater that has static booleans as flags to schedule an update on certain part of the UI instead of having every UI elements update and query the model 60 fps.

Some solutions

  • Add some code to save and load the values of those static fields;
  • change the fields to non-static and give Game another parameter called finances that will only be created once.

I was going with the second approach for a while but I realized I was just passing Engine engine everywhere to have access to everything like engine.getGame().getFinances().getWaterBill().pay()

I feel like this is just like a global variable but more complicated. Here I am not hoping to code the best code with the best structure and all best practices. I am just looking to improve and learn in a fun way. Most articles I found just end "anyway if you end up with needing many singletons or globals your code probably smells". That did not help me find a solution.

\$\endgroup\$

closed as primarily opinion-based by Almo, Charanor, Kromster says support Monica, Anko, DMGregory Dec 6 '18 at 3:00

Many good questions generate some degree of opinion based on expert experience, but answers to this question will tend to be almost entirely based on opinions, rather than facts, references, or specific expertise. If this question can be reworded to fit the rules in the help center, please edit the question.

  • \$\begingroup\$ I don't understand the question. Your title suggest you want to avoid global classes and singletons, but then on the body you describe why you need such a class so you can access it from anywhere. Which one is it? In general having variables being accessible from anywhere asks for trouble, are you asking for advice on not using them? \$\endgroup\$ – TomTsagk Dec 4 '18 at 14:46
  • \$\begingroup\$ The title is the question : should I try to avoid and how. The body describes the context and explains my level of knowledge and research so far. The body also explains why I am struggling and why I think I need global to simplify my design a lot. I think I need a nudge in the right direction if someone feels I am going in the wrong one, something more precise than : yea redesign your code! \$\endgroup\$ – Ram Dec 4 '18 at 15:04
  • 3
    \$\begingroup\$ This is somewhat of an area of controversy in programming generally, and gamedev specifically. Some teams throw singletons around willy-nilly, some begrudgingly accept that a few globals/singletons are a big help or centralize around something like a global service locator, some swear off of globals entirely and stick to patterns like dependency injection instead. So you might not find an objective "correct" answer to this — it may be a matter of chosing a strategy that works for your project and your team's preferred working style. \$\endgroup\$ – DMGregory Dec 4 '18 at 15:06
1
\$\begingroup\$

Usually it's a good practise to avoid global variables/classes. The reason being, once you have a big enough project, and suddenly one global variable suddenly has a value that you didn't expect, how would you know who caused that? What if that result was caused from multiple places? It makes a big spaghetti mess.

There are ways to organise your code to avoid this, my favourite being Object-Oriented programming, where (in an ideal scenario) every object has access only to the data it needs to change and no more.

At the end of the day though, this is not a "black/white" thing, no answer is the best answer, and if you make a project full of singletons and global variables, but it works, does it really matter?

\$\endgroup\$
  • \$\begingroup\$ That is no way unique to global classes. Besides, it's not that hard to know who changed what if you have variable set through setter, decent logging and/or call stack reconstruction in place. \$\endgroup\$ – Kromster says support Monica Dec 4 '18 at 19:02
  • \$\begingroup\$ @Kromster Getters/Setters limit the visibility of data and create an interaction layer, similar to what object orientation describes, making things easier to control. Yes, what I describe is not unique to global classes, but it's one of their downside as well. \$\endgroup\$ – TomTsagk Dec 4 '18 at 19:15
0
\$\begingroup\$

all that i can say is that you can use if it works for your project, for example if you are using a singleton and works for your game and it has better performance than to have many instances of that then i consider is ok, i suggest you to start implementing patterns where needed, i have an engine too and i have a Game class where i have the main loop/update there, i also have an util class where i have several methods to load resources ( pictures, sound, fonts, etc ), i have another class to process collisions and that is a singleton attached to the Game class so all levels can use the same instance to manage collisions. for controller i have another helper singleton class where i instantiate it, on game class and on each level depending if is a pause screen, menu or game play i just have different listeners for the same input, but at the end is the same class for all.

If you follow Java Best Practices then you will have a good project, try to follow the SOLID principle as well.

\$\endgroup\$
  • \$\begingroup\$ Your claim of "if you follow Java Best Practices then you will have a good project" over simplifies the development process of most real projects. There's no canonical set of best practices & even well regarded best practices may at times contradict themselves. \$\endgroup\$ – Pikalek Dec 4 '18 at 22:22

Not the answer you're looking for? Browse other questions tagged or ask your own question.