I’m aware of many of them. Usually those don’t refer to system-wide resources situations.
Most of such papers/blogs/etc refer to a high level system design.
For example, say you have this code:
void doSomething(Object& object)
{
object.doSomething();
GlobalLogger::log(object);
}
This code has side effects, as it interacts with system resources.
You could pass the logger of course:
void doSomething(Object& object, Logger& logger);
But it would still be a bit difficult to unit test the logging bit, as the logger itself writes to some global system memory outside of the program.
What is usually recommended to do is to instead not pass the logger, and do something like:
std::string doSomething(Object& object)
{
object.doSomething();
return object.toString();
}
//On use:
GlobalLogger::log(doSomething(object));
This gives you a fully unit testable code with no side effects other than the object you passed in. The singleton is only used to interact with the system resource.
I believe most blogs, etc, would also recommend this - and would not recommend passing the entire global system resources like allocators, logs, threads, for each function.
Can you show an example from any language or framework where doing things like message thread or logging is not done with singletons?
Just for reference - in languages like Javascript, when you use async or await, there’s an invisible global message thread object… It’s extremely difficult to implement otherwise in a way that’s usable.