0

Unlike many libraries SDL and OpenGL are designed to provide global resources; you can access them at any time from any class. There are justifications for this: They are written in C, meant to be readily cross-platform and designed to be fast.

They are not object oriented though, and global state is supposed to be a Very Bad Idea normally. It adds dramatically to the number of inputs to every function in your code.

Let's say you're working in C++ or some other object oriented language with one of these libraries. You know what functionality you need. At that point isn't it a good idea to encapsulate what you need into X and Y classes and say "every time you need to work with this library, use X and Y"?

For example, with SDL, it seems like a good idea to have a class which calls SDL_Init in the constructor and cleans everything up in the destructor. This manager class only allows you to create windows and renderers while SDL is active.

A good cause for a singleton perhaps? I'd rather not. The Google Testing Blog gives a good example of a case against singletons: http://googletesting.blogspot.co.uk/2008/08/root-cause-of-singletons.html

So really my questions are 1) if encapsulating part of a library is a good idea or pure madness and 2) how to approach managing global resources without singletons.

EDIT: Paul K's answer here gives a really good, concise introduction to dependency injection, which removes the need for singletons. However it's still unclear how to deal with the state which is unfortunately made global by a library such as OpenGL or SDL. The extensive global state provided by these libraries can't easily be passed by reference unless it is collected together and managed by a wrapper class. Even once this is done the client can still use the library directly.

matt_rule
  • 121

2 Answers2

2

A good alternative to singletons is using Dependency Injection as described in Paul K's answer here. Create and initialise a class at the highest necessary scope, then pass it down by reference.

When dealing with existing globally accessible state/resources, my solution would be to: 1) Determine what parts of the global state are needed. 2) Encapsulate these into a set of wrapper classes. 3) Dependency Inject these classes.

AFAIK there isn't a way to prevent the client from accessing the resource directly.

matt_rule
  • 121
0

One of the things that's bothered me for a long time about the debate around the Singleton pattern is that almost no one looks at the original design pattern from GoF. They are talking about a shallow simplification of the pattern. I think this is pretty disrespectful to the authors of a book that's probably one of the most influential texts in software engineering ever. I highly recommend it as a primer for OO design.

What most people miss if that in the original text, if you look at the example code the Singleton definition is abstract. The idea is that you can create different versions of the actual Singleton object and use configuration to load the one you want at runtime. Does that sound familiar? It should because it's essentially a proto-DI in a very narrow scope.

The article you reference about attacks Singletons on the lines that they are global state. Shared state is problematic and globally available shared state even more so. You should absolutely avoid shared state as much as possible. I'm not convinced that it's always possible to avoid and if you need to share state, the Singleton pattern is strategy for encapsulating and managing that sharing of state. If you are using DI to inject shared state all over your program, you still have shared state. DI isn't a solution for avoiding shared state. It's a solution for avoiding coupling and if you build the Singleton as described in the GoF patterns, it also avoids coupling.

JimmyJames supports Canada
  • 30,578
  • 3
  • 59
  • 108