About the subject
I hesitated for a while between using singletons objects or plain static ones. After having read a lot of different opinions, I made mine:
If you don't need to prevent multiple creation of an object, don't use a singleton.
Therefore I used mostly static objects.
Context
My program is a complex scientific program. It must communicate with the outside world (using zmq), output some logs and time itself to be sure that everything is fine.
What I did
Logger
I dealt with the logs by creating/destroying the Logger object each time I need it. Static functions like
Logger::log() << "My Log";
construct the object, and at destruction (end of calling function) the log is output. And this is fine!
Zmq
Because it's needed everywhere in the code, the class implementing zmq cannot be owned by one object. I therefore access to a static object created above the main()
function.
Timers
Again my timers must be able to time over several functions and be printed all at once for easier diagnostics: same solution for me, a static TimerList
object containing all timers used.
The Question
Now that you know as much as I do about my project: is it a bad design?
What would you do instead? Singletons ? Something else?
Here is my main.cpp
bool READONLY;
// Must be started first to be deleted last.
zmq::context_t context(1);
zmq_ext::socket_t logSocket(context, ZMQ_PUB);
namespace TimingModule{
TimerList tm;
}
//Must be static so that exit() do a proper deletion.
static App app;
namespace Messenger {
Messenger messenger(context);
}
int main(int argc, char *argv[])
{
return app.run()
}
There is no exact answer because it's more set of advises and good practices: compiling the insightful comments would make a good answer. It helped a lot. Thanks!
-
1What makes me think that it's a bad design is that objects have now several calls that seems to come from somewhere unknown (not a method, not a member function...)ochurlaud– ochurlaud2016年05月10日 13:24:49 +00:00Commented May 10, 2016 at 13:24
-
Maybe it belongs to codereview? I don't knowochurlaud– ochurlaud2016年05月10日 13:25:11 +00:00Commented May 10, 2016 at 13:25
-
2Dependency InjectionCodesInChaos– CodesInChaos2016年05月10日 14:19:14 +00:00Commented May 10, 2016 at 14:19
-
1I can only guess what "server info" and "measure the time" means in your case. But if server info is mainly constant data then I'd initialize that first and I would only pass the data that each class needs when creating the classes that use the server info data. If ServerInfo changes a lot then I'd possibly have ServerInfo signal change events for the info of interest and have the other classes handle those events. For measure time, I don't know what you mean other than something like this, startTime = RTC.GetTime(); // do some stuff; endTime=RTC.GetTime(); totalTime=endTime-startTime;Dunk– Dunk2016年05月10日 22:06:38 +00:00Commented May 10, 2016 at 22:06
-
1"Would you do a singleton?". I have not used a true singleton in at least a decade. Once I learned how to do a decent OO design it became obvious that singletons are only needed for very rare special cases. Usually, the one and only instance is created at application startup and it is passed around to those who need it. That one instance doesn't get deleted until the app exits. No singleton implementation necessary. If that one instance gets created/deleted multiple times during the app life then singleton applies. I haven't run into needing that yet even after hundreds of thousands of SLOC.Dunk– Dunk2016年05月10日 22:19:29 +00:00Commented May 10, 2016 at 22:19
1 Answer 1
I wouldn't say you're using bad design. There is always a cost in coding--to win the most 'CS class' worthy / most object-oriented award isn't really what coding is about. Code is a tool, just like any other and like most tools--you invent uses for those tools as needed.
I find it easier myself to use a static class for 'utility' type stuff as you have here and then unstatic them. In essence you then just need to now keep track of when they're created, destroyed, and which one you're referencing instead of rebuilding a singleton class, which has a much different format. The way I tend to build my static classes are pretty similar to how I treat objects anyway, minus some of the bookkeeping--so it's more readily scaleable.
In short--if you didn't need to complicate your product and saved time with your solution, there's no problem at all with what you did. As you get more experienced you'll learn how to keep your code manageable so that if you do need to scale it and unstatic your classes, you already have built your template for how 1 works in a bubble.
There is no greater punishment, however, for having built a very unscalable solution and your boss tells you the next day to have it support x1000.