Smalltalk about Objective-C


Ok not so much a small talk, but more a ramble with an objective. (wow, geek humor is really bad).

Thats_the_joke

I’ve had the fortunate ability to spend the past 2 weeks or so getting ramped up on all things iOS and Objective-C for an internal project my company is working on. As a guy who has historically programmed in C-style languages and environments (.NET, Java, C/C++, and JavaScript), I thought this language would be pretty easy to pick up.  I was both right and wrong.

Of course, the core syntax of Objective-C IS almost exactly the same as C, which is great. For me to read through the code and understand which method was calling which other method and why and how, to follow the pointers and references, and the basic structure and syntax were all easy.  Then came the hard part.  Understanding both the Smalltalk-inspired messaging features that are grafted into C, as well as the modifications NeXTSTEP and Apple had taken with the language over the years.  This required a lot of reading.

The first thing for me was to identify all of the interop types that I was starting to see in examples all over the place. This was very reminiscent of all of the coding I had done with C++/CLI where native C types could stand alongside .NET managed types (Well… sort of. I mean, that was the theory with C++/CLI even if that didn’t really all that well. You know what? Let’s never mention C++/CLI ever again). So I understood of course Apple had their own wrapped object framework, like most languages that abstract from native code – NSObject being the base to most things – so I started here.  As a side note, while I was aware that the “NS” in Apple’s core frameworks stood for NeXTSTEP/Sun, I DID NOT realize that the NS “prefix” on all of their objects actually served a greater purpose.  Objective-C does not support namespaces. At all. Yes, you read that correctly. There is no concept of namespaces in Obj-C.  It’s probably one of the top more easily referenced complaints of experienced developers that switch to using Obj-C.  Apple’s hacky solution?  Prefix all of your classes in a library or project with an all-caps, two or three (or more) character prefix. So instead of codemouse.myproject.data you do something like “CMMPD” as a prefix on every file and class.

namespace CodeMouse.MyProject.Data
{
    public class DataConnector
    {
        //yay namespaces.
    }
}
CMMPDDataConnector* dataConnector;
//This CMMPD prefix everywhere is as good as it gets in Obj-C land. Man I miss namespaces.

YES, in theory, you can most certainly have code collisions this way with third-partly libraries. Though it seems in actual practice, this is rare – and with the rise of package managers like CocoaPods, which functions for OS X similarly to how nuget package manager functions for Visual Studio), this seems even less likely.

OK back to our funky NSObject.  I’ll tell you when things finally started to click for me. So I started seeing references to nil everywhere. Nil nil nil. I was like OK, is this like NULL?  Well…. no.  Nil, like all message-enabled objects in Obj-C is… uh, well… It’s message-able.  Huh? OK. Let me explain. If I had an object in C or C++ or C# or Java that was NULL, the value itself was NULL and I tried to call upon properties or methods of that object, I would universally get a Null Reference exception.  This is why there is always so much checking for obj != null in all this code, because without that you’d get a ton of runtime exceptions if something slipped through the cracks.

MyObject myObject = null;

//poke the bee hive with a stick
var result = myObject.DoSomething(); //I'M NOT OK WITH THIS
//System.NullReferenceException barfs on your screen
MyObject* myObject = nil;
NSString* result;

//come at me bro
result = [myObject doSomething]; //I ain't even mad
//result = nil;

So Obj-C objects don’t have the classic Null Reference issue. Since nil is message-able (is that a word? it is now), it’s perfectly allowed to respond to anything that you send to it. It wont DO what is requested of course, but it will respond to your message. Meaning, if I call a property on a nil object, I will not receive a runtime exception, I will get nil.  This was a crazy concept for me to grasp (and kind of exciting actually) and helped to set the stage for understanding the entire Messaging paradigm.  I am used to thinking of methods and returns, but that is not quite correct in how Obj-C works.  I found this blog post explains this (and the potential pitfalls of this) fairly well. The most often way you will see this taken advantage of in Obj-C is through a large pile of nested method calls (without fear of it breaking the compiler somewhere along the way).  Since Obj-C is far from the least verbose programming language, I am a fan.

There were other things to also figure out. OK, so there is no “this”, Apple decided to call it “self” – probably to differentiate from C (OK, FINE – I’ll take a [self]ie rather than this or that). Update: as was pointed out to me via Reddit, “self” was a core designation of Smalltalk and Apple explicitly borrowed this same concept. And yes, C itself DOES NOT have a concept of “this” (only C++).

maxresdefault

