I have a lot of big singleton objects in my project because I’m 100% sure that I need only one of those, they look like this
object Renderer {
//Tons of vars
//Tons of functions
}
//Main screen of the game, contains the player, all the entities etc...
object IngameScreen {
//Tons of vars
//Tons of functions
}
Is it a bad idea to have vars in an object like i did above ? It seems to work fine, for now at least
It can be problematic if this shared state is mutated concurrently. You’d have to use synchronization which can be inefficient and error prone then.
I would try to use as much immutable data structures as possible. An idea to mange global state is to use the Redux Architecture (known from React).
It is almost always a bad idea to store vars in object. It is called global shared mutable state and it should be avoided always, especially if you have some kind of concurrency in your program. You probably need to change the design to avoid it.
1 Like
Moreover “accumulate and fire” is a well known antipattern.
See DI (Dependency Injection patern) and more common IoC (Inversion of Control principle). At least some of your classes you don’t need to save in memory all the time and this is the only first reason. Also see dagger2 | toothpick | koin framworks. They’re help you to manage your dependencies. Singletones (objects in kotlin are singletones) with tons of stuff known as bad design for implementing IoC. You always can use your common classes with sigletone container (maybe with lazy initialization) but you need to follow single responcibility principle. So you always have many classes, not 1-2 big classes with tons of stuff. You produce some kind of dependency tree in your common sigletons and it’s hard to manage their initialization and lifetime. Also you have troubles with mocking them and testing.
What we can do? For implementing IoC principle we have three patterns - Dependency Injection, Fabric Method and Service Locator. The only DI actual framework is Dagger2. It’s industrial standard and it’s recommended for large teams (huge amount of boilerplate code, compile-time verification and so on, but it works exactly the best way for actually large teams).
Fabric Method (Like Renderer.get() or in your case is Renderer as an object itself) is the building your common classes tree by hands - you make some kind of your singletone container with methods wich produce your little single-responsible classes tree and store it, or dispose some parts of this tree when nobody don’t use them (for example you can use link-counting). For example renderer parts responsible for different, i dont know, figures, like circles or triangles, game entities, and canvas or surface (their own dependencies is hardcoded inside singleton and not visible for user classes, and the tree always builded by singleton). This way you get something what hard to support, test and also contains large amount of boilerplate code. But for small amount of small classes it’s ok.
And finally for individual development or small teams recommended the third way - Service Locator pattern which implemeted in many frameworks. Most popular are toothpick and koin. I prefer koin, btw, it provides nice dsl for module description. Service Locators as a rule have small amount of boilerplate code, simple injection, but they haven’t compile-time validation. If you forget to add some dependency in module - you get runtime exception.
It’s very big part of theory, i just touch some random top-level points, i hope it will give you a vector to organize your common code right and nice way.