• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
Krohm

Getting the rid of managers

14 posts in this topic

Thank you very much Gamedev for providing me food for thought. This is a follow-up on [url="http://www.gamedev.net/topic/613027-question-about-managers/"]Questions about managers[/url] to avoid hijacking the thread.

It's a real shame, but I do have a few managers. I tried to not call them that way, but I couldn't figure out anything so I just gave them a quick name and carried on. I sometime split them with "moderate" success but they resist in existing. I am really ashamed to say but they are truly ugly! Not only they are "some sort of managers" but they don't even got a nice design.

Pearl number 1: [font="Courier New"]ImageManager[/font]. This resisted because I'm lazy and I don't want to check out the file again. I suppose I might change it tomorrow to [font="Courier New"]ImageLoader[/font]. This is not so bad after all. Only thing it does: reference-count image loads.

Pearl number 2: [font="Courier New"]BasicManager : protected CallMapper, protected base::ImageManager[/font].
[source='cpp']/*! The "basic" manager deals with "basic" resources. ...*/[/source]If I look back, I cannot recall what taken me there... this thing does pretty much nothing but manage "waves"... which are probably what you're thinking about right now. There is some processing involved. There's quite a bit of interaction between this thing and the scripting systems as well as shader management. I therefore suppose [font="Courier New"]Wave[i]Something[/i] [/font]could be a better name (I'd probably also make it a component instead).


Pearl number 3:[font="Courier New"] AdvancedManager : protected BasicManager, protected FlexMaterialManagerInterface[/font]
This was really big some time ago so I split out a [font="Courier New"]GameWorldSystem [/font]class. I'm fairly happy with the GWS class, it seems it has its right to exist. Tomorrow I will rename [font="'Courier New"]FlexMaterialManagerInterface [/font]to [font="'Courier New"]FlexMaterialLoaderInterface[/font].
What does this manager do? It loads "more advanced resources". Very informative.
This has quite a lot of interactions with the scripting subsystems, the management is not always trivial as I'd like to. I expect to need more logic here in the near future (so it will be even less trivial) the requirements of this future expansion are not quite clear yet. So far I've been leaving it as is waiting for more focused semantics to rise from the thing.

Since I'll need to touch this last one "soon" I guess it's a good time to begin thinking at it. Suggestions are welcome.
0

Share this post


Link to post
Share on other sites
[quote name='Krohm' timestamp='1319219965' post='4875096']It's a real shame, but I do have a few managers. I tried to not call them that way, but I couldn't figure out anything so I just gave them a quick name and carried on. I sometime split them with "moderate" success but they resist in existing. I am really ashamed to say but they are truly ugly! Not only they are "some sort of managers" but they don't even got a nice design.[/quote]
As in the other thread, a class that manages stuff isn't a bad thing. It can be a good thing. The issue is when you try to turn it into a singleton.

[quote]Pearl number 1: [font="Courier New"]ImageManager[/font]. This resisted because I'm lazy and I don't want to check out the file again. I suppose I might change it tomorrow to [font="Courier New"]ImageLoader[/font]. This is not so bad after all. Only thing it does: reference-count image loads.[/quote]

Great, it does one thing, you can create as many as you want even if you only happen to need one.

[quote]
Pearl number 2: [font="Courier New"]BasicManager : protected CallMapper, protected base::ImageManager[/font]. /*! The "basic" manager deals with "basic" resources. ...*/
If I look back, I cannot recall what taken me there... this thing does pretty much nothing but manage "waves"... which are probably what you're thinking about right now. There is some processing involved. There's quite a bit of interaction between this thing and the scripting systems as well as shader management. I therefore suppose [font="Courier New"]Wave[i]Something[/i] [/font]could be a better name (I'd probably also make it a component instead).
[/quote]
Yes, it does not do one task. It does multiple ambiguous tasks.

Is it a custom container for images? Is it a custom container for wave objects? Does it coordinate the the availability of resources?

Define what the thing actually does (without the word manage) and it should help. If you cannot, it is possible that you have given it too many responsibilities. Break it up into smaller individual tasks.

[quote]
Pearl number 3:[font="Courier New"] AdvancedManager : protected BasicManager, protected FlexMaterialManagerInterface[/font]
This was really big some time ago so I split out a [font="Courier New"]GameWorldSystem [/font]class. I'm fairly happy with the GWS class, it seems it has its right to exist.
[/quote]
Seems like a renamed version of other stuff.

There is often a simulator class, and it contains instances of lots of pieces that make up the simulator. Sounds like your own re-discovery of this.

[quote]
Tomorrow I will rename [font="Courier New"]FlexMaterialManagerInterface [/font]to [font="Courier New"]FlexMaterialLoaderInterface[/font].
What does this manager do? It loads "more advanced resources". Very informative.[/quote] Why can't your other resource manager handle this?

The tasks of pre-loading, loading, caching, unloading, and otherwise getting blobs of data into and out of your game is a very common task. It is very frequently implemented as a factory method that works with your own serializers and deserializers.

It does not really matter the type of object if you use a factory. You want to load an animation named foo. You want to load an audio clip named baz. You want to load a model asset named bar. You want to load a UI element, or shader, or whatever else. All of them do exactly the same thing: possibly precache, load, potentially cache or share, and unload.

Any "more advanced resource" is still just a resource, isn't it?

[quote]
This has quite a lot of interactions with the scripting subsystems, the management is not always trivial as I'd like to. I expect to need more logic here in the near future (so it will be even less trivial) the requirements of this future expansion are not quite clear yet. So far I've been leaving it as is waiting for more focused semantics to rise from the thing.[/quote]

What is a script in your system?

Often a scripting system can be implemented very simply as a state machine.

The script writers get a very basic state machine. There are nodes and transitions. That's it.

Each node can call functions and use data that you expose in your source code or data. It does the thing. Then when whatever condition is specified in the transitions are satisfied, that transition is followed and the machine moves to the next state.

It can be extremely easy to implement, and insanely powerful for script writers who want to invent new ways to break the game.
2

Share this post


Link to post
Share on other sites
You go straight to the point here![quote name='frob' timestamp='1319226493' post='4875147']As in the other thread, a class that manages stuff isn't a bad thing. It can be a good thing. The issue is when you try to turn it into a singleton.[/quote]I think I've got this. Problem is this IS a singleton. I use hashes a lot, the system probably won't run correctly if more than one of those is loaded (it will just load up stuff multiple times).

[quote]W1) Is it a custom container for images? W2) Is it a custom container for wave objects? W3) Does it coordinate the the availability of resources?[/quote]W1) No, I used inheritance just because it cut some corners here and there, and I was too lazy to route the calls to a nested object. There indeed was some sense in this choice, ideally those objects would all make up a big "execution environment" providing all the features. Of course that's the same thing by composition... I will look at the code next week and re-factor.
W2) It has some logic involving 'ticking' the waves each time step. Originally, that was not even planned to exist, I was just performing some cleanup and I pulled it out of a bigger class.
W3) No, an external component does.