Then I stumbled upon “id”.  What the heck is “id”?  I have used C# very heavily over recent years and tried to equate “id” to a variety of things over in .NET-land. Was it like “object”? No… Apple had a generic base object implementation called, NSObject.  Ok… So, was it like “var”? No, “var” is merely implicit typing and still gets checked at compilation. OK so… “dynamic”?  Yes. Well, sort of.  TL;DR;, I’ve decided it’s equal to a hybrid of “dynamic” and “IntPtr” because “dynamic” of course relies on the DLR (which Obj-C has no direct comparison) learned that since Smalltalk was originally designed to have every object potentially be dynamic and messagable, this is an expected and core behavior in the entire framework. So basically “id” is just a pointer to an object that is not static-type checked at compilation. Which of course means it can fail miserably at runtime if you screw it up.  Still, it was good to realize that Obj-C had this concept (inherited directly from Smalltalk), and I have begun implementing it heavily where appropriate, particularly when I always know the expected type that is returned.

What else… Well, Enums are basically, enums (more or less). Structs are basically structs.  The “@” symbol in front of EVERY SINGLE Obj-C NSString really bugs me, but Apple insists that again, its to differentiate between its own wrapped strings and native C strings.

String myString = "this is a perfectly reasonable string";
NSString* myString = @"this is a perfectly reasonable string";
NSString* myString = "i forgot my @ symbol and i hate everyone, especially YOU, clang compiler";

The method parameter list conventions really threw me.  Parameters are separated by colons than commas (fine), and they are ordered parameters (not named). OK.  But, they have “optional” prefix names that you can specify to help identify which parameter is which.  The names are ignored by the compiler so they can be anything, but are really there for the developer’s sake. OK.  That’s cool. BUT… The first parameter in every method signature is not allowed to have a prefix name. Huh?  Yea well…. Apple things it’s best that the method itself should be suffixed with a relevant lead-in to the “main parameter” you want to pass.

//here's my method signature
public void ModifyThisAndThat(string thisString, string thatString) { }

//here's me calling this method
ModifyThisAndThat("this", "that");
//here's my method signature
- (void)modifyThisAndThat:(NSString* thisString) thatString:(NSString* thatString) { }

//here's me messaging this method
[modifyThisAndThat:@"this" thatString:@"that"];

Ugh. Ya know, I can see a lot of value in their structuring here – it somewhat forces you to really think about the params you are passing. Ideally they inadvertently steer you towards passing only ONE parameter that the method expects, and then maybe an array or object of options – which – is better programming practice in general. But I don’t understand why they forcefully pushed these standards when they could have made them optional.

Lastly, I was happy to figure out that Obj-C support anonymous methods (yay) via something they refer to as blocks.  Blocks can be directly translated to C#’s lambdas as anonymous functions. With the advent of LINQ and C#’s ever-increasing arsenal of functional programming techniques, I have grown very accustomed to using anon functions inline all the time. Luckily, this is easily supported in Obj-C too.

//oversimplified LINQ iteration with lambdas
myStringCollection.ForEach(x =>
{
    if (x == "these are the droids i am looking for.")
        Console.WriteLine("i found them.");
});
//oversimplified FastEnumeration iteration with blocks
[myStringCollection enumerateObjectsUsingBlock: ^(id x, NSUInteger idx, BOOL *stop) {
    if ([x isEqual: @"these are the droids i am looking for."])
        NSLog(@"i found them.");
}];

So… There’s still plenty more that I need to figure out. And don’t even get me started on learning Cocoa, Quartz, and all the other frameworks. I miss data binding and MVVM and I’m trying to embrace Notifications and MVC. XCode was one of the strangest IDEs I have ever had to learn (and still continues to be). iOS certificates and deployments for device testing is probably about as complex with how you would do this with Windows Phone, so that was no big deal. I can say overall I am happy to have learned another language. Objective-C itself is pretty great. Some apple-centric things and practices I may have some disagreements with, but I can live with that. I look forward to Obj-C 3.0 being release sometime in the next few years to address namespacing and to add some additional modern elements to the language.  We’ll see what’s next.

300px-NeXT_logo.svg_

 

– b

 

Advertisement

