Posts filed under 'rant'

Five Things that Suck About Objective-C and Cocoa

Things have been quiet here in this blog. Too quiet. As such, I’m keeping the name-five-things-you-hate-about-a-language-you-like ball rolling, having seen it rolled with zest and vigor by brian d foy, Titus, Jacob Kaplan-Moss and Vincent.

Without further ado:

Five Things that Suck About Objective-C/Cocoa:

  1. Syntax for NSString literals. For the uninitiated, in Objective-C code enclosing "insomnia" in simple double-quotes creates a C-style char[] string; if you wish to use the far more powerful and versatile Objective-C NSString class, you must add an @ (making @"insomnia"). Backwards-compatibility with C is a good and useful thing, but why require more keystrokes to do the most commonly-used thing? I myself last weekend puzzled over a wonderfully non-specific “invalid reciever” error for a long time before realizing that I forgot an @ when sending strings to an arrayWithObjects: method. Aside from that, why use the @-sign as a prefix for NSStrings when it’s used in a plethora of other places, such as @interface, @implementation, @end and @selector? Though 90% of my @-key-presses in Textmate are prefixes to NSStrings, I can’t have a keypress of @ automatically expand to @”" - there are too many other things to do with the poor little @-sign. The oft-neglected | (pipe or vertical bar, I’ve heard both) character is far less disruptive to the flow of typing.
  2. reallyLongAndCamelCasedMethodNamesGetAnnoying. I refer specifically to the lovely NSWorkspace method openURLs: withAppBundleIdentifier: options: additionalEventParamDescriptor: launchIdentifiers:
    And ObjC method names can be concise yet informative - take for example NSString’s compare: options: range: locale:. I must admit, this complaint is not entirely valid, especially considering Textmate/XCode’s fancy code completion.
  3. No operator overloading. Come on, guys - why reject this crucial part of Smalltalk heritage? I, for one, am sick of writing objectAtIndex and objectForKey: as compared to Python’s []. Though Smalltalk allows one to define new operators, I’d be perfectly happy to settle for a few overloadable operators (string concatenation is desperately needed).
  4. Mysterious helper methods. I didn’t know of the existence of NSHomeDirectory(), NSTemporaryDirectory(), or NSClassFromString() until very recently. True, this is my fault, but I think that F-Script’s idea of storing all of these methods in a singleton System object is excellent, and much more in line with Objective-C’s Smalltalk heritage. (Actually, I have a half-finished ObjC class that makes NSBeep() and all those other miscellaneous C functions into class methods; if there’s any interest, I’ll finish and release it. I suppose that makes this complaint invalid. Oh well.)
  5. File management is a mess. Essential code is scattered throughout NSWorkspace (in all its brain-dead glory), NSFileManager, NSFileHandle, NSPipe, NSDirectoryEnumerator, and NSData - few things are as infuriating as hunting down the correct class that does exactly what I want. (Actually, no. Finding a better solution after thirty minutes of hacking around some perceived inadequacy is worse.

So there you have it. To be honest, it took me quite a while to write this, mainly because Objective-C is such a great language and Cocoa is such a great set of libraries. I suppose that the imperfections in a consistently useful and friendly toolkits stand out, and in retrospect I sort of feel guilty for my picky attitude. After all, it could be much, much worse.


2 comments April 5, 2007

C == Assembly

Last month John Gruber asked the question “Is C the new assembly?”

It’s a tough question - what, exactly, does ‘the new assembly’ mean? The first things that pop into my head when I think of assembly language are these:

  1. Fast (or believed to be so)
  2. Ugly and difficult
  3. Nonportable
  4. Foundation for other languages

C has all of these attributes. (And more!) But does it have these attributes in such a way that it can be called ‘the new assembly’? I think so.
(more…)


13 comments March 4, 2007

Quartz Confuser

I’ve joined the CenterStage open-source project as a Cocoa developer, and I’m having a great time working on such a large project with such passionate and intelligent people. I have taken it upon myself to improve, such as I can, the quality of the application intended to catalog and organize movie files, known as BackStage. Since part of a media center application is eye candy, I recently renovated a Quartz Composer composition that shows a 3D DVD box for the selected movie. I had played with QC a few times, and found it to be a really cool and flashy tool with a user interface I had never seen before; I looked forward to working with it on a serious project.

I can say without a doubt that Quartz Composer is nothing more than a toy. For anything more complex than an RSS screensaver, the visual data mapping becomes a chore to connect and use. The patches, while a good idea in theory, turn out to be only barely usable in practice. There’s no patch for a clickable button, for a slider, for any widget which anybody might concievably want to use - but to hell with all that, we have a glowing Apple logo patch! If, as I needed to, you need an input to an Interpolation patch so that you can turn it on and off, too bad! You’re limited to what Apple give you. Additionally, Apple have not made the slightest effort to allow people to export, import or add new patches or clips - why? Why is this third-rate software bundled along with such first-rate tools as XCode, Interface Builder and the ObjectAlloc debugger?

And there’s no undo function. How can you possibly justify releasing a program aimed at developers that doesn’t have undo-and-redo support? Much to my dismay, the only solution I could find to work around this glaring lack of functionality was to a) have around seven different save files so that I could revert if necessary, and b) keep another scratch project in which to cut-and-paste everything that I remove from the actual project. This is absolutely inexcusable, and Quartz Composer’s inclusion in the fantastic Apple developer tools is nothing but an embarrassment, plain and simple.