Although what this does is pretty clear, my main problem with that is finding a name which is short and descriptive. Mainly jargon.
I'm not quite sure I can split it again as it's like 300 LOC.

[quote]Seems like a renamed version of other stuff.

There is often a simulator class, and it contains instances of lots of pieces that make up the simulator. Sounds like your own re-discovery of this.[/quote]I don't quite get the point here. Yes, it's just another "piece of something"... so? And what is this "discovery" thing you're referring to?

[quote]IM1) Why can't your other resource manager handle this?
IM2 The tasks of pre-loading, loading, caching, unloading, and otherwise getting blobs of data into and out of your game is a very common task. It is very frequently implemented as a factory method that works with your own serializers and deserializers.
IM3) Any "more advanced resource" is still just a resource, isn't it?[/quote]IM1) It was originally part of other managers. It has been pulled out to support some external utilities involving material mangling (mainly the filters).
IM2) Problem was that some resources are terribly complex. I had one whose factory method took about 12 parameters. I initially just grouped those parameters in more logical matters - one of those turned out to be the [font="Courier New"]FlexMaterialLoaderInterface [/font]- I eventually got this down to 4, then figured out that those things could have been useful in a broader topic. They were originally intended to be temporary duct tape but they have been there for a while.
IM3) Yes of course but I don't think I am well aware of what I should do. Perhaps I'm just stuck in the drawn picture. Those objects provide the factory methods. The need to link them together arisen by the interactions of the 'advanced' resources with regards to the basic ones. It's mostly historical and somewhat redundant now that scripting is more pervasive. Yes, I will think at this.

