I've seen two great videos (this and this) about dependency injection, law of demeter and global states (Singletons are considered as global).
I think I got the basic idea but I already have some singleton classes in my library. However if I want a testable and "well-designed" or "less coupled" code, I should use the DI and the LoD. This of course means that Singletons (as a design pattern) are evil because the caller does not now the implementation and any dependency on a global thing is bad, at least from a testing perspective.
More specifically I'm building a simple game engine without using any bigger 3rd party libs. This means I have to work with platform-specific and low level code as well.
Let's be more concrete. I have a Math section in my library where I have a class Vector2. It should be able to "throw assert" when invalid data is entered for one of its function. Or should be able to log it as an error. Or both. Until this time I've simply used a Singleton<Logger>
so I was able to access it everywhere.
But I agree, these things should not be used and DI solves these issues. Eg. what if the logger is not initialized yet? What if I want a dummy logger for tests? And so on... What do you recommend for these cases (like the Logger and Assert classes)?
Also the LoD says that I should not use accessors for objects (like getObjectA()->getObjectB()->doSomething()
). Instead, pass them as a parameter to the function/constructor. It's okay that it makes everything easier to test (and debug), but it can be painful to skip these functions.
Consider an example from the Unity engine. A GameObject has a method for getting a component from that object. Eg. if I want to manually transform my object I have no choice to call the "object getter", something like this:
this.GetComponent<Transform>().SetPosition(...);
This is against the LoD, isn't it?