Sharp and Objective

This may come as a surprise for some people, but I’ve been using C# and Objective-C both for almost exactly as long (between three and four years). What you might call my current day job is comprised of writing C# code.

Here’s the thing with .NET. .NET is great. It’s not great as the One True Platform for Windows development. On the other hand, it’s not “great for something that’s from Microsoft” either. It is great on its own merits, perhaps, and it is a shame that its merits are so tightly coupled to provide an excuse for C# to exist, because they are each shackled to eachother.

.NET is now, and has been for a while, at least perceptibly noticeably faster than Java. I’m personally way better off with C# than with Java. What I think I’m doing at this stage is establishing that I really quite like .NET and C# both, and that even if I didn’t, I’d think they were more than reasonable efforts for a technology-of-the-week company like Microsoft.

That said, there’s a big technology - and philosophy - divide between C# and Objective-C, and between .NET and Cocoa. Coding in both of them means that I’m soaking both my feet in water of different temperatures. I am in a fairly unique position to stand with one foot in a bucket of cold water and one foot in a bucket of hot water and announce how, on average, I’m feeling pretty good. To wit: When I’m in C#, I end up missing Objective-C. When I’m in Objective-C, I end up missing C#. Here, therefore, are some reflections, most prompted by a chat I had with Scott earlier today.

  • I love generics. This appeared gradually and surprised me at first, but it’s quite true. Generics, if you don’t know, means that you can supply types to classes when using them - like List<string> or Dictionary<string,int> - and have instances whose methods change to accept those types. I’m generally firmly in the duck typing camp, but C# and Objective-C both need compiling, and when there’s a compiling stage, you can get warnings and errors. The Objective-C code for storing, say, a string in an array, makes it impossible to know when you’re passing in non-strings without doing type checks manually beforehand, or creating tuned methods that only accept the given type in order to generate the standard compiler error.

    C#:
    List<string> strings = new List<string>();
    strings.Add(”xyzzy”); // takes only strings
    strings.Add(15); // compiler error
    string x = strings[0]; // guaranteed to be a string
    // or non-existant (yielding an exception)
    strings.Remove(0);

    Objective-C:
    NSMutableArray *strings = [[NSArray array] mutableCopy];
    [strings addObject:@”xyzzy”];
    [strings addObject:[NSNumber numberWithInt:15]];
    string x = [strings objectAtIndex:0];
    [strings removeObjectAtIndex:0];

  • The previous example brings to mind another wider look at the same subject - lists. In Objective-C, you get a fairly simple choice for an array: mutable or immutable (default). Being the strict C superset that it is, you can also drop down into C arrays and pointer trickery.

    C#, on the other hand… Someone at Microsoft enjoys having a dozen deceptively similar - but ultimately all a little different - ways to solve this problem.

    At the bottom end, you have C# arrays, which are similar to C arrays. They are fixed-size and immutable. They’re also alone in being natively initializable via literals. A low-level class, System.Array handles the juggling, and each Array is typed for a specific type but using a special, C array-like syntax (string[]), instead of generics syntax. This is because generics were introduced in C# 2.0 and .NET 2.0, and the Array has been along (with the same special treatment) since the very beginning.

    Slightly above C# arrays are non-generic lists. The ArrayList is an almost perfect parallel to Cocoa’s NSMutableArray - something that stores only objects. You can store anything in an ArrayList. These were the only mutable all-purpose lists in .NET 1.0 and 1.1.

    Above ArrayList lie generic lists - List<T>, where T is to be substituted to a type you pass in when you instantiate, subclass from or otherwise use the class.

    So far, so good. What’s wrong with the hierarchy is everything above this point. Imagine for a second that you have a control called a ListView. (Hint: Microsoft does.) Imagine further that you want a property inside to return the list of items for your pursual. Imagine also that these items are all of class ListViewItem. If you were Microsoft, you might want to use, simply, List<ListViewItem>. Too bad you’re not Microsoft, and too bad ListView was around in .NET 1.0, way before generic lists.

    In these kinds of situations, there are special purpose lists (belonging to some sort of fuzzily defined grouping called Collections meaning basically “objects that have other objects in them”). In fact, there are fields, endless fields, where Collections are no longer being born, they are grown. So what do you end up with? ListView.ListViewItemCollection - a special-purpose class if you ever had one - specifically designed to hold ListViewItems. To be fair, ListViewItemCollection has at least one speciality - that of being able to access ListViewItems by passing their Key property as the indexer - literally like collection["key"].

    Just having several hundred very special-purpose classes isn’t a valid point of criticism, though. The strange thing is that many of them drop (or choose not to implement) small parts of functionality. Some might not ‘do’ enumeration (the technology that enables foreach loops), some might leave out Contains-like functionality to check for the existance of a value. It’s all very confusing and a very poor and uneven experience for the programmer, especially since the class’s raison d’être is often deeply hidden in the documentation, if mentioned at all.

    As much as I like generic lists, I despise most of the rest of the trickery.

  • Boxing! C# gets boxing (wrapping non-objects in objects) right - int and double and string and friends are supposedly primitives, but are surprisingly well-mapped back and forth to real classes to the point where you really can’t tell unless you’re profiling. In Objective-C, on the other hand, the boxing process is entirely manual, like: NSNumber *integer = [NSNumber numberWithInt:8]; int x = [integer intValue];

  • C# has constructors. Objective-C has alloc-init method pairs, designed to be called in a chain, or class convenience methods for doing both and returning an autoreleased object for you. When you call a constructor in C#, it first creates the object for you and then calls the appropriate constructor, whose objective it is to set up the object, already assigned to this. In Objective-C, you’re responsible for returning the object self. In both languages, you’re responsible for calling the appropriate superclass constructors.

    The C# way involves less manual labor and book-keeping. In Objective-C, you can return an object that has already been initialized, say, if you’re keeping a cache of objects not supposed to be created twice, instead of the object just created.

    There’s no correct answer, but the different approaches will be sure to have you curse at one time or another.

  • The class models in C# and Objective-C are vastly different.

    Objective-C has bona-fide class methods, eligible for specification in Objective-C protocols. C# has static methods, not eligible for specification in C# interfaces. Objective-C does not have class variables, but it does inherit static variables from C, which works almost the same. C#’s doodads are also called static variables. In Objective-C, no instance variable can be assigned immediately on declaration, but must be instantiated in the init instance method; in C#, both static and instance variables can be assigned immediately, and to the return value of any statement, including functions. (Since Objective-C inherits C’s static variables, you can only assign literal values to them on declaration, and not return values of methods or functions.)

    C# has dynamic dispatch off by default - it’s opt-in by the use of the virtual keyword in the method declaration and the override keyword in the ‘overriding’ method. Classes can be prevented from containing virtual methods by being declared with the sealed keyword. It’s also possible to declare abstract classes, which have abstract methods that have to be overridden and use dynamic dispatch. Objective-C has dynamic dispatch on by default. (Dynamic dispatch is being able to define the method foo in class A, introducing class B that inherits from class A, implementing method foo in class B, and having class B called when you call the method foo on class B.)

    Finally, C#, like Java before it, and Objective-C before it, uses a policy of one superclass, n interfaces/protocols. In Objective-C, the way of specifying an interface type is ObjectClass<Interface>; in C#, it’s just Interface. (C# has one root class, System.Object, which everything implicitly inherits from by default; Objective-C allows defining new root classes and provides the id keyword - in actuality the runtime’s data structure of an object - to specify ‘any object whatsoever’.)