[quote]S1) What is a script in your system?
S2) Often a scripting system can be implemented very simply as a state machine.[/quote]There was a state machine based script system in the beginning. There also was another scripting system (I'd likely not elaborate on that, unless it's absolutely necessary). I eventually got mad at the two things and melted them together. Think at a dumb version of UnrealScript. I plan to go back to state-based systems a day but I will likely layer those on top of the current scripting.
0

Share this post


Link to post
Share on other sites
[size="2"]I have a very limited time in which to reply so I can only cover a small portion of your concerns.[/size]
[font="arial, verdana, tahoma, sans-serif"][size="2"]As I have said before, singletons and globals in general create security risks, though I am not speaking only from that standpoint but also from the design standpoint.[/size][/font]
[font="arial, verdana, tahoma, sans-serif"] [/font]
[font="arial, verdana, tahoma, sans-serif"][size="2"]So let’s assume singletons are not welcome, and you are wondering what you can do to make sure that no more than 1 instance of a class exists.[/size][/font][font="arial, verdana, tahoma, sans-serif"] [/font][font="arial, verdana, tahoma, sans-serif"][size="2"]Well I designed the in-house engine of a company long ago and I thought that it was common sense not to make 2 CGame instances. A CGame class would create a sound device and some other things that needed to be done only once.[/size][/font][font="arial, verdana, tahoma, sans-serif"][size="2"]However, one of my coworkers was a programmer, but not a [i]game[/i] programmer. For debug issues he was making a second game instance.[/size][/font]
[font="arial, verdana, tahoma, sans-serif"] [/font]
[font="arial, verdana, tahoma, sans-serif"][size="2"]To my amazement, my sound manager still worked as expected after having been initialized twice, but still this was not a logical course of action.[/size][/font][font="arial, verdana, tahoma, sans-serif"] [/font][font="arial, verdana, tahoma, sans-serif"][size="2"]So I finally added debug [b]only[/b] code that checked to see if a second CGame instance was made. That fixed the problem quite effectively, because most developers work in debug mode until near the end of the project.[/size][/font][font="arial, verdana, tahoma, sans-serif"] [/font][font="arial, verdana, tahoma, sans-serif"] [/font][font="arial, verdana, tahoma, sans-serif"][size="2"]So there [b]is[/b] a way to ensure that only one instance of your class is created, even without using a singleton, and without creating global variables that can be exploited on release. These global variable exist only in debug mode, so they act to both protected from incorrect behavior and doing so without creating security leaks in release mode.[/size][/font]
[size="2"]In my design, singletons are not needed for sound managers etc., because the CGame class, which must be created in order to use my engine, creates that pointer itself, and every state of the engine [/size]receives[size="2"] a pointer to the game class and can therefore reach the sound manager, or whatever other manager there needs to be.[/size]
[font="arial, verdana, tahoma, sans-serif"] [/font]
[font="arial, verdana, tahoma, sans-serif"] [/font]
[font="arial, verdana, tahoma, sans-serif"][size="2"]L. Spiro[/size][/font]
1

