Hacker News new | past | comments | ask | show | jobs | submit login
Clean, Modern Objective-C (harlanhaskins.com)
23 points by lyinsteve on Feb 20, 2014 | hide | past | favorite | 47 comments



All of these things are something you use an automated formatter for, not regard as some kind of 'modern objc'. I guess people like to focus on pointless stuff like this because it's easier to worry about than whether you should use an eventbus or a delegate - you know, actual hard choices.

Stylistic stuff like this is not something you need to give rules for. Create an automated formatter, run it on your or others source files, and get back to solving real problems.


You're right to an extent, but I don't think "Run your code through a formatter when you're done hacking it together" is a viable, maintainable, or scalable policy. Especially not for enterprise or team based workflows.

Also, #'s 1, 2, 4, and to a certain extent 8 are more questions of design pattern than 'style'.


> 2. Use consistent spacing and use whitespace liberally.

The very definition of a formatting bikeshed.

> 1. No instance variables.

I'm not convinced here - he certainly doesn't explain why you shouldn't use them. I guess he likes to use self.var rather than var - but it's important to note that this does have some performance implications.

> 4. Modularize and model.

I'll give you 4 though - using compiler recognizable types is always a boon. I'm not sure if anybody really needs to be told to modularize and model, most people would understand that without being told. It does lock-in your public API though, making changes to a library require updating all apps that use the library. Meanwhile, adding a new field into a dict means existing apps can upgrade the library easily. Still, I'd definitely agree that types are always a better bet in the long run.


Whoops, sorry, I meant 1, 4, 5, and 8. You're right about 2.


> but I don't think "Run your code through a formatter when you're done hacking it together" is a viable, maintainable, or scalable policy.

Just hook clang-format or clang-tidy with your build system. A lot of projects do it.

You will be surprised how inconsistent people actually are, even in project where almost everyone is sticking to these practices at 100%. And the larger the project, the worse it gets (most people are inconsistent in different ways).

The only way to get this right is to either produce hard errors when they are violated (e.g. your code won't compile, or won't be committed) or do it automatically. clang-tidy is just the way to go.


I think many go programmers would disagree with you, and C++ programmers who've discovered clang-format too.

Bikeshed discussions about formatting quickly go out the window when you have an automated tool that can settle all arguments.


Why isn't it a viable, maintainable or scalable policy? Can't you setup a git hook to do it?


I'm surprised that he provides five versions of the method definition syntax and none of them are what Apple does and what I consider to be the standard:

    - (void)doSomethingWithParameter:(NSString *)parameter;


That is the convention officially endorsed by Apple (https://developer.apple.com/library/ios/documentation/Cocoa/...)


That's what I use as well. In Apple's frameworks I've found them to be very inconsistent between different areas though.


Maybe because these things simply don't matter.

Worse than that, they distract from things that do.

Bike shed?


You're correct. I've updated the post with credit to you, thanks!


No problem! Have you commonly come across all these variations? I have seen a couple different things but my experience working in objective-c written by others has been limited, so my impression was that the above was more widely accepted.


I contribute to CocoaPods repositories, so I've seen a lot. I don't really feel adamantly one way or the other, but just be consistent.


That is my preferred method as well, but I've seen a lot of templates use:

-(void) doSomethingWithParameter:(NSString *)parameter;


When in Rome, do as the Romans do.


This and the linked guides claim there is no advantage to using instance variables (preferring properties), but I see at least one advantage: simplicity. When you're reading code that uses an instance variable you know exactly what it's doing, you don't have to check the attributes of the property, or the getter/setter implementation, or think about any KVO going on.

I'm not saying this makes instance variables preferable, but there is something to be said for minimising the number of places you need to look when trying to understand a snippet of implementation.


Exactly!!!! So much of objc programming is about maintaining internal state. Dot syntax and automatically synthesized properties just obfuscates whats actually going on.

IMO you should always be accessing the ivar directly unless you have a specific reason not to.


The ridiculous amount of effort that we have to go through to define private properties (just sheer amount of text around them) makes me miss the pre-property days... I still define iVars the old fashioned way. The whole language would do well to have some syntax sugar added akin to Java's private, public, protected for properties so we could just go

@private NSString dog;

@public NSString cat;

... Oh Wait! We do, it's just that nobody uses it anymore. http://stackoverflow.com/questions/4869935/objective-c-priva...

Well we have syntax sugar for iVars... I think it's so messy putting some properties in the header and some in the implementation file with a private category - come on we can't have better syntax than that?


Having public things be in the header and private things in the .m seems exactly right! The header should only expose the public interface, not the implementation details, no?

(On the other hand, defining properties in an anon category, instead of just plain old instance variables in the .m, seems pointless to me -- why have a layer of indirection for the class to access itself?)


If we take "should" and run with it then there should be no archaic header files at all and instead a.. gasp.. real module system :-)


I'm a heavy user of properties in other languages like C#, but in Objective C, to define the anonymous category with all the property ceremony and verbiage, feels...excessive...if all you need is some private state, and you don't care about generated accessors or KVO.

Why are ivars bad, exactly? They're a lot more succinct if you don't actually need what properties give you.


Right, exactly.


Well, I think nobody uses them anymore because they aren't synthesized and the (readonly|readwrite) distinction is so clear.


I'm not saying properties and all the automation they bring are a bad thing - I'm just saying the way we have to use them syntactically sucks.


