Re: Followup - Re: Is there a pattern for creating an object with global scope?
On 15 Apr 2013, at 00:25, Graham Cox graham@bigpond.com wrote: On 14/04/2013, at 2:08 PM, YT y...@redwoodcontent.com wrote: My struggle is partially due to my lack of experience in OOP. I just have not written enough OO code as of yet. AND I'm very new to Objective-C. Hence my lack of experience and working knowledge of Objective-C. extern int gFoobar; I understand that solution and its working for me right now. I understand how tempting it is to go with whatever you can get working, especially when you're new to something. But in this case I believe you should resist the temptation and try and gain a little more understanding before you get too far down this road. GLOBALS ARE BAD NEWS. That is a pretty good rule and well worth sticking to. If you can get rid of globals (and you always can) then you should avoid them. There is NO problem in application programming that requires a global to solve it. Singletons are a much safer and more predictable means of achieving something that has global scope but prevents the hidden state/parameters problem that globals bring with them. Wow, I really can't get my head around this one. You make bold statements like GLOBALS ARE BAD NEWS (which I 100% agree with), but then follow up with effectively use singletons instead. Singletons bring with them 95% of the problems globals bring. They still break any attempts at threading, they still break any attempts at testing, they still break separation of concerns, and they're always avoidable. So I'd follow up with SINGLETONS ARE BAD NEWS TOO! In 95% of cases where you have a singleton, you should almost certainly be using dependancy injection instead, or some other method of avoiding it. Note also – simply using your app delegate as a store for things that aren't singletons, but only one of them is pointed at by your app delegate is also horrific – you're just substituting one singleton for another. Thanks Tom Davie ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Followup - Re: Is there a pattern for creating an object with global scope?
On 15/04/2013, at 8:44 PM, Tom Davie tom.da...@gmail.com wrote: Wow, I really can't get my head around this one. You make bold statements like GLOBALS ARE BAD NEWS (which I 100% agree with), but then follow up with effectively use singletons instead. Singletons bring with them 95% of the problems globals bring. They still break any attempts at threading, they still break any attempts at testing, they still break separation of concerns, and they're always avoidable. So I'd follow up with SINGLETONS ARE BAD NEWS TOO! In 95% of cases where you have a singleton, you should almost certainly be using dependancy injection instead, or some other method of avoiding it. Note also – simply using your app delegate as a store for things that aren't singletons, but only one of them is pointed at by your app delegate is also horrific – you're just substituting one singleton for another. I'm not suggesting you use singletons all over the place, but judicious use of singletons is a reasonable and straightforward way to solve the global scope problem without directly using globals. Sometimes you need something with global scope, and the OP's use-case of preferences is a common example. Other things are a natural fit too, such as NSApplication. I agree that they can bring many of the same problems with them, but some of the things you mention are not inherently a problem with singletons as long as you're aware of the issues. Threading for example, is easily taken care of. Are they a solution for every situation? No, I'm not suggesting they are, but I don't think they bring 95% of the same problems as globals. I don't know what you mean by dependency injection, it's not a term I've heard of, but it's like anything - there are good and correct solutions to a problem and there are others which work but are non-optimal. The craftsman needs to be aware of the tools at his disposal and use the appropriate one for the task at hand. Globals are never required, singletons occasionally. Something else altogether usually. --Graham ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Followup - Re: Is there a pattern for creating an object with global scope?
On 16/04/2013, at 10:18 AM, Graham Cox graham@bigpond.com wrote: I don't know what you mean by dependency injection, it's not a term I've heard of OK, I looked it up. I hadn't heard the term but I'm very familiar with the concept it refers to. Sometimes the service or dependent entity should be a singleton... I don't see that it's a substitutable solution, but one orthogonal to the existence of singletons. --Graham ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Followup - Re: Is there a pattern for creating an object with global scope?
On 15.04.2013, at 12:44, Tom Davie tom.da...@gmail.com wrote: Note also – simply using your app delegate as a store for things that aren't singletons, but only one of them is pointed at by your app delegate is also horrific – you're just substituting one singleton for another. If it were only that! At least singletons only pull in dependencies from their problem domain into any module that uses them. If you instead implement them in the app delegate, all that code not only bloats the app delegate, its dependencies also make all these singletons recompile whenever only one of them changes. Cheers, -- Uli Kusterer The Witnesses of TeachText are everywhere... http://www.zathras.de ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Followup - Re: Is there a pattern for creating an object with global scope?
On 14.04.2013, at 06:29, Steve Mills sjmi...@mac.com wrote: Oh, that's easy, once you know how to make singletons. OK, I wouldn't call it easy, but it's the right thing to do. If the C++ Steve wrote helps you understand things better, here's a 1-to-1 translation of that code to the equivalent in Objective C: PreRun.h: @interface PreRun : NSObject { BOOLtheVariableYouWantToBeGlobal; } -(PreRun*) sharedInstance; // Usually a singleton access method is called defaultX or sharedX, not GetInstance like in C++. -(void) setVar: (BOOL)b; -(BOOL) var;// You usually don't use GetX as the name for a getter in Objective C. A 'get' prefix is used to indicate a method that has return parameters. @end PreRun.m: @implementation PreRun -(PreRun*) instance { static PreRun* sSharedInstance = nil; if( sSharedInstance == nil ) sSharedInstance = [[PreRun alloc] init]; return sSharedInstance; } -(void) setVar: (BOOL)b { theVariableYouWantToBeGlobal = b; } -(BOOL) var { return theVariableYouWantToBeGlobal; } @end In a file that wants to use that variable: [[PreRun instance] setVar: YES]; As others mentioned, you could use dispatch_once for thread safety (but I don't think threading is a topic you want to tackle at this point, save that for later and save yourself a lot of pain and random bugs that sometimes happen and sometimes don't). Also, you would probably use @property BOOL (assign) var; and @synthesize var = theVariableYouWantToBeGlobal; to save yourself the work of writing setVar:/var methods and declaring the instance variable 'theVariableYouWantToBeGlobal'. Some people also believe in overriding -init, -retain, -release and -retainCount to keep people from creating a second instance of this object, but that's more defensive coding than necessary. I just mention it because it's the moral equivalent to Steve's making the constructor private. Cheers, -- Uli Kusterer The Witnesses of TeachText are everywhere... http://www.masters-of-the-void.com ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Followup - Re: Is there a pattern for creating an object with global scope?
On 14/04/2013, at 2:08 PM, YT y...@redwoodcontent.com wrote: My struggle is partially due to my lack of experience in OOP. I just have not written enough OO code as of yet. AND I'm very new to Objective-C. Hence my lack of experience and working knowledge of Objective-C. extern int gFoobar; I understand that solution and its working for me right now. I understand how tempting it is to go with whatever you can get working, especially when you're new to something. But in this case I believe you should resist the temptation and try and gain a little more understanding before you get too far down this road. GLOBALS ARE BAD NEWS. That is a pretty good rule and well worth sticking to. If you can get rid of globals (and you always can) then you should avoid them. There is NO problem in application programming that requires a global to solve it. Singletons are a much safer and more predictable means of achieving something that has global scope but prevents the hidden state/parameters problem that globals bring with them. Globals tie together parts of your program in ways that are not obvious, and as a result lead to bugs that can be extremely hard to track down. Decoupling each part of your app from every other part as far as possible is a good aim - globals instantly spoil that. Note that singletons don't lead to the same problem since the singleton object itself can be self-contained, and any state associated with it is at least boxed into that object, making debugging less of a problem. About the only excuse for globals are as a shortcut, e.g. NSApp instead of +[NSApplication sharedApplication] but even there it's arguably bad style. When I started in programming globals were the only variables there were (BASIC, circa 1979) and that's one reason why this language gained such a notorious reputation. It's a pity better languages perpetuated the existence of globals - if they're there, you should use them, right? Wrong. Getting rid of globals is arguably the single best thing you can do to improve the quality of your code as you move from first steps to more ambitious projects. I have a PreRun Class that defines the object and I instantiate in main.m just before the line return NSApplicationMain(argc, (const char **)argv); This sounds like a bad idea to me. First, it means you're modifying main.m which is almost never necessary (there's a reason that this file is supplied in a standard form and placed into the 'support files' group, out of harm's way). Second it means you're wasting time instantiating an object that isn't needed for a long time yet, if ever. Using a singleton is cleaner, because it will only be instantiated at its first point of use (and if never used, will never be instantiated). runs in main.m. The object instance persists the entire program run. THEN I simply extern the global var that holds the pointer to the object in all of the Class files where its required to access it. It may be a violation of OOP theory and application, it may be considered a kludge BUT it works right now. I am willing to move to a conventional OOP solution if I could figure out how. Many replies have shown you how - make a class method that returns the object, instantiating it once. Using a static variable within the class method ensures that it happens only once. You should import the class header where code makes use of the singleton, rather than use an 'extern' reference. Reading Apple Documentation is like reading UNIX Man pages - groan, beat me with a stick but don't make me read UNIX Man Pages - sigh. Better get used to it, because apart from voluntary help via this list and others, that's how you're going to learn about classes. In fact the docs aren't as terse as man pages, and there are plenty of other guides that show you how classes are used in a broader context. --Graham P.S. Tip: don't change the subject line when replying to postings, it prevents all the replies appearing in the same thread. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Followup - Re: Is there a pattern for creating an object with global scope?
First just to clear a distraction... I didn't want to actually create my own version of Preferences. In fact that was a mistake to even mention it. Sorry, I was flailing in my mind trying to describe what I was struggling with and out came Preferences as an example. Totally throw away the notion of creating a Preferences Object. My struggle is partially due to my lack of experience in OOP. I just have not written enough OO code as of yet. AND I'm very new to Objective-C. Hence my lack of experience and working knowledge of Objective-C. Scott Ribe sited a working example that I could instantly understand, since I have lots of experience in good 'ole Standard C. Yes, extremely easy, just create the var, as in: int gFoobar = 42; Then reference it elsewhere as: extern int gFoobar; I understand that solution and its working for me right now. I have a PreRun Class that defines the object and I instantiate in main.m just before the line return NSApplicationMain(argc, (const char **)argv); runs in main.m. The object instance persists the entire program run. THEN I simply extern the global var that holds the pointer to the object in all of the Class files where its required to access it. It may be a violation of OOP theory and application, it may be considered a kludge BUT it works right now. I am willing to move to a conventional OOP solution if I could figure out how. Reading Apple Documentation is like reading UNIX Man pages - groan, beat me with a stick but don't make me read UNIX Man Pages - sigh. As suggested I read some on NSUserDefaults - I'm not sure how this would provide what I need, perhaps more reading here. As Suggested I looked up the notion of a Singleton and Creating a Singleton Instance - Looks promising BUT since I have little experience to date on deciphering Apple Objective-C documentation it has created more unanswered questions rather than producing working code. SIGH! More reading in my future and stumbling in the dark. YT . ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Followup - Re: Is there a pattern for creating an object with global scope?
On Apr 13, 2013, at 23:08:41, YT y...@redwoodcontent.com wrote: int gFoobar = 42; Then reference it elsewhere as: extern int gFoobar; I understand that solution and its working for me right now. I have a PreRun Class that defines the object and I instantiate in main.m just before the line return NSApplicationMain(argc, (const char **)argv); runs in main.m. Instead of doing it there, add an NSApplicationDelegate subclass and do your initialization in the applicationWillFinishLaunching method. Read up on that. This is all good stuff to learn if you want to write good Mac or iOS apps. The object instance persists the entire program run. THEN I simply extern the global var that holds the pointer to the object in all of the Class files where its required to access it. It may be a violation of OOP theory and application, it may be considered a kludge BUT it works right now. I am willing to move to a conventional OOP solution if I could figure out how. Oh, that's easy, once you know how to make singletons. OK, I wouldn't call it easy, but it's the right thing to do. PreRun.h: class PreRun { private: // Static variable that holds the only instance of this class: static PreRun* instance; // The variable: booltheVariableYouWantToBeGlobal; // Private ctor so nobody else can create this: PreRun(void) : theVariableYouWantToBeGlobal(false) // Inits the member var. {} // Nothing else to do here. public: static PreRun* GetInstance(void) { if(instance == nil) instance = new PreRun; return instance; } void SetVar(const bool b) { theVariableYouWantToBeGlobal = b; } bool GetVar(void) const { return theVariableYouWantToBeGlobal; } }; PreRun.cpp: // Automatic initializer sets the instance to nil: bool PreRun::instance = nil; In a file that wants to use that variable: PreRun::GetInstance()-SetVar(true); Now, this doesn't handle the case of threaded apps where multiple threads might be trying to set and/or get the value at the same time. That's a whole other discussion. And, you can always simplify this example by making the member var public instead of private and doing away with the Set/GetVar methods, but that's not good form either. -- Steve Mills Drummer, Mac geek ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com