What mental lapse caused the selection of Javascript as the only scripting language inside QC? The target audience - OS X developers, Cocoa and Carbon in particular - have a low likelihood of knowing, much less enjoying the use of Javascript. Ask yourself - why are there so many libraries which proport to, in the words of MochiKit, make Javascript suck less? Why, indeed, would Google make GWT?

“But Patrick,” you say, “Javascript was a good choice because you shouldn’t be writing much code in QC.”

Oh, really? Even if the assumption for your argument was valid - which it isn’t; due to the fundamental brokenness of the QC patch system and dearth of patches and clips, I am forced to write code - Javascript is still a bad idea. There’s no printf(), no wait(), curly brackets out the wazoo, and tacked-on OO. Sure, with Firebug it sucks less, but we’re not exactly working in Firebug, are we? No, we’re working in Quartz Composer, where the extent of debugging is the Log() function.

Even if you have to use Javascript - despite the fact that Ruby or Python both blow JS out of the water - you could have made it much, much better. Sure, patches are a good visual paradigm - now why not let us pass them around programatically, trigger scripts at various events, and include a text editor that does little more than highlight syntax? A visual paradigm should work on top of handwritten code, not in its place; if I really wanted to I could write a Swing/SWT GUI application with a text editor.

Nothing inspires confidence like discovering that the extent of the documentation is a .rtf file in the application’s directory; the meagre resources on the ADC site as regards QC serve mostly as a guide on how to put compositions inside Cocoa apps or - the thought is almost painful - Dashboard widgets..

Quartz Composer needs some serious work for it to be useful as anything other than a pretty interface to make screen savers. I have a hunch that there is a sizable market for an improved version of QC - hell, I’d pay for it if it made my life easier.

Moral of the story? Before labeling something as a developer tool, first make sure it’s not an abysmal piece of software.


4 comments February 15, 2007

Ruby + ActiveSupport + Facets - Cruft = Awesome

Libraries are the soul of a programming language. If your pet language doesn’t have any useful prebuilt libraries for web/game/media/network development, it will never have an audience beyond the world of theory and academia.

Though Ruby’s standard libraries are - and this is purely my opinion - not as well-developed or extensive as those of Python (see: sqlite3, wsgiref, tabnanny, etc.), they nonetheless serve the majority of developers well. However, Ruby has a unique advantage in the area of libraries in its support for metaprogramming.

Since Ruby code can modify built-in classes such as NilClass, Ruby coders are given a degree of freedom that I haven’t found in any other language. Need to change the behavior of a method inside the String class? Simply write the method, send two alias_method messages to the String module, and boom! You’ve modified the Ruby language temporarily to fit your needs. Awesome, huh? And if you write a library that includes these changes to the base classes, you can seamlessly change the language and pass your changes onto your friends: no mucking about with compiler code here, my friends! This is metaprogramming!

