Hey! I've some C++ experience (less than one year, still learning a lot) but just began studying gamedev; I've just finished SFML Game Development book book as my first contact with the subject. I'm trying to write simple 2D games on my own (Tetris, Arkanoid, long list of 2D clones with increasing complexity here etc) following the book approach, but I'm wondering if there is an alternative implementation, because the book's code very different from what I've learned in other programming books (e.g. Martin's Clean Code).
For example, there's large parameters lists (which Uncle Bob advises against); sometimes the parameters are not really used by the class, they're just passed-by-reference/pointer to another class, which pass it to another class, which pass it... and so on, until reaching some class that really uses it. At some point the book creates a `struct Context`, which is a simple wrapper around all those many parameters. Example:
Application(): initializer list with 11 members, which calls State(Context) // Application stores a FontHolder and a lot of other stuff; let's see which class uses the font
Context(): initializer list with 8 members, which is used by // Context have a pointer to FontHolder
// suppose that we are in the GameState
GameState(): initializer list with 3 members, which calls // GameState have a Context member, which passes FontHolder to World
World(): initializer list with 18 members, which calls // World passes FontHolder to Aircraft()
Aircraft(): initializer list with 20 members, which calls // Aircraft passes FontHolder to TextNode
TextNode(): initializer list list with 2 members, which uses the font
IMHO this long constructor lists are aesthetically ugly and smells like a big heavy monolithic class. However, being myself a beginner, I'm not sure if there's a stardard alternative.
On one hand, I feel like it would be logical to instantiate a single TextureHolder on Application, so that we don't have one TextureHolder to load menu buttons on MenuState, another TextureHolder to load aircraft textures on GameState (I think that we would be wasting memory with so many std::maps* and speed with constant calls to load) etc; on the other hand, instantiate a TextureHolder on Application impose the burden of passing it through many (already long) initializer lists until finding some class that really uses it.
* I didn't understand why use a std::map instead of std::unordered_map, but whatever.
In FontHolder example, I would like to have something like:
class FontUser
{
sf::Text text;
text.setFont(fontHolder.get(fontId)); // how can fontHolder be accessible here without passing through all that constructors above?
text.setString("someText");
}
My only idea was to create a singleton, but I've read here that they're bad and one alternative is "to simply pass the object you need as an argument to the functions that need it", but perhaps the author of this site didn't have a 20 argument list in mind.
I've read this, which ressonate what I'm feeling, but I don't know how to redesign.
QuoteThat said, chances are, if you're dealing with an argument list that long in your constructor, that your object is too big and does too much, as is.
QuoteAgain, this is a personal-preference thing, and there are exceptions far and wide, but if you're passing 20 things into an object, chances are good that you could find a way to make that object do less, by making smaller objects.
TL;DR: Beginner in GameDev struggling in redesigning giant class with long parameter lists and many dependencies. Reading a gamedev book that is confusing me and (I think so, at least) conflicting with other programming books that I've read. For example, I don't know how to pass a ResourceHolder to classes that use it without singletons or huge parameter lists.
Thanks!
P.S.: Sorry for any grammar mistakes, english is not my native language x_x