Singleton and template Error (C++)

Started by
12 comments, last by SeanMiddleditch 8 years, 6 months ago

Down that path lies passing 60 parameters to constructors and grotesque contortions just to avoid using a global here and there. All of your code because harder to read, harder to understand, and harder to maintain.

You're comparing using global variables, to... writing terrible, terrible code....

How about you don't use globals, and *gasp*, also don't write terrible code? tongue.png

Your OS syscalls are, for all intents and purposes, services/singletons.

And they provide a service to the EXE as a whole / their mutable state is owned by the EXE as a whole, so they don't have a choice but to be global (to the exe).

Development services such as a logger can argued to fit into the same category, so can get away with using global state.
Almost everything in a game code-base, does not fit into that category... and no, the alternative is not grotesque contortions and passing 60 parameters everywhere...

I am seriously tired of dealing with the cognitive overhead of dependency injection frameworks

I've also seen some pretty terrible global service locator frameworks. The problem there is bloated frameworks and bad "architects" tongue.png

Advertisement

I have to agree with Sean here, I am seriously tired of dealing with the cognitive overhead of dependency injection frameworks that have me forced to pass the same damn object around everywhere because it's sufficiently basic and low-level that everything needs it, and at the end of the day it's still a global because everything everywhere has a reference to the exact same object. Things are just as bad as with a global, except now I have a dependency injection framework with it and my code's simple logic is obscured by a weird meta-language to describe its relationship with other simple dependencies (parameter-passing in constructors/factories, annotations, XML dependency trees; pick your poison). I do not see a problem with having genuine services as long as their interface is sane, nor am I against explicitly codifying abstract dependencies when it makes sense and adds value. I have a brain and my colleagues do as well, and at work I find that most of it is being used working with against "modern" design patterns and contorting straightforward code to fit someone else's idea of "decoupled code" instead of actually implementing business logic, and probably producing far more bugs as a result. As everything else in life, design principles become bad and dangerous when taken in excess. If in doubt, stop and think.

Anyway frob I found it interesting that you used the word "generally" followed by an unconditional statement. What in your opinion would be an uncommon use case where a singleton or service locator would be a sensible design choice?

Completely agree.


Error 2 error LNK1120: 1 unresolved externals E:\WORK\InLine2D\InLine2D\Debug\InLine2D.exe 1 1 InLine2D

Anyway, back to the OP's question.

Whenever you're trying to do something in C++, it's always a good idea to look to see how the standard C++ already does it, because there have been a lot of expert input into the design and implementation of the standard C++ library.

In the standard C++ library, there is a global console logging object with a set of overloaded and templatized functions for inserting into it. In fact, you're trying to create a similar Java-style singleton class to wrap the standard object that already does exactly what you need, except not in the style a Java develop mey be accustomed to, with static member functions returning object instances that are used to invoke instanced functions with overloaded procedures for combining formatting and streaming functions.

In the C++ standard library you will find a set of global logging stream objects that are designed to be instantiated on first use: std::cout, std::cerr, and std::clog. They have an accompanying suite of overloaded and templatized functions (operator<<()) that perform manipulation and insertion into those logging streams. They have already solved your problems, consider using them instead of wrapping them in your own problematic code, or at least examine their design and emulate it yourself.

The C++ standard library logging objects are designed to be extended not only by overloading operator<<() for your own types but by replacing their streambuf to give you control over things like final destination or setting categories and severities. Notice the post linked to there was addressing pretty much exactly the same topic as this one, and is dated 2006. The aswer is still completely valid over a decade later.

Stephen M. Webb
Professional Free Software Developer

I've also seen some pretty terrible global service locator frameworks. The problem there is bloated frameworks and bad "architects"


True. Very true. smile.png

Sean Middleditch – Game Systems Engineer – Join my team!

This topic is closed to new replies.

Advertisement