Cocos2d-x architecture

Started by
4 comments, last by Ravyne 11 years, 7 months ago
If singletons are generally considered bad, then why is Cocos2d-x considered to be so good? I've been using Cocos2d-x and I like it. But I've noticed that there are lots of singleton classes.
Advertisement
Singletons are a design choice. There are many good reasons not to use them. There are also a few good reasons to use them, especially if they meet several well-established criteria.

It is a design tradeoff, and programmers must decide between these tradeoffs continually. Time vs space is one of the most common: you can store results in a cache or recompute.

They made design choices, and they seem to work for that library.
More to the point, Cocos2d-x had most of the choices made for them. Cocos2d-x is C++ port of the popular Objective-C library Cocos2D, which itself is a port of a Python based library of the same name.

To a certain degree, trying to emulate an existing API is going to greatly restrict your design choices.

Another thing to keep in mind, many of the biggest flaws with singletons apply to C++ only ( especially in regards to threading ).

Also, be careful when listening to people that say blanket statements like "don't ever use X". Things are so rarely this black and white. Design purists are often so quick to discount other factors like ease of use or ease of learning. While a singleton may have it's downsides, it is easy to implement and easy to grok, both important factors.
Serapth has a good answer, and I'd like to add that Singletons in C++ really have two cutting edges to them -- firstly are the implementation issues like threading, and secondly are the design issues it can promote. One of the design issues that you encounter with singletons is their global availability, which promotes poor separation of responsibilities and causes systems to become more tightly coupled (a bad thing), but simply having a singleton doesn't require you to break these design principles, you can still make good design decisions and face fewer of the consequences.

For people who are not informed enough about good design, or who are not responsible enough to hold themselves to good design over convenience, its usually better to forego the singleton so that bad decisions are not so easy to make.

In other languages, Singletons are not nearly so bad, or mean something else entirely (I've heard the term used in some languages to describe static classes).

You should *always* be wary of singletons in C++. You should *almost always* prefer other solutions in C++ when you have a choice. You should *never* give in to the convenient "solutions" that Singleton seems to provide in C++, because it nearly always goes directly against good design principles.

throw table_exception("(? ???)? ? ???");

Well what I was thinking is that it would be usefull for utility classes, like event managers. That way anything that implements the IEventListener can register in it's constructor, and unregister for events in it's destructor (as an example). And it wouldn't have to depend on other classes (like a GameManager or App class) to gain access to the event manager.
What if you want to have two event managers? You might think now that you would never want more than one, but subscribing to singleton locks you into an early decision, and by not passing in the event manager through a proper chain of command, you have no easy way to later say that some class of events uses one manager, and another class of events uses another. What you're really saying when you say "It's great that no one has to tell me what manager I can use" is "I don't want to have to think about who tells who what." -- That's basically shirking your responsibility as a programmer.

Another example -- The convenience argument has been used as a justification for error logging singletons. Proponents would say "Aha! Logging! I just need one, and I need unfettered access from anywhere!" Well, what if you do want just one, but you want a different one tomorrow? Or if you want a different one based on a user setting? Singleton complicates that kind of scenario, it'd be far easier to just instantiate one class or the other and pass it down the chain as needed.

Finally, with proper design, you shouldn't be passing in a million different parameters through a dozen-plus layers of code. It just doesn't happen with proper design. Good design passes only what's needed, just as far as needed -- usually a parameter or two, if any, through 2-3 layers. Anything more than that and you should worry that it's a code-smell. A singleton implementation never reveals this kind of smell, even though all of its ill effects are still there.

throw table_exception("(? ???)? ? ???");

This topic is closed to new replies.

Advertisement