
Pierre-Jules Tremblay wrote:
On Jan 17, 2008 2:15 AM, Johan Nilsson <r.johan.nilsson@gmail.com> wrote:
Did you notice that it is possible to use multiple inheritance? This way you can implement and test your domain-specific logic as a "normal" class, and then just expose a singleton of that specific type using e.g. boost::singleton<>.
Yes, it makes it possible to test the class to be wrapped as a singleton. That's the easy part. The hard part is to make the singleton's client code testable.
If I have a singleton class A that wraps a "regular" class B, I can test B independently of A. However, I have no way to test any code that calls A::instance to get to B.
That's why you should use dependency injection instead of designing the client code to directly call A::instance(). Why does the client code need to know it is accessing a singleton, when all it wants is the domain-specific logic?
I agree and advocate for dependency injection myself. But your original comment was that somehow Tobias' singleton's multiple-inheritance support makes it possible to test the code. I'm saying it only enables you to test the class-to-be-used-as-a-singleton's code, not the client code.
Exactly. I never said that MI somehow magically enables you to test the client code. It can help, though.
Now you're saying the client code shouldn't depend on the class being used as a singleton.
Yes. The client code should depend on the "class-to-be-used-as-a-singleton". Example: class Foo {}; class FooSingleton : public Foo, public singleton<FooSingleton, ...> {}; Unit-test Foo as normal and make clients depend on Foo rather than FooSingleton. If you need to use e.g. "lease", design an adapter interface or concept (depending on whether you want to use dynamic or static polymorphism) that mirrors that behaviour and make clients depend on that instead.
I agree, but Tobias' design doesn't make that use case possible,
I wouldn't say that the particular use case is impossible, possibly awkward. See above.
so what are you suggesting (in the context of this particular review)?
This is getting off-topic I think, so I won't disturb the review by further comments on testability. I guess that what I'm saying is that code that uses singletons are testable, even without the "settable singleton" variety, as long as one carefully designs the client code not to directly access the singleton; i.e. don't call singleton::instance(). Note that when using static polymorphism you could even allow clients to directly call singleton::instance(), as long as singletons' type is a template parameter for the client. / Johan