Share this post


Link to post
Share on other sites
[quote name='YogurtEmperor' timestamp='1319277790' post='4875301']

[font="arial, verdana, tahoma, sans-serif"][size="2"]So let’s assume singletons are not welcome, and you are wondering what you can do to make sure that no more than 1 instance of a class exists.[/size][/font][font="arial, verdana, tahoma, sans-serif"] [/font]
[size="2"][/quote][/size]
[size="2"]If you want to make sure that no more than 1 instance of a class exists, why not use a singleton? That's what they're meant for, after all. If singletons are "not welcome", but it's OK having classes that can only function properly when there's max one instance, then that's just hypocrisy.[/size]
[size="2"]
[/size]
0

Share this post


Link to post
Share on other sites
[quote name='patrrr' timestamp='1319279636' post='4875305']
[quote name='YogurtEmperor' timestamp='1319277790' post='4875301']
[font="arial, verdana, tahoma, sans-serif"][size="2"]So let’s assume singletons are not welcome, and you are wondering what you can do to make sure that no more than 1 instance of a class exists.[/size][/font][font="arial, verdana, tahoma, sans-serif"] [/font]
[size="2"][/quote][/size]
[size="2"]If you want to make sure that no more than 1 instance of a class exists, why not use a singleton? That's what they're meant for, after all. If singletons are "not welcome", but it's OK having classes that can only function properly when there's max one instance, then that's just hypocrisy.[/size]

[/quote]

Singletons are to be used for a case where there can only [i]be [/i]one instance of the class without causing erroneous or incorrect behaviour. It's not a catch-em-all insurance policy against having > 1 instances. Sure, it can be used that way, if you really want -- just like globals can be used for things that aren't truly needed globally.

It's just not a terrific idea to do so. Especially when it comes down to: "I [i]think [/i]there should never be need for two instances of this."
0

Share this post


Link to post
Share on other sites
Getting back to the GWS object, that is just fine. Many games will have a main simulator object and will work just fine with it. Your re-discovery is not an issue.


As for the singletons, the business world and TDD advocates naturally solve it by their basic philosophies. Many game developers get stuck in the emotional rut that there is only one game window shown on the screen at a time, therefore singleton.


Most well-designed games I've worked on don't have this issue.

Some experiments to help you:
One great trick to split screen and certain graphical effects is to run two different view windows at once. Can you run two windows? If not, why not? There is no physical reason why you cannot run multiple windows on the screen; that is exactly what it is made for. What about split screen within a single window? If not, why not? Your display area is normalized to a rectangle, why should it matter if the rectangle is only a portion of the physical screen? Why should you be restricted to a single rectangle instead of two or three or nine? The restriction is artificial and probably unnecessary.

One of the best in-house engines I worked with had two views on screen; one showed the regular game, the other was exactly the same view with alternate visualization: overdraw, physics objects, physics motion displays, and x-ray vision were the most useful to me. Any fundamatal reasons your game engine cannot do that? Why not?

Can you have one game instance run multiple simulations internally? If not, why not? It can make network play easier to debug since you can eliminate the difficulties of networking and simply hae direct IPC between the systems. You should be able to have a collection of game simulations all running currently (even if it is slow). Automted testing (either test scripts or stress tests) could start 30+ instances of the simulator and run them all at once.

Can you have multiple instances of your resource manager? If not, why not? When debugging and stress testing it is sometimes useful to have multiple instances. Sometimes it is useful to have one instance pulling from the main resource location and a second instance pulling from a debug resource location.


At home I use TDD so this isn't an issue because everything must be instanced rather than globals or singletons. One way to do this is have everything come from the game simulator. The simulator has clocks. The simulator has resource loaders. The simulator has everything neccesary to run the game. The simulator has an interface for display, but does not have a view (that is secondary to running the game). Now create and run two or more independant simulators.
1

Share this post


