Singletons


It is well known that singletons don’t work very well when you want to test your code. However, conceptually they just make a lot of sense sometimes.

One great example of that is UIDevice.currentDevice(). Even if you are against singletons it may be hard to explain to your coworker why this should not be a singleton. It is just one current device in the end, isn’t it?

Example

Let’s say you are working on application where user is required to register first. This is a bit tedious flow with multiple steps. Your application communicates with backend on each step to inform it where user is and to act accordingly. You are required to send device information in every request. Backend verifies that information match for all requests in the same session. UIDevice.currentDevice() has all we need so let’s use that to implement our flow.

You are now done with register flow and you want to write some UI tests. You have written some tests for registration flow and now you should test you main app. But you don’t want to register before each test because it takes long time. So you register with your script and pass username and password to your application. Now you have a problem. In your script, you have probably fixed device info, and your app uses UIDevice.currentDevice() to get information. Backend won’t allow this.

What to do

There are probably some weird ways to workaround this, but if you had UIDevice.currentDevice() spread across the objects, it won’t be simple fix.

Way to design this is to declare explicit dependency on UIDevice in objects which are using that singleton. I think best way to do this is to have it required in initialiser, but having it as property may be fine as well. In this way you should be able to inject whatever you want when you are in testing mode.

Conclusion

There are also drawbacks, with all of object dependencies explicit, our initialisers become too long. If this happens, we should probably then think about decoupling that object because it is probably doing more then it should anyway.

So my current rule is no singletons at all, because they just made my life much harder a lot of times.