The most notable sources for extensions to the Ruby language are the Facets of Ruby project and the Ruby on Rails ActiveSupport extensions. Take a gander through err the blog’s ActiveSupport Advent Calendar - look at how many useful methods there are! String.at(), String.each_char, the Numeric bytes methods, attr_accessor_with_default, Symbol.to_proc - for the love of Dijkstra, why isn’t this stuff in Ruby? It goes beyond pragmatics into the realm of principles - if, as Matz asserts, Ruby is based on the Principle of Least Surprise, then why am I so surprised that all of this stuff isn’t in there? :) Why does String.each by default iterate through substrings separated by spaces instead of doing the unsurprising thing and iterate through each of the characters (as a string, not a byte)?

And then there’s the silly, crufty things in the Ruby stdlib, the modules which, though they are neat and illustrative of Ruby’s power, don’t deserve to be bundled and packaged along with every Ruby installation. Sure, Abbrev is neat, but does it really merit that spot right alongside Array? Abbrev is the kind of thing you keep on CPAN, not inside the standard library. What, exactly, does this lovely yet undocumented Foo class do, and why is it in my Ruby installation? Shouldn’t an RSS parsing library be stored on rubygems instead of in the main libraries? It seems as though Ruby is leaving out vital ingredients and adding superfluous ones.

I call upon you, all you designers of Ruby - especially Rubinous, YARV, and JRuby - take a step back and look at your standard library. Cut out parts you don’t need, add parts you do, make a few organizational changes and soon people won’t need to follow “Ruby is better and purer than #{competing_language}” with “but its library support is sorely lacking.” Everybody wins.


2 comments January 29, 2007

Why I Dig Objective-C

I apologize if this entry is incoherent or trivial. But I need to build up the habit of blogging.

I recently picked up a copy of Refactoring. I hadn’t heard of that book before I read Steve Yegge’s thoughts on it - indeed, my entire concept of refactoring had previously been limited to Eclipse’s built-in tools. To describe this book as an eye-opener would be an understatement; not only has it taught me many coding strategies (upon reading the entry for Introduce Null Object, I practically screamed “Why didn’t I think of that?”), but it’s also changed many of my ideas about the way I code.

Fowler’s clear, direct writing is one of the strengths of Refactoring; during the book, he introduces the concept of the code smell - a term which I had not heard before, and which perfectly describes a situation with which I have been familiar ever since I started coding - and points out that a sure-fire sign of smelly code is the presence of many comments; if you need to explain a method in excruciating detail, then you’re probably made it too complex.

One of the reasons why I adore Eclipse for Java development is because it shows JavaDoc attributes in its Intellisense methods - I don’t need to navigate through the Java API when I can hit Ctrl+Space and see the arguments the method takes. Without Eclipse, I have to either rely on memory (and in my opinion, life’s too short to memorize the proper sequence of arguments that a proper BufferedReader instance takes) or waste time navigating the API docs.

Objective-C, on the other hand, doesn’t have this - because method signatures can be broken up into multiple pieces. Take a look at these two method signatures - taken straight from the documentation:

- (NSRange)rangeOfString:(NSString *)subString options:(unsigned)mask range:(NSRange)aRange

versus:

public NSRange rangeOfString(String s, int i, NSRange nsrange)

When looking at the first method signature, I know that the second object will be an integer that controls the masking - simply by virtue of the fact that, like its parent Smalltalk, its methods recieve messages via keyword messaging. I can also make the assumption - and it is only an assumption - that - (NSRange)rangeOfString:(NSString *)subString options:(unsigned)mask and - (NSRange)rangeOfString:(NSString *)subString are valid methods. With the Java API, on the other hand, I have no clue what the second argument does; if I had to know, I’d need to be using Eclipse or XCode, not Emacs or Textmate. Textmate’s Cocoa completions don’t show any HeaderDoc information - but that doesn’t matter: the keywords tell me what the arguments are used for.

