Skip to main content
gamedev.net
🔒 Locked

On library interfaces

Started by _goat 2 replies 400+ views
Original Post
_goat
_goat
My design towards my graphics/other engines is naturally modular - I think best like that, I guess. However, I am a little unsure of my implementation, so I turn to you to critique :). I divided my things into three (at the moment) main "libraries":
  • A OS wrapper
  • A graphics API wrapper, which uses the OS wrapper
  • The actual graphics engine, which uses both of those
Now, entry into each of the libraries is via a Singleton (I realise stating this will resault in backlash). Each is contained in its own namespace, as are all the other related classes. So for example in the silk "library" (the API wrapper):
NOTE: silk is a macro:    #define silk ISilk::getSingleton()
 
ITexture * texture = silk.createTexture("dropship.jpg", ...);
The question is really this: Should I instead put the functions in the namespaces (above code would be in a .cpp file with namespace declared) for something like:
silk::createTexture(...);
The only thing is that ISilk and the other singleton classes store information - Silk for example stores textures and the number of references to them. Is there a better way of doing this?
Zipster
Zipster
I say keep the singletons, but internalize them to the libraries, and add the namespaced functions as a wrapper to the singletons and the entry to the libraries. This adds a degree of separation between you and the singleton so if you switch away from a singleton implementation, you don't have to go through your code and change every instance of silk.createTexture(...). Now the user doesn't even have to know about the details of an ISilk object or how it's created, and entry into the libraries isn't through a singleton so you won't get any backlash. This arrangement also allows you to add extra code that's called when the user attempts to make a call into the interface, either so you can do logging, benchmarking, whatever, without making it an explicit responsibility of the user of the API. I envision it like this:

// simplified examplenamespace silk{   ITexture* getTexture(const std::string& filename, ...)   {      log::report_call("getTexture");            return ISilk::getSingleton().getTexture(filename, ...);   }   // More functions here}


[Edited by - Zipster on November 1, 2005 2:33:53 AM]
_goat
_goat
Hmm, that's a possibility, but it'd require writing the same function at least three times (once for the entry point, once for ISilk, and once each for the classes that are derived from it, like CSilkDX and CSilkOGL). I suppose a better question would be: Do you think there are any serious design flaws here? Keeping in mind that the order of initialisation is actually set (via a setSingleton method).
Zipster
Zipster
I don't see anything seriously wrong with it, it's just my line of thinking that the modules should know as little about the implementation details of other modules as possible. That includes whether or not ISilk is a singleton, or whether or not it's even an object at all. The entry point function is really just a stub that calls the singleton function, nothing more than a handful of lines.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.