My app contains several singletons (following from this tutorial). I've noticed however, when the app crashes because of a singleton, it becomes nearly impossible to figure out where it came from. The app breakpoints at the main function giving an EXEC_BAD_ACCESS even though the problem lies in one of the Singleton objects. Is there a guide to how would I debug my singleton objects if they were problematic?
if you don't want to change your design (as recommended in my other post), then consider the usual debugging facilities: assertions, unit tests, zombie tests, memory tests (GuardMalloc, scribbling), etc. this should identify the vast majority of issues one would encounter.
of course, you will have some restrictions regarding what you can and cannot do - notably regarding what cannot be tested independently using unit tests.
as well, reproducibility may be more difficult in some contexts when/if you are dealing with a complex global state because you have created several enforced singletons. when the global state is quite large and complex - testing these types independently may not be fruitful in all cases since the bug may appear only in a complex global state found in your app (when 4 singletons interact in a specific manner). if you have isolated the issue to interactions of multiple singleton instances (e.g. MONAudioFileCache and MONVideoCache), placing these objects in a container class will allow you to introduce coupling, which will help diagnose this. although increasing coupling is normally considered a bad thing; this does't really increase coupling (it already exists as components of the global state) but simply concentrates existing global state dependencies -- you're really not increasing it as much as you are concentrating it when the state of these singletons affect other components of the mutable global state.
if you still insist on using singletons, these may help:
either make them thread safe or add some assertions to verify mutations happen only on the main thread (for example). too many people assume an object with atomic properties implies the object is thread safe. that is false.
encapsulate your data better, particularly that which mutates. for example: rather than passing out an array your class holds for the client to mutate, have the singleton class add the object to the array it holds. if you truly must expose the array to the client, then return a copy. ths is just basic ood, but many objc devs expose the majority of their ivars disregarding the importance of encapsualtion.
if it's not thread safe and the class is used in a mutithreaded context, make the class (not the client) implement proper thread safety.
design singletons' error checking to be particularly robust. if the programmer passes an invalid argument or misuses the interface - just assert (with a nice message about the problem/resolution).
do write unit tests.
detach state (e.g. if you can remove an ivar easily, do it)
reduce complexity of state.
if something is still impossible to debug after writing/testing with thorough assertions, unit tests, zombie tests, memory tests (GuardMalloc, scribbling), etc,, you are writing programs which are too complex (e.g. divide the complexity among multiple classes), or the requirements do not match the actual usage. if you're at that point, you should definitely refer to my other post. the more complex the global variable state, the more time it will take to debug, and the less you can reuse and test your programs when things do go wrong.
good luck
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With