It seems to me that Objective-C’s syntax lends itself to clarity by its very nature; Java, on the other hand, depends on other programmers being clear and helpful in their method signatures. And as a short perusal through The Daily WTF reveals, programmers can be very, very unhelpful at times.


1 comment January 12, 2007

Blocks != Functional Programming

Joel Spolsky is one of my heroes. He has a vast amount of insightful articles that rank among the clearest and most relevant software writing today, and his blog gets more hits in a day than mine ever will. (Speaking of which, I hit 2000 visitors yesterday - around 10x more than I ever thought I’d get.) He’s a very smart cookie, and when he speaks, people listen. But last week, while browsing the top Reddit articles of all time, I was surprised to see his article Can Your Programming Language Do This? at #4. While it’s a good primer on Javascript abstraction, I don’t think it deserves as many points as it recieved. I spent the next few days thinking about why this article bothered me so much - Joel certainly didn’t say anything untrue, attack any favorite language of mine, or make some outlandish claim. But then I realized that Joel’s article fit together in a pattern of recent articles, all of which bothered me slightly.

Here’s what I realized: it seems that every language under the sun is being evangelized as an excellent functional programming language simply because it supports a few paradigms from FP.

Or, restated: Anonymous functions do not a functional language make.

The most egregious example of a pundit claiming a language is functional when it’s clearly not is Eric Kidd’s well-known Why Ruby is an acceptable Lisp. Kidd tells us explicitly that Ruby is a denser functional language than Lisp - and I’ll be the first one to admit that if I were to debate the “denser” part of that sentence, I wouldn’t know what I was talking about.

But Ruby is not functional - Wikipedia calls it a reflective, object-oriented programming language, and I agree with them. Yes, you can have block arguments to methods, continuations, generators, reflection, and metaprogramming - but it isn’t functional, for two reasons.

1. It’s hard to carry around functions as objects.

I really don’t know why Ruby hates parentheses so much - it’s probably part of its Perl heritage. In Ruby, you can call methods without sticking superfluous parentheses in there - take a look at this Python code:

” I’ll write about Cocoa soon; disaster struck the app I was writing “.strip().lower().split()

Now take a look at the equivalent Ruby code:

” Apple’s releasing a tool
with XCode 3 which completely supersedes my Cocoa app - so I'm very depressed right now ".strip.downcase.split

Though you could put parentheses in front of strip, downcase, and split, Ruby will work just fine without them. Now, this feature makes for far fewer parentheses, thereby making code significantly more readable. But what if I want a previously-declared function as an argument? If I type in the name, Ruby will just evaluate the function. Sure, I could use the kludge that is Symbol.to_proc, but that’s ugly - and it wraps the function inside a Proc object, which has to be called with the call(*args) method. And that’s just ugly. In Python, all you need to do is type the function’s name to use it as an object, and append a pair of parentheses if you need to call it.

2. Variables are.

A purely functional language only has immutable variables. Ruby doesn’t. (Yes, I know LISP isn’t purely functional. But it adheres to so many other FP paradigms that we can overlook that.)

But I’m getting distracted, so I’ll cut the above point short.

Anyway, what I wanted to say was this - just because your pet language has support for anonymous functions/closures doesn’t make it a functional language. Sure, Python has lambda and list comprehensions (which are taken from Haskell, a purely functional language) - but it’s not functional, it’s object-oriented. Yes, Ruby has blocks (even if you do have to wrap them in Procs), but it’s not functional. Javascript may have support for anonymous functions, but its syntax can be traced back to Algol and the birth of imperative programming language. Hell, even Objective-C has blocks if you include the F-Script framework, and it’s the farthest thing from functional there is.

In conclusion, don’t say your language is a functional one just because you borrowed a few ideas from Lisp. If you want a real functional language, try OCaml, Haskell, ML, or Scheme. Calling imperative/OOP languages functional just makes the term meaningless.


10 comments January 2, 2007


About Me



I'm a college freshman, passionate about technology, programming (especially Cocoa and Python), and Apple.

By the way, 'important shock' is an anagram for 'Patrick Thomson'.

Meta

Links

Categories

Top Posts

Blog Stats