13 thoughts on “Smalltalk about Objective-C

  1. Welcome to the world of Objective-C. As someone that’s been in the thick of it for several years, I just have two comments on your post.

    1) The fact that id is something you’re “implementing heavily” is troubling. You should use this very rarely. In fact, it’s very unusual for me to include it in a class. The typical place for it to be used is in an initializer. As in “- (id)init”. But, that has been replaced recently with the much better “- (instancetype)init”. You might also be tempted to use id in the delegate pattern, but you should almost never pass something as a bare id, without at least decorating it with a protocol you expect the pointed-to object to implement. And, in that case, you might as well put the protocol on NSObject. So, your type would be “NSObject *foo” instead of “id foo”.

    2) Naming method parameters is tricky at first, and since you’ve been steeped in C# for a while, it’s not surprising that you named your example as you did. That’s similar to my thinking when I jumped from C# to Obj-C. But, it’s wrong. Instead of [obj modifyThisAndThat:@”this” thatString:@”that”], it’s more natural (and reads much better) as [obj modifyThis:@”this” that:@”that”]. Don’t make the mistake of putting what you’d use as the variable name in the name of the method.

    Good luck with your adventure!

  2. David,

    Thank you for your comments!

    Allow me to elaborate, as I realize I should have clarified how I was “implementing heavily” the use of “id”. I agree entirely that it should not be used in most instances, and instead it’s best to implement an explicit type. Where I DID end up using it a lot was when calling a potential abstraction layer that calls an external API. I created an abstraction layer to inject logging and centralization into database query calls centrally, and as a result, perhaps implied certain parameters dynamically (that were always going to be of x type). I felt it worked fairly well in that situation, but yes – I am working to migrate as many instances as possible to explicit types.

    I was reading about that this morning regarding naming methodology for methods and I agree. It’s an adjustment to make, and it’s a slow learning curve. For example, like you suggested, if I wanted to update say latitude and longitude values, I would name my method updateLatitude (or, updateLongitude) and create a second parameter called longitude. It’s “odd” I suppose, but then again in c#/java land the parameters don’t even have names to begin with. I suppose in theory I could simplify this even further by creating a coordinate object that contains lat/long properties and simply creating a method that says updatePosition or updateCoordinate (which, actually, I like the idea of even more). Like I said, it’s strange but I think in the long run it gets you to think about how best to organize your parameters more logically and create a more simplified return structure. Of this, I am a fan.

    I will continue my experimenting – it’s been an interesting two weeks. Still much to learn. 😀

    brian

  3. I had an interview with a large Silicon Valley company yesterday where one of the interviewers had similar gripes about objective-c. Both of you were very reluctant to give up the safety net that is called strict type checking.

    Having “suffered” through years of windows coding using C/C++ I really enjoy Objective-c. Thanks for the good read!

    • Chris,

      Thanks!

      Last year I went through a more painful exercise in having to enter the world of node.js with JavaScript. I’ll take Obj-C any day over the clunkiness of JS. The more I have used Obj-C, the more I really dig it. I just wish that it wasn’t locked to the Apple ecosystem. It looks like between MS’s relaxed .NET policies (http://msdn.microsoft.com/en-gb/roslyn) and Mono/Xamarin pushing forward, .NET COULD be cross-platform sooner than you think. I think a good MS-equivalent to Obj-C is C++/CX, but I’m not horribly keen on jumping into the Windows 8 world yet (nor are any of my clients).

      And yes, most things beat C/C++/COM dev – I’m glad to hopefully move further and further from this.

      Brian

      • There is no equivalent to Obj-C. Anything that comes from the .Net background will adhere to strict data type checking.

        ugh… JavaScript. I feel your pain.. Not really a language, but abused as one.

      • Chris – System.Dynamic (dynamic) is “close” but you of course have to incorporate the DLR. I used this quite heavily to get back values as dictionary objects from a schema-less data store. Performance was questionable but it made for some very dynamic JS-like code.

  4. Very interesting article. I’m am studying Computer Science myself. Mainly focusing on Java, Databases, design, computer architecture, network. Programming wise tho – focus on Java, which is too boring for me. Which is why I have started making my own website and learning some other languages. Like app development in Objective C. Not quite ready to really begin just that, cause I got many other things that require my attention lol. OH WELL; The reason I’m here (you might wonder) is because I have accidentally picked the same domain name for my webpage as you!! My name is Rasmus and “mus” in danish means “mouse” so yea lol. I like your site, way more interesting than mine! But yea still a beginner; web-wise. And i have only had my web-site for about a week. I will be sure to check in here sometimes – I enjoy your site 🙂

    • Rasmus – good luck 😉 I paid several hundred US dollars for this domain name to take it away from someone else. I think I will hold onto it. :)) I hope to write more in the future, I have been too busy with new job. I originally wanted to do this in Polska – myz or myzska for mouse but going English seemed to make more sense. Thanks for the compliments, maybe in this new year I will actually have time to write a lot more (I HOPE SO!) Ciao. – b

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s