4

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!

  • 1
    What 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 May 10 '16 at 13:24
  • Maybe it belongs to codereview? I don't know – ochurlaud May 10 '16 at 13:25
  • 2
    Dependency Injection – CodesInChaos May 10 '16 at 14:19
  • 1
    I 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 May 10 '16 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 May 10 '16 at 22:19
3

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.