How about taking a look at the Google ObjC style guide? https://google-styleguide.googlecode.com/svn/trunk/objcguide...

I'm not convinced by private properties either. Use ARC and just define your ivars in the implementation.


I'm still learning Objective-C but it always bothers me a bit when a controller conforms to many protocols. Are there strategies to manage this (other than #pragma mark)?

I really like point #4. I'd take that further and say that most "keyed access" classes should be wrapped in a more domain-specific wrapper class (thinking of NSUserDefaults, and the like).

With regards to point #8, Apple actually recommends against naming functions starting with get... also, unless they are property getter overrides. (https://developer.apple.com/library/mac/documentation/Cocoa/...)

Thanks for the article.


the only other strategy I have seen is to instantiate handlers for the sub concerns. so set self.tv.delegate = myTVDelegate; or something like that.

Apple warns against it because it goes against key value coding I think. I am kinda on the I wish they had a consistent prefix for stuff. maybe it's just my feeble mind, but I like to have the code completion remind me of what's available. the sometimes inconsistent naming conventions in different classes makes it tough to remember all the nuances when you don't use them every day.


My points on Modern Objective-C:

  - Use MVVM and some method of bindings (e.g. ReactiveCocoa) [0]  
  - Split up ViewControllers and DataSources [1]  
  - Split up classes using Categories (I've seen so many blown up AppDelegates)
  - Use CocoaPods (this should be a given by now)
  - probably much more I forgot about...
oh, and btw: those `@directives` go by the name of `literals`

[0] - http://lmgtfy.com/?q=mvvm+objective-c [1] - http://www.objc.io/issue-1/


-I've heard a lot about ReactiveCocoa recently, but I haven't had a chance to try it. Maybe I should. And maybe I will!

- I'm super guilty of just handling everything in AppDelegate (notifications, URI schemes, etc.) I need to work on this.

- CocoaPods are the greatest


Build some stuff with Reactive Cocoa before you jump on that bandwagon. It pollutes the stack of everything it touches and its not very useful unless you use it pervasively...


I agree completely. Its use case is highly specialized and all it does is make a bunch of code nicely split up into methods and crams it into fewer methods with a ton of blocks. Even the example of "before" and "after" on the github page shows that how complicated it makes things look.


I'm guilty of #4, but I think it's a judgement thing. If you're just going to briefly use the dictionary, I personally think it's a waste of time to go to the effort of creating a class. If it's core to your program it makes more sense since you can then tap into things like KVO a bit better. And, prior to ARC and automatic synthesis of properties, it made for a ton of boilerplate code.


It's a nice little list. My one nitpick is that he referred to to the class extension [1] as an anonymous category and while it also has been called this it's generally documented as a class extension by Apple and so it makes sense to call that out so folks can go read about how it actually works.

[1] http://goo.gl/zTu3nA


You're right. I'll update it to include both definitions in the morning.


In response to point #3, my counter-example is that when you list a method's arguments or return type, the parentheses include the star. In other words, the star does not "belong" to the variable in that particular case.

  -(NSData*) myMethod:(NSString*)string;
It can really be argued both ways. We've hugged the type everywhere I worked.


I agreed with you for about ten years, and then I stopped doing that because of the OPs example but also because idiomatic c and c++ are written this way and I just decided to stop swimming upstream after reading enough of it.

But it can be very confusing when dealing with dereferences. So I feel you there. Doing C for 15 years you just get used to it.


The OPs example only shows that you should never declare two variables on the same line! This is a rule that's as old as programming, even.

  int* a;
  int  b;


Isn't it a bad idea to define private/protected properties in your implementation file? What if you want to subclass?


You'll have to redefine the properties in the subclass's class and specify @dynamic so that it knows the properties were synthesized in the parent class


I've experimented with putting the category in a private, implementors-only header file and it seemed to work fine. But I'm not sure if that's canonical.


And thats all bad and why inheritance and encapsulation in obj C are kind of rough on you.

But on the other hand, it discourages something thats overused in other languages. Inheritance!

Obj-C would do well to find a better composition mechanism to make most of the inheritance issues a secondary concern.


Maybe you should give an obj-c seminar


I'm working on it!


Just when the Heck will apple starting making or designing a replacement for Objective C?

Until Rust turns to 1.0?


I am a rookie Objective-C learner and all these are pretty known to me. I now think "probably people are writing worse code than I do". These are pretty straightforward facts.


Unfortunately I disagree that this is cleaner.

Yes its true, you can hack your way to to some idealized notion of objective C.

Accessing everything through properties is lame, and it sucks, and it only seems like a good idea if you use ARC because you think it will make it easier to find the retention bugs, it actually makes it harder.

Also properties are not the same as private members, although obj C trendists want them to become the same.

No, I disagree it takes you further away from object programming not closer.

The current trends in objective C are to hack the file syntax to make it seem like its more encapsulated and use properties to make ARC happy.

Both are wrong, obj C is a leaky abstraction. Too bad. You will never make it better by making your code harder to read and debug.

Yes in obj C inheritance sucks, protocols suck, constants suck, encapsulation sucks, and in the end if you know how to make something, it really doesn't matter. Stop obsessing on shit nobody cares about and build something.

Even with all your recommendations obj C is a bandaid. But falling off your skateboard can be fun. Live a little.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: