Which Singleton class is better?

Discussion in 'iOS Programming' started by mikezang, Sep 7, 2010.

  1. mikezang macrumors 6502a

    Joined:
    May 22, 2010
    Location:
    Tokyo, Japan
    #1
    I have two Singleton class, I am not sure which one is better, I hope that you can give some suggestion.
    Code:
    #import "SingletonClass.h"
    
    @implementation SingletonClass
    
    static SingletonClass *sharedInstance = nil;
    
    + (SingletonClass *)sharedInstance {
        @synchronized(self) {
            if(sharedInstance == nil) {
                [[self alloc] init];
            }
        }
    
        return sharedInstance;
    }
    
    + (id)allocWithZone:(NSZone *)zone {
        @synchronized(self) {
            if (sharedInstance == nil) {
                sharedInstance = [super allocWithZone:zone];
                return sharedInstance;  
            }
        }
        return nil; 
    }
    
    - (id)copyWithZone:(NSZone *)zone {
        return self;
    }
    
    - (id)retain {
        return self;
    }
    
    - (NSUInteger)retainCount {
        return NSUIntegerMax;  
    } 
    
    - (void)release {
    }
    
    - (id)autorelease {
        return self;
    }
    
    @end
    
    Code:
    #import "SingletonClass.h"
     
    @implementation SingletonClass
     
    static SingletonClass *sharedInstance = nil;
     
    + (SingletonClass *)sharedInstance {
        if (sharedInstance == nil) {
            sharedInstance = [[super allocWithZone:NULL] init];
        }
     
        return sharedInstance;
    }
     
    + (id)allocWithZone:(NSZone *)zone {
        return [[self sharedInstance] retain];
    }
     
    - (id)copyWithZone:(NSZone *)zone {
        return self;
    }
     
    - (id)retain {
        return self;
    }
     
    - (NSUInteger)retainCount {
        return NSUIntegerMax;
    }
     
    - (void)release {
    }
     
    - (id)autorelease {
        return self;
    }
     
    @end
     
  2. Luke Redpath macrumors 6502a

    Joined:
    Nov 9, 2007
    Location:
    Colchester, UK
    #2
    One that doesn't exist ;)

    Seriously though, whilst I know that this is the singleton example that Apple gives, it's full of unnecessary boilerplate.

    This article, written by an Apple engineer, explains the simplest way to implement a singleton, with or without thread safety.

    http://eschatologist.net/blog/?p=178
     
  3. mikezang thread starter macrumors 6502a

    Joined:
    May 22, 2010
    Location:
    Tokyo, Japan
    #3
    Why do you know author is an Apple engineer?
     
  4. Luke Redpath macrumors 6502a

    Joined:
    Nov 9, 2007
    Location:
    Colchester, UK
    #4
    Because I'm psychic.

    Or, because I know who he is, I follow him on Twitter, he contributes on the Apple developer forums and he also presented one of the talks at WWDC this year. He works on the developer tools team and has done for a while.

    http://eschatologist.net/blog/?p=134
     
  5. PhoneyDeveloper macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #5
    A few random comments on this subject:

    Mr. Hanson is a nut about unit testing. Unit testers hate, with a passion, singletons. They hate singletons because they screw up unit testing royally. They will give you all kinds of reasons why singletons are bad but the bottom line is that singletons screw up unit testing. Royally.

    That said, OP, all your code that you show contains a bunch of neurotic stuff intended to prevent a bunch of problems that will never occur. Hanson's post, 178, simplifies things somewhat. And if that works for you then use it.

    For me I usually just make singletons that only have class methods. No instance of the singleton class ever needs to be created. None of that neurotic code that's intended to prevent alloc/init/release/kissme whatever methods from being called is needed. If you're writing a library, like Foundation, then maybe you need that stuff. If you're just writing a plain old application where you control all the code then you don't need to override release or allocWithZone or any of that junk.
     
  6. mikezang thread starter macrumors 6502a

    Joined:
    May 22, 2010
    Location:
    Tokyo, Japan
    #6
    Well, In fact, I just want to utility library, for example, and so on...
    [singletonClass isHoliday]
    [singletonClass isMarketopen]
     
  7. PhoneyDeveloper macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #7
    Exactly.

    In that case chuck all that junk you had and just implement class methods. It's very simple.
     
  8. mikezang thread starter macrumors 6502a

    Joined:
    May 22, 2010
    Location:
    Tokyo, Japan
    #8
    So this is ok?
    Code:
    #import "SingletonClass.h"
     
    @implementation SingletonClass
     
    static SingletonClass *sharedInstance = nil;
     
    + (SingletonClass *)sharedInstance {
        if (sharedInstance == nil) {
            sharedInstance = [[super allocWithZone:NULL] init];
        }
     
        return sharedInstance;
    }
    
    @end
    
     
  9. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #9
    Write them as functions. Plain ordinary C functions:
    Code:
    extern BOOL isHoliday(void);
    extern BOOL isMarketopen(void);
    
    What do you gain by making them class methods? If you can't answer that with a technically sound reason, then just write functions. Why make anything more complex than it absolutely needs to be?

    One of the most commonly used things in Cocoa is NSLog(), and it's a function.

    If functions are "bad" or "un-Cocoa-like", then someone forgot to tell Cocoa's designers:
    http://developer.apple.com/mac/libr...Foundation_Functions/Reference/reference.html
     
  10. mikezang thread starter macrumors 6502a

    Joined:
    May 22, 2010
    Location:
    Tokyo, Japan
    #10
    Great!

    I thought everything should like to use OOP:(
     
  11. Luke Redpath macrumors 6502a

    Joined:
    Nov 9, 2007
    Location:
    Colchester, UK
    #11
    Ideally, yes. Objective C is an OO language and as such you should try and follow sound object oriented principles but if you are going to eschew them then I am with chown3; you may as well use functions.

    That said, one advantage using a bunch of class methods is that you get some namespacing but its unlikely to be an issue as long as you are careful (and you can always prefix your functions).

    Oh, and being a "unit testing nut" is nothing to be ashamed of. To me, the nut is the person who doesn't write a automated tests for their code' whether they are unit tests or higher level acceptance tests. ;)
     
  12. PhoneyDeveloper macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #12
    For simple functions like this they can be either C functions or class methods and there isn't much difference. If they are conceptually related then it makes sense to make them class methods. If they rely on any state then it makes sense for them to be class methods.

    I don't think there are any classes like this in UIKit or foundation. But classes like UIDevice and NSFileManager are similar. If you look at UIDevice it's basically just a bunch of properties. However, you can't use the property syntax as a class method so they have to have an instance. Also, most or all the properties are conceptually related. UIDevice could be implemented as a bunch of C functions or as a bunch of class methods with little difference to the current implementation.
     
  13. Luke Redpath macrumors 6502a

    Joined:
    Nov 9, 2007
    Location:
    Colchester, UK
    #13
    Surely, if they rely on state, it makes more sense from them to be instance methods on a properly designed class?

    You don't know that because you don't know what kind of state UIDevice is tracking internally. UIDevice is certainly one of the few cases where a true singleton makes sense (there is only one device, after all) but that still doesn't preclude it from being a proper object.

    UIScreen on the other hand is an example of a class that naively one might implement as a singleton. There is only one screen right? But then along comes 3.2 with external display support.

    Generally, I've found that Cocoa APIs don't tend to use singletons in the strictest sense of the word, but normal objects that happen to have one or more globally available instances (think [NSNotificationCenter defaultCenter], [NSUserDefaults standardUserDefaults], [UIScreen mainScreen] etc.).

    I won't deny that there are occasionally times where a simple class method or global function is useful to encapsulate a small piece of common functionality but that doesn't stop me treating it as an anti-pattern; a code smell that should indicate that you are writing procedural code that could do with refactoring to a better, OO design.

    Likewise, singletons are occasionally useful (although I find the shared instance pattern to be preferable as you rarely need a true singleton) but I again treat it as an anti-pattern and an indication that something might be wrong with my application design. This is why I generally avoid singletons - not just because they are a barrier to testing as they make dependency injection harder, although that's certainly a factor - but because whilst they are occasionally the pragmatic choice, there is often a better, more cohesive and less coupled design.

    Does the above matter if you're making a simple fart app that takes a few days to put together? No, but if you're writing a more complicated application that has to be maintained over a longer period of time, then I think it does.
     
  14. firewood macrumors 604

    Joined:
    Jul 29, 2003
    Location:
    Silicon Valley
    #14
    OPP makes code bigger and slower. Probably burns more battery as well. It should only be used in cases where the advantages outweigh the disadvantages. That's most (non-tiny & non-fast) things, but not all.
     
  15. mikezang thread starter macrumors 6502a

    Joined:
    May 22, 2010
    Location:
    Tokyo, Japan
    #15
    So most of Helper and Wrapper class don't be needed, do you think so?
     
  16. Cromulent macrumors 603

    Cromulent

    Joined:
    Oct 2, 2006
    Location:
    The Land of Hope and Glory
    #16
    Except unit tests promote the thought pattern of "I have unit tests therefore I don't need to manually test as much".

    Its better to make sure you rigorously test manually and run through your code with a debugger to see what is going on than it is to make sure you have unit tests for everything.

    Plus if your unit tests are not kept in absolute lock step with the rest of your code you run into other problems (such as tests passing when they should fail - that will definitely ruin one of your days in the future).
     
  17. firewood macrumors 604

    Joined:
    Jul 29, 2003
    Location:
    Silicon Valley
    #17
    The fart app that paid off the most money likely wasn't automatically unit tested. But it was among the very first to market. The 100th fart app that was finally actually properly designed and fully automatically tested probably paid off the development time at 0.5% of minimum wage. This is a tiny example, but I've seen the same happen to million dollar projects. Unless working for NASA, the FAA or FDA, a useless nut is anyone who doesn't know when dirty shortcuts are the proper trade-off for success.

    For small stuff just use functions and globals (and pointers and goto's). It's far less painless to eventually rewrite the small stuff completely rather than forcing it to be reusable when you aren't.
     
  18. Luke Redpath macrumors 6502a

    Joined:
    Nov 9, 2007
    Location:
    Colchester, UK
    #18
    *ahem*

     
  19. Luke Redpath macrumors 6502a

    Joined:
    Nov 9, 2007
    Location:
    Colchester, UK
    #19
    TDDis a practice that mitigates your last point.

    Manual testing has value, especially with apps where the end user experience is so important but being able to repeatedly run a series of automated tests is more valuable.

    Unit tests alone are not enough. You also need a good suite of high level acceptance tests.

    If you are writing tests that produce false negatives, then you need to learn how to write better tests.
     
  20. Cromulent macrumors 603

    Cromulent

    Joined:
    Oct 2, 2006
    Location:
    The Land of Hope and Glory
    #20
    Not at all.

    Unit tests are only as good as the programmer who implements them. If you make a mistake in your basic assumptions, that same mistake will be replicated in your unit tests. They are not a silver bullet.

    They are a tool like any other, this preaching that they are one of the saving graces of development is ridiculous. It's yet more bandwagoning of the worst kind.

    I'm not arguing against unit tests in the least. I am arguing against the assumption that they are the most important part of developing stable and low bug count code.
     
  21. Luke Redpath macrumors 6502a

    Joined:
    Nov 9, 2007
    Location:
    Colchester, UK
    #21
    I don't think I've said at any point that unit tests are some kind of silver bullet for writing bug free code and naturally, you can have 100% test coverage and still not absolutely guarantee your code is bug free. Unit tests can't help you debug memory leaks and a variety of other problems (fortunately there are plenty of other tools that can help you with these things).

    My original point was about automated testing; whether they are written as part of a TDD cycle (which is equally about driving the design of your code, not just ensuring that it works) or written after the fact.

    The fact is that in the majority of cases, if you can test something manually, you can or should be able to automate it. Automating it means those tests can be run repeatedly and frequently. They can be run before you check in to your version control system and they can be run as part of a continuous build process. They might not catch everything but they can and do help to catch unexpected bugs and regressions and they provide an excellent safety harness for refactoring.

    I also took exception to the notion that somebody who advocates unit testing is in some way a "nut". To me, there is nothing worse than a code base with no automated tests. You can't possibly manually test everything after making a change therefore every change carries the risk of breaking something that you didn't intend to. I'd even go as far to say that on anything but the simplest of code bases, not writing automated tests is just irresponsible.

    The idea that hacking your way from point A to B, taking "dirty little shortcuts" here and there, is somehow a good thing because it gets you to market quicker is often a false economy. Yes, there are absolutely times when these sacrifices need to be made but lets not kid ourselves that you are building up a technical debt in the process that will likely have to be paid off at some point in the future; the worst thing you can do is let that technical debt overwhelm your project otherwise it's your app that will be languishing behind the competition whilst they roll out new features and you are left putting out fires and fixing bugs and dealing with customer complaints. Nobody will care that you "got there first" if your customers start to abandon you.
     
  22. PhoneyDeveloper macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #22
    I meant "nut" in a good way. Mr Hanson is a strong advocate of unit testing and just about anything I've ever read from him was on that topic.

    I object to the ridiculous assertion, and I paraphrase, that no code can be good unless it's unit tested.

    Gee, I thought we were talking about Singletons.
     
  23. pflau macrumors 6502

    Joined:
    Sep 17, 2007
    #23
    The first singleton class, one that makes sure createInstance is synchronized, while clever, has been shown to not work in some situations.

    So neither of them is perfect. The best way is to create the object instance of the singleton right at the beginning of the program instead of when it is needed. Doing so has the added advantage of catching any error before the program goes too deep.
     

Share This Page