There’s a lot of ground to cover on C# and Objective-C, and on .NET and Cocoa. The origins and fates of .NET and Cocoa are, dates taken out of the equation, remarkably similar: objective-oriented juggernauts gaining traction with smaller and newer apps, but largely failing with the cross-platform market and the big, heavy, thousand-year apps.

What best sums up my feelings about Objective-C and C# is this: Objective-C+Cocoa is smaller and better defined, and scores a higher average level on the graph. However, C#+.NET’s extremes - both good and bad - are more pronounced. At its best, it’s above Objective-C+Cocoa by a good deal; at its worst, it’s right down the chasm with no hope of improving.

I am certainly hoping that both teams are watching each other with open minds.

“Creative”

When did we start calling art directors, copywriters and designers “creatives”? Creative is an adjective. I’m more creative than some of the “creative professionals” I’ve met. For that matter, what do you call an amateurish “creative professional”?

Tell you what: I’m going to steal an adjective too. I am a kick-ass professional, and I hope the rest of my chums in the kick-ass industry join me.

Nerves, and the striking thereof

It seems that my HTML5 switch has sparked some thoughts.

On the del.icio.us page for the article, Jonathan Rentzsch writes: “Circa 1999 I predicted XHTML would Win™. I failed to consider W3C’s complete bungling and now agree with Jesper, the future is HTML5. So long XHTML.” Also on that page, Alessandro Fulciniti wonders: “”From this moment on, Waffle is served in HTML5″… Is that a good idea at the moment?”