Link to post
Share on other sites
Well since we are discussing uses for managers as in when they are good. How about a manager that loads, starts, shuts down, and unloads dynamic libraries containing separate systems (graphics, network, etc)?

My code (ignore the name as core does have meaning inside the design for the whole program. I have removed includes as they are irrelevant to the discussion of managers.
[code]
// Preprocessor selection based on OS
#ifdef _WIN32
#include <Windows.h>
typedef HMODULE DLLHANDLE;
#else
#include <dlfcn.h>
typedef void* DLLHANDLE;
#endif

class CoreManager {
public:
CoreManager(GlobalProperties* gprops, MessageDispatcher* msgdisp);


void Startup(std::string name = "");
void Shutdown(std::string name = "");
void Load(std::string name);
void Unload(std::string name = "");

void Update(double dt = 0.0f);
private:
GlobalProperties* gprops;
MessageDispatcher* msgdisp;

std::map<std::string, CoreInterface*> coremap; // A mapping of each core to its given name
std::map<std::string, DLLHANDLE> libraries; // A mapping of each loaded library to a given filename
};
[/code]
[code]

CoreManager::CoreManager( GlobalProperties* gprops, MessageDispatcher* msgdisp ) : gprops(gprops), msgdisp(msgdisp)
{

}

void CoreManager::Startup(std::string name /*= ""*/ )
{
if (name == "") {
// We need to use the regular for loop as we may modify the iterators if a core fails to start
for (auto it = this->coremap.begin(); it != this->coremap.end(); ++it) {
if (!(*it).second->Startup()) {
//EventLogger::printToFile( 5,"Core failed to start removing.", 'C'); // TODO: Fix eventlogger
(*it).second->Shutdown();
delete (*it).second;
this->coremap.erase(it++);
if (it == this->coremap.end()) {
break;
}
}
}
this->msgdisp->SetCores(&this->coremap);
} else {
if (this->coremap.find(name) != this->coremap.end()) {
this->coremap[name]->Startup();
}
}
}

void CoreManager::Shutdown( std::string name /*= ""*/ )
{
if (name == "") {
// We need to use the regular for loop as we may modify the iterators if a core fails to start
for (auto it = this->coremap.begin(); it != this->coremap.end(); ++it) {
(*it).second->Shutdown();
delete (*it).second;
this->coremap.erase(it++);
}
} else {
if (this->coremap.find(name) != this->coremap.end()) {
this->coremap[name]->Shutdown();
delete this->coremap[name];
this->coremap.erase(name);
}
}
}

void CoreManager::Load( std::string name )
{
if (this->libraries.find(name) == this->libraries.end())
{
#ifdef _WIN32
wchar_t buf[256];
mbstowcs(buf, name.c_str(), name.length());
HMODULE libdll = LoadLibrary(buf);

this->libraries[name] = libdll;
#else
void * libdll = dlopen(fname.c_str(), RTLD_LAZY);
this->libraries[name] = libdll;
#endif
}

CoreFactory fact;
#ifdef _WIN32
fact = (CoreFactory)GetProcAddress(this->libraries[name], "CoreFactory");
#else
fact = (CoreFactory)dlsym(this->libraries[name], "CoreFactory");
#endif

CoreInterface* core = fact(this->gprops, this->msgdisp->GetCallback());
this->coremap[name] = core;
}

void CoreManager::Unload( std::string name /*= ""*/ )
{

bool ret = false;

if (this->libraries.find(name) != this->libraries.end())
{
Shutdown(name);
#ifdef _WIN32
if (FreeLibrary(this->libraries[name]) != 0)
{
ret = true;
}
#else
ret = dlclose(this->libraries[name]);
#endif
if (ret)
{
this->libraries.erase(this->libraries.find(name));
}
}
}

void CoreManager::Update( double dt /*= 0.0f*/ )
{
for (auto it = this->coremap.begin(); it != this->coremap.end(); ++it) {
(*it).second->Update(dt);
}
}
[/code]
0

Share this post


Link to post
[quote]In my design, singletons are not needed for sound managers etc., because the CGame class, which must be created in order to use my engine, creates that pointer itself, and every state of the engine receives a pointer to the game class and can therefore reach the sound manager, or whatever other manager there needs to be.[/quote]Thank you very much! It's exactly the same rationale I used to design mine! Everything is a part of the bigger core object. The object is instantiated using a global systemwide lock so no chance of double instantiation can happen. It's always good to know I'm kinda on a good path.

I begin being positive perhaps there's no real problem after all. Besides naming. I'd still want some suggestions for the WaveSomething... perhaps WavePooler would do ?_?

[quote]WM1) Can you run two windows? WM1A) If not, why not? There is no physical reason why you cannot run multiple windows on the screen; that is exactly what it is made for. WM2) What about split screen within a single window? WM2A) If not, why not? WM2B) Your display area is normalized to a rectangle, why should it matter if the rectangle is only a portion of the physical screen? WM2C) Why should you be restricted to a single rectangle instead of two or three or nine? The restriction is artificial and probably unnecessary.
...
WM3) One of the best in-house engines I worked with had two views on screen... Any fundamatal reasons your game engine cannot do that? Why not?


[/quote][b]WM1) No.[/b] The system was able to do that in very old versions.
[b]WM1A) It just collected dust [/b]with no apparent benefit. It was originally implemented as it was deemed useful WRT previous experience - it was a different field. As a side question - how's going with sharing renderers across multiple windows? As far as I recall direct3D9 is a bit quirky on that, for GL I am not sure but I think not (it's bound to the Device Context which is a per-window property). If this involves creating multiple renderers... that's going to be a big no. I think your statement is a generalization a bit too broad. I don't recall a single PS3 game I've played showing multiple windows per screen. I have also seen some games not only assuming a single window but also allowing a single resolution - I don't see this being a problem for me in the real world for the next years.
[b]WM2)[/b] [b]Not currently supported[/b]. Plan is to just expose an additional renderer control (it will likely be script-driven).
[b]WM2A)[/b] [b]Not necessary now[/b].
[b]WM2B)[/b] [b]I disagree[/b] with this. What is this normalized rectangle? How do you deal with it on 4:3? What on 16:10? What about stretching. No way. I work in physical inches, or perhaps pixels. If the user (script) wants to cut it in ratios, that's his/her choice. Design units are in pixels at 96dpi. The alternative, offset-scale normalized coords seems unnecessarily convoluted. Perhaps it's just me, but I didn't like the normalized coord approach at all in the past. I couldn't stand the stretching.
[b]WM2C)[/b]Of course when it is scripted there will be N (I don't care). This day is not now. I disagree with your statement; I don't quite see the connection with the original problem.
[b]WM3) Yes[/b], each day got only 24 hours, priorities and trade-offs will have to be made; I think that is a major fundamental reason.

[quote]Can you have one game instance run multiple simulations internally...The simulator has clocks. The simulator has resource loaders. The simulator has everything neccesary to run the game. The simulator has an interface for display, but does not have a view (that is secondary to running the game).[/quote]Yes, totally awesome and... what's the difference between my system and yours? And what's the deal of running it multiple times in the same process? Why not just ran them sequentially... in parallel chunks? It sounds like write about "accuracy" as a mathematician might write about: I don't see the point of having more than adeguate accuracy. I understand [b]nothing[/b] of what you're writing about. Please try to be more concise and [b]propose real world examples[/b] (excuse me, but I am not well aware of what you do).
I don't want to write an "engine"... I want to [b]get the job done[/b]. I will implement "nicely" whatever it takes to [b]get the job done[/b]. Everything else will wait. Long term investments will be considered... in a long term perspective. OP is NOT about a long term perspective it is about a simple solution to a problem I have. Now.
0

Share this post


Link to post
Share on other sites
[quote name='Krohm' timestamp='1319219965' post='4875096']
Pearl number 1: [font="Courier New"]ImageManager[/font]. This resisted because I'm lazy and I don't want to check out the file again. I suppose I might change it tomorrow to [font="Courier New"]ImageLoader[/font]. This is not so bad after all. Only thing it does: reference-count image loads.
[/quote]
Sounds like an ImageCache.

I'll suggest to extract the construction of resources away from these classes. Then you have ImageCollection / ImageCache, BasicImageLoader and AdvancedImageLoader. Or maybe just free functions for construction of resources. Or, If the construction is complex process, you could try builder pattern where you can pass short lived builder objects around that can retain the state until the result is finished. These builders can even be polymorphic.

A lot of times people subclass just to be able to add different constructor, while the public interface of the end result remains the same.
0

Share this post


Link to post
Share on other sites
The actual construction is in a derived class.
Nonetheless, I might want to figure out something else in the future, I will think at this.
0

Share this post


Link to post
Share on other sites
When I read the title of this thread a jolt of enthusiastic excitement went through me ... until I realized that you're talking about a programming issue.
2

Share this post


Link to post
Share on other sites
[quote name='DarklyDreaming' timestamp='1319283749' post='4875312']
Singletons are to be used for a case where there can only [i]be [/i]one instance of the class without causing erroneous or incorrect behaviour. It's not a catch-em-all insurance policy against having > 1 instances. Sure, it can be used that way, if you really want -- just like globals can be used for things that aren't truly needed globally.

It's just not a terrific idea to do so. Especially when it comes down to: "I [i]think [/i]there should never be need for two instances of this."
[/quote]

Exactly, and if the implementation of a class relies on side-effects or some kind of global state which makes it not safe to instantiate more than once, why not make it a singleton? Then you're at least honest with your limitations. Note: I'm not saying you should make such a class.


[font=arial, verdana, tahoma, sans-serif][size=2][quote name='Krohm' timestamp='1319395719' post='4876028']
The object is instantiated using a global systemwide lock so no chance of double instantiation can happen.
[/quote]

So this means that for all intents and purposes, it is a singleton, but enforced externally? I might even argue that is worse.[/size][/font]
Singletons are crappy, but sometimes they are needed, and sometimes they minimize incorrect usage of a class. Substituting a singleton with something else that enforces oneness just ignores the underlying issue.
0

Share this post


Link to post
Share on other sites
[quote name='patrrr' timestamp='1319797231' post='4877829'][quote name='Krohm' timestamp='1319395719' post='4876028']The object is instantiated using a global systemwide lock so no chance of double instantiation can happen. [/quote]So this means that for all intents and purposes, it is a singleton, but enforced externally? I might even argue that is worse.Singletons are crappy, but sometimes they are needed, and sometimes they minimize incorrect usage of a class. Substituting a singleton with something else that enforces oneness just ignores the underlying issue.[/quote]
Not at all.

There are many system-wide unique resources. There are global mutexes and semaphores. There are individually named files on the file system. There is volatile information about larger systems such as machine state.

Locally constrained uniqueness is often enough for small programs that need it, but they are not everything. At the smallest end of the scale you have interlocked memory and IPC communication methods. Externally contstrained uniqueness is absolutely critically on larger systems that span networks, such as resources controlled by remote databases.

Just consider the classic problems of simultaneous updates, such as the computer science problem with two travel agents booking reservations simultaneously, have need of strong external uniqueness constraints.

There are very solid, established, and proven uses for such things. Enforcing uniqueness locally and globally is an extremely important design requirement for many programming problems.


The problem is not simply using it; there are many times when it is not just a good design but instead absolutely essential to proper function. The problem comes from using it unnecessarily.


The real questions to ask are:
(1) Does the problem require enforced uniqueness?
(2) If it is required, does the proposed solution adequately enforce it?

