views:

2072

answers:

13
+19  Q: 

Cocoa Bad Habits

What are those bad habits you've developed since you've started coding in Cocoa?

I think making a list of bad habits and actively adding to it and, more importantly, breaking those habits is a good technique to produce your code quality. So start now, get your bad habits off your chest. Maybe other people share your bad habits.

+5  A: 

Here's some of mine:

Throwing exceptions without any attempt to catch 'em. I've started to rely on NSError more and more to prevent NSExceptions from flying about like bullets in a John Woo movie, but I still have a lot of exceptional code out there.

Writing a quick class to do X, Y & Z and then forgetting to clean up in dealloc. Leaks ahoy!

Using strings directly in various places (KVO) instead of defining a constant and using that (see Dave Dribin's excellent blog post on KVO for more)

schwa
One thing I really like about Cocoa's design is that NSExceptions are defined to be used only for programmer error (like an out-of-bounds index) while NSError is to be used for runtime errors. Since I realized that, I've felt a lot less need to use NSException.
Evan DiBiase
Except of course you're free to use exceptions as you want. Just because Apple guarantees (well mostly guarantees) that exceptions are used like that in their frameworks doesn't mean you should automatically adopt it too.
schwa
While, of course, you're free to use exceptions and errors as you see fit, http://developer.apple.com/documentation/Cocoa/Conceptual/ErrorHandlingCocoa/CreateCustomizeNSError/chapter_4_section_4.html recommends the distinction I described for all Cocoa code, not just Apple's code.
Evan DiBiase
And, I should add, I wasn't trying to ding you for using NSException too much. I just wanted to point out that Apple's distinction between NSError and NSException makes sense to me, and that it might help you write code that uses fewer exceptions, if that's your goal.
Evan DiBiase
Oh I know you weren't dinging me. I didn't realise that apple recommends that practice globally. Good to know.
schwa
+7  A: 

I get lazy about using accessors inside of classes. Usually, the biggest problem is that I can't easily tell the scope of the variable at a quick glance. Then I spent a few hours last week debugging a memory corruption issues that was due to using

self.displayName = name

in some places and

displayName = name

in others. I was happy when I found it and my app stopped crashing. I wasn't so happy that I wasted several hours looking for such an avoidable mistake.

Jablair
This is avoidable if, as many people suggest you shouldn't, you @synthesize displayName = _displayName, and then NEVER use _displayName. It's a code-smell tactic.
dlamblin
+4  A: 

I use #defines more often where I should be using const declarations.

Also, I'm probably a little too prolific in the NSNotifications I throw around; decoupling run amok!

Ben Gottlieb
+4  A: 

You mean, apart from grinning smugly when I can do in ten lines what takes an MFC coder 300? I suppose my biggest gripe about my own code is the explosion of accessors; next design work I do, I've set myself the challenge of using the smallest number of properties.

Graham Lee
+16  A: 

Passing nil to arguments that call for NSError**, pure lazy.

lfalin
+4  A: 

Misusing Bindings to bind model object properties to each other. This use of Bindings leads to code that is hard to understand, hard to debug, and hard to test. Use Bindings only to bind a UI to a Controller. If you need decoupled models, use NSNotification instead of bindings. At least it's a bit more explicit than KVO.

Barry Wark
It is perfectly fine for one model object to *observe* another.
mmalc
@mmalc True. Unless you're using a more sane KVO than the default Cocoa model (see http://www.mikeash.com/?page=pyblog/key-value-observing-done-right.html), I don't recommend using KVO to observe other model objects: it still ends up as spaghetti. With something like Google Toolbox for Mac's GTMNSObject+KeyValueObserving (http://code.google.com/p/google-toolbox-for-mac/source/browse/trunk/Foundation/GTMNSObject%2BKeyValueObserving.h), I think using KVO is a totally reasonable thing to do.
Barry Wark
I should add for future readers that @mmalc is a true expert. You should take my response with a grain of salt and his comment with the weight of a thousand engineers.
Barry Wark
+7  A: 

Not unit testing enough. It's really difficult to clean up and refactor code if you don't have unit tests. And without constant refactoring and cleaning, code rot begins to set in and spread.

Using the singleton pattern to share objects, like +[MyObject defaultObject]. This is essentially a global variable that makes for some nice hidden dependencies and coupling. This, in turn, makes code harder to test.

Dave Dribin
N-ing the singleton pattern. I'm an abuser too.
schwa
-1 Because both of those are problems in any OO language.
Outlaw Programmer
+7  A: 

Using exceptions for control flow

(And other non-exceptional circumstances.)

Since use of exceptions is brought up in another answer here and the documentation referred to in the comments does not stress this point particularly, it is worth emphasising that exceptions should not be used for normal control flow (as is common in some other environments). Exceptions in Cocoa are comparatively extremely expensive. If you want to communicate an error, use an NSError object and the error-handling architecture provided by Cocoa. Don't throw exceptions.

mmalc
The typo reverses the meaning. Instead of "exceptions should now be used", I think it was meant to be "exceptions should **not** be used".
Rob
+2  A: 

This is somewhat generic and not necessarily cocoa specific but:

Not refactoring enough because the laziness of having to update both .m and .h files.

XCode 3 makes it easier for certain kinds of refactoring like renames, but I found myself refactoring less frequently than on Java or C# and that's a bad habit I'm trying to break.

Sergio Acosta
FYI, CMD-J in XCode makes refactoring a breeze! It updates the .h, the .m and all the other .ms that use your [whatever].
Olie
+1  A: 

I often find myself forgetting to type the return self; part of my constructors. Luckily I've begun to break this particular habit.

Colin Barrett
I keep a basic `-init` method in my Quicksilver Shelf to avoid making mistakes like this (and because I hate typing the same thing 40,000 times).
Peter Hosey
+2  A: 

I learned to hate Interface@#$%-er back when it was far less useful and more buggy than it is now, and so tend to create all my UI in code, steadfastly still avoiding IB. It's silly, since I know it reduces my productivity a ton, but I just can't seem to be bothered to spend an afternoon learning how to plug things into IBs. (Yeah, I know how to do the simple stuff, but I always get annoyed when there's some medium-not-simple stuff to do, and IB seems to work against me.)

Ok, you convinced me -- I'm going to break THAT bad habit this weekend.

Thanks! :)

Olie
+2  A: 

Bad habit: Retaining my Java mindset.

My Java background leads me to obsessively check for a null before even thinking about doing anything with a variable, when I could be making use of Objective-C's ability to send a message to nil. (See: "Sending a message to nil?")

Instead of trying to preemptively catch a nil, I have to remind myself that Objective-C allows me to simply write code that gracefully works with return values of 0 or nil.

Jeff
+2  A: 

Hard-coding strings like buttons/view titles. Pure lazy. Now need to get out everything in order to support localization :(

Nava Carmon