The story as I’m concerned is very simple. When it comes to things like Windows vs [Your Linux distribution] vs Mac OS X and so on, it’s often really not all that clear-cut. When you have powerful tools that you’re comfortable with, it’s often hard to change just for the sake of changing to something that’s technically better and more capable - ie some folks stay with Windows 2000 and a bunch of programs that they are happy with and don’t wish to upgrade to Windows XP or Vista, or even jump ship to something that’s got plenty of programs and take up less resources than Windows 2000.

That’s not how it is with HTML5. HTML5 is technically clearly superior at being a specification, and as has been discussed at length, mostly by me, it’s much more closely mirroring the direction in which the people who actually use HTML would like to take it. From what I’ve seen, there’s very little debate that HTML5 is the better spec. What HTML5 has going against it is just that it’s not gained wide-spread acceptance yet. Opera and Mozilla are behind it; Google is funding Ian Hickson (the editor) and, I assume, Mark Pilgrim; at least the better, non-legal-dept., half of Apple are throwing it out there and poking it with a stick. Other than that, the rest of the world, at least the rest of the world that lies in Redmond and heads W3C chairs, doesn’t seem to want anything to do with it.

Luckily, this is where common sense comes in. Adopting HTML5 full-out would have taken a few tag changes (and not actually work at the moment); adopting HTML5 investigatingly takes literally less than two minutes. Very few changes need to be made and your site will work just fine. What you’re doing is symbolic, but it’s important. You’re running a stake into the ground, and you’re saying: “This is HTML5 country. I am for a future of the web that means your uncle will not have to stop at the fact that you forgot to close an entity reference on line 20, column 8, when you or your HTML generator mess up. I know a great spec when I see it, I look forward to it, and I want to help make it happen.”

I encourage you to do so. The HTML5 spec runs 191 printed A4 pages. What you need to know is that they are mostly really great and that you won’t need to read 189 of them.

Update: Again from the del.icio.us page; the signature ‘numberless’ notes “ah crap. Now do I need to re-learn HTML? I wish I understand this stuff better.”

You don’t have to re-learn HTML at all. Nearly everything is drop-in ready. There will be a bunch of new tags that you’ll want to use to improve the readability of your markup - <div class="x"> and <div id="y"> only take you so far, and the closing tags are hell - but you can’t use them just yet.

Update: Apparently, depending on how you define it, Safari may be thunderously incompatible with feed autodiscovery.

According to the Atom autodiscovery specification: Well, the ‘RSS’ autodiscovery button stops appearing when you put in another relationship in addition to alternate in the <link> element pointing out the feed. In every single current (X)HTML specification specifying the <link> element, the rel attribute is defined to be a space-separated list of relationship strings. The correct behavior is to watch for “alternate” as one of these values in the list - Safari bails out after encountering another.

The RSS autodiscovery specification, on the other hand - to be fair the one n8han should use since he serves RSS, but nevertheless just one of the two standards Safari should adhere to - specifically acknowledges that the HTML specification allows more, but dictates that “alternate” must be the only value and must be in lower-case.

See also: Safari RSS autodiscovery sucks.

Remote Remote

iLounge speculates that Apple might introduce a Universal Remote. I’m with them. I hope they’re right.

The Stockholm area just shut down its analogue TV net. I have a not-entirely-new TV (it’s 4:3 and thus ancient, and it’s not even an LCD TV) and a comparatively small and easy-to-use DVB-T decoder. The decoder remote (credit card-sized) has 29 buttons. The TV remote (monolith-sized) has 63 buttons. Sixty. Fucking. Three.

The big, big, big problem with most of the remotes - especially universal remotes, but any remote - the big problem is that they think you’ve got to have everything there. They think you need more or less 29+63 buttons. That’s not true. Here’s what I want: Power on. Volume up/down. Mute. Channel up/down. That’s 1 + 2 + 1 + 2 = 6 buttons. Teachable, of course - flip the record switch, fire any old IR remote button press up its rump, hit a button, flip the record switch again.

Not enough? Add some more: Keypad. Info button. Switch source. That’s 6 + 10 + 1 + 1 = 18 buttons. It’s no Apple Remote, but it’s positively anemic compared to what’s out there. Even if you further add a Guide button, directional buttons and OK (needed to navigate said Guide) and Teletext, it’s ‘just’ 25 buttons for both devices with some clever programming - and by clever programming I really just mean sending out different signals. Of the two remotes I use, no buttons overlap. Volume and power on on the TV remote, the rest (’channelly stuff’) on the decoder remote.

What would I like most of all? A 3-inch touchscreen remote. I know, I know. Even Philips charge through the nose for a version bundled with crapware. (A friend got one, five years ago. He’s up to his fourth attempt to configure it. Configure it!) Still, though… If only…

Older posts »