Very few problems require it.

Most of the time it is a non-issue. Don't write code that depends on uniqueness. Data driven designs, component based systems, and thinking with reuse in mind solve this in most cases.

But if it is needed, it is absolutely essential. For every problem you need to discover the necessary scope.

For example, your enforcement may be a single block of shared memory. It may be a single instance of a class within a single app. It may be a single instance of a service on a single OS instance. It may be a single item on a physical machine regardless of virtualization. It may be a mandatory pessimistic lock on a database record that needs to propagate across a server cluster.

Don't use it when it isn't required. But if a system does require it you better know the available tools so you choose the right one for the job.
1

Share this post


Link to post
Share on other sites
[quote name='patrrr' timestamp='1319279636' post='4875305']
[quote name='YogurtEmperor' timestamp='1319277790' post='4875301']
[font="arial, verdana, tahoma, sans-serif"][size="2"]So let’s assume singletons are not welcome, and you are wondering what you can do to make sure that no more than 1 instance of a class exists.[/size][/font][font="arial, verdana, tahoma, sans-serif"] [/font]
[size="2"][/quote][/size]
[size="2"]If you want to make sure that no more than 1 instance of a class exists, why not use a singleton? That's what they're meant for, after all. If singletons are "not welcome", but it's OK having classes that can only function properly when there's max one instance, then that's just hypocrisy.[/size][/quote]
I am a little late but-

No, I want CGame be instantiated only once, not to be instantiated only once [b]and[/b] be global in scope.

My engine will pass the game pointer to the 3 main objects that need it: Scene Manager, State Manager, and States themselves.

Access to the CGame class is restricted to these objects because these 3 objects are the highest-level objects under the CGame class, and they are the only ones that could possibly need to know about all the different systems running in the game (all of which can be accessed through CGame).


There is a design problem with using a singleton, but also one less subjective. If my engine relied on a singleton for the main game class, how would the users of my engine inherit from my CGame and make an instance of their own "CMyGame"?
If the user wants to make a singleton out of his or her own CMyGame, or just make an instance on the stack (preferred), that is his or her business. My engine makes no assumptions as to how the game class is stored; when something needs it it is passed as a parameter.

And the design issue is: How do you control which classes/modules have access to the CGame pointer?
So, you made this nifty system that uses singletons for the CGame. From the CGame you can access all other managers.
Now you have a small bit that just wants a sound manager. Well now he has to include the CGame file, and with that he must now link to the graphics library, the physics library, scene manager, etc.

Trying to avoid this by using a bunch of different singletons does not really improve your design. You still haven't restricted access from things that should not have access, so when your programmers get lazy they will just #include "SoundManSingleton.h" instead of just the components of the sound module they need. Inevitably, singletons lead to unnecessary relationships between classes.



I will take a system of constraint any day. I want to think logically about what every system needs and manually give it (and only it) to them. [i]That[/i] is organization.


L. Spiro
0

Share this post


Link to post
Share on other sites
[quote name='patrrr' timestamp='1319797231' post='4877829']
Exactly, and if the implementation of a class relies on side-effects or some kind of global state which makes it not safe to instantiate more than once, why not make it a singleton? Then you're at least honest with your limitations. Note: I'm not saying you should make such a class.
[/quote]

The singleton design pattern implies more than just that there be only one instance of the object.

[url="http://blogs.msdn.com/b/scottdensmore/archive/2004/05/25/140827.aspx"]http://blogs.msdn.co.../25/140827.aspx[/url]

Also to be noted, it should be the decision of the program, not the class to limit the creation of itself. If you want to limit the creation of certain objects you should make a factory class to handle that, not a singleton.

Also, I seriously question a single class that is not safe to instantiate more than once for anything important. It feels like a bit of a code smell. I could see it being useful in some cases, but if it is something that's coming up repeatedly I would be wary of it. See frob's first post for examples.
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0