Re: StateFull vs Stateless Singleton
On 5 juuli, 21:06, James Kanze <james.ka...@gmail.com> wrote:
On Jul 5, 6:05 pm, =D6=F6 Tiib <oot...@hot.ee> wrote:
On 5 juuli, 17:38, James Kanze <james.ka...@gmail.com> wrote:
On Jul 5, 12:31 am, =D6=F6 Tiib <oot...@hot.ee> wrote:
Not sure why someone needs to have global state? Typical
example of singletons is a logger. Huh? So ... OK. What if
i need to have separate logs from different modules?
I will then need new class for each log to have separate
singleton logger for each module? Nonsense.
So your log manager is a singleton. Somewhere, there must
be a single bit of code which reads the configuration file
for the log.
I am not saying there may not be single instances of
something. I am saying that these should not be in some global
state,
It's not "global" state:-).
Ok, about hidden implementation details i do not usually complain.
Whatever is elegant to get interface contract fulfilled. If it is
singleton most fitting there then so be it.
[...]
Well, logging is a very special case.
Yes, logging is most valuable debugging/issue resolving tool.
Especially when there are difficulties to debug, like with some
embedded systems. I did bring it in because it is typical thing that i
have heard is a "natural singleton". Seems that we agree there,
natural interface for logging in C++ is a macro. Singletons interface
does not pull the weight. Singleton may be again some behind scenes
implementation detail.
What I hate is when singleton is sort of replacement for a global
variable. That is the cheat how that pattern is often abused.
As is the code which captures the command line and its options.
Command line is passed to main() and so main() passes it to
some singleton? Why it should be a singleton?
Because there can't be more than one command line. Options have
to register before main is called (from the constructor of
a static object), so you need something to handle the order of
initialization issues.
These are command line arguments for something that will be
further called by main(). Why there must be a global singleton
that holds its options?
Because no one component is interested in all of the options.
OK, may be it is reasonable. However such options may be passed to
component run-time as well? What is the difference if the source is
command line or some user command to change them later, run-time?
However that does not worry me, after all there are very few
things that directly depend on command line and that command
line does not likely change during program run.
Not once it has been parsed. But Option enroles with the
CommandLine class, so that it can correctly pick up options when
it parses the command line.
Ok, there is just one command line and pretending there may be several
is pointless when there are no other sources of options.
In a multithreaded application, the thread manager (which
ensures e.g. a clean shutdown) must be a singleton.
At the moment yes, application (or some framework that it
uses) has to orchestrate shutdown itself. Again, when i do not
get rid of single things then i do not like
"ShutDownManager::instance().doIt()". I prefer to have
shutDown() function. If nothing else then faking it for a unit
test is lot cheaper.
The main argument against this solution is that it doesn't work.
The task manager has to know about all of the tasks, so that it
can signal them in case of a shutdown request, then wait until
they've finished.
To expose something to a function is actually as hard as to expose it
to a class, isn't it? Ok, task manager. I do not still see why there
must be a class for it.
namespace taskmanager {
void shutDown(); // shortest thing to say.
// other operations with task manager.
}
It might be feels like C way of information hiding, but nameless
namespaces are exactly for that ... like i understand the standard.
Sure, it may be a class too.
(Thinking about it, this seems to be a common theme of
singletons. The have to know about all of the instances of
something else: threads, temporary files, etc.)
Yes. For example factories. I prefer factory functions when there are
limits so creation (or destruction, or reusage) of something should
not be made in usual ways. How a factory function achieves it is
implementation detail. It may use real singletons that are defined in
(nameless namespace in) translation unit that defines such factory
function.
Such design likely removes (or adds flexibility how to handle) the
issues that may be with construction/destruction order of singletons.
Namespace also naturally does not let any usual questions about
classes (like what if i copy or derive from or use as member or
delete) to be asked with straight face.
[...]
Yes. More generally, however, when single instances of data are
involved, I prefer to wrap in a class than in a namespace. Once
I've defined the class, no one else can get at the data.
I believe nameless namespace in a translation unit is deepest place
where single instance of data can be hidden with C++. It may be is my
allergic overreaction to widespread abuse of singletons, so i want to
put them as far from global as possible. ;-)