Next article: Using FileMerge with subversion
Previous article: Name/comment conflict
Tags: dashboard rant
I've spent a good part of the last few days working on a Dashboard widget, trying to get it ready in time for the release. The good news is that I got it done and working. The bad news is that Dashboard seems like a horrible, badly-designed development environment. The main purpose of this post is to rant about that, but it'll also include the occasional tip for writing your own widget.Dashboard is, basically, a pretty wrapper around WebKit. A Dashboard widget is simply a web page, usually with fancy dynamic scripting. This was probably intended to make it easier for non-programmers to create widgets. Sounds good, right? This approach causes significant problems for Dashboard developers.
The first problem is that doing the entire widget in HTML throws out all of the good GUI builder stuff that we've come to expect from Interface Builder on OS X. Using Interface Builder and Cocoa Bindings, you can do a lot of things without writing any code.
In the widget I worked on, I ended up having a severe problem with a Dashboard-specific API, namely the widget.system() function. I couldn't test in Safari, I couldn't use any kind of debugger, and it was a nightmare to work out. I finally abandone d the widget.system() interface altogether and wrote a widget plugin to do the work instead.
And this brings us to our first Dashboard hint! Avoid widget.system() at all costs when working with any significant amount of data. It's highly prone to lockups, intermittent failures, deadlocks, etc., whether in synchronous or asynchronous mode. I would have requests that worked fine and then failed the second time they were requested, locking up my widget and making it unusable, with no indications as to why. I tried every possible workaround I could think of, but the problems never went away until I ditched the widget.system() call and switched to using a widget plugin. I suggest you short-circuit the problem and simply make a widget plugin to begin with; they're ridiculously easy to create.
Another problem with widgets is that they all look and act totally differently from everything else. This is a problem both for users and for developers. It's a problem for users because, in addition to the already confusing array of Aqua, Metal, Wood, Milk, etc., there's now also a zillion different Dashboard interfaces.
It's a problem for developers because they have to actually, create these unique interfaces if they want to fit in with Dashboard. (Apple explicitly discourages using standard Aqua widgets; you're not even supposed to use a standard HMTL submit button, but rather create your own graphical submit button.) So every time you want a button, a scroll bar, a slider, a radio button, a checkbox... you have to make your own graphics and write a bunch of support code behind it.
19 comments:what a crybaby…but I do agree. :)
eddienull - 29 April '05 - 11:18Dashboard is mostly for ‘web designers’ who are used to working in crappy environments.
john - 29 April '05 - 12:39I think it’s a step in the right direction. Opportunities for full Cocoa/Carbon programmers to create tiny little useful programs has been here for a long time. Dock drop-ins, Menu extras, Contextual plug-ins and small programs – you name it.
Dashboard adds not much new in this respect – just a nice Expose effect and an universal F12 system-wide activation. That’s it. So the real BIG feature, in my oppinion, is that is raises the number of potential developer by one or two orders of magnitude.
Exactly this is why I think Dashboard will be huge. (And yes – I do agree, from program-design perspective, it’s a huge step backwards. It’s just that Dashboard widget creation is not programming – it’s scripting.)
zzen - 15 May '05 - 17:54I don’t get it – if you’re a Mac developer experienced in Interface Builder, why not just write an actual Cocoa app instead of a Dashboard widget? You sound like Lance Armstrong with a set of training wheels, complaining that they don’t let you corner as tightly as you’d like.
Nat Irons (link) - 16 May '05 - 21:17I wrote a widget in about 4 hours to download weather radar images, resize and display them. The difficulty was to make it only request updates when someone is looking.
There is a most helpful debug() subroutine at the end of Apple’s world clock which allows you to print debug messages to the screen.
At least the standard widgets are readable source, and you’ll need to if you want to see how much code it takes to do the flip effect.
Scott Schram (link) - 16 May '05 - 21:28I’m not writing an actual Cocoa app because actual Cocoa apps cannot be displayed in the Dashboard. If I want something to be in the Dashboard, the I have to write a completely separate thing. This is one of my big complaints; Apple simultaneously created a new user interface area, and a new API, but has tied the two together strongly. I can’t use Cocoa to make Dashboard widgets, and somebody who actually likes the Dashboard programming environment can’t use what he knows anywhere else.
Waldron Faulkner (email) - 17 May '05 - 17:22Dude, if you want IB, build a Cocoa app!!! Dashboard is not for you! It’s for the rest of us!
pb (email) - 19 May '05 - 15:50I’ve had some trouble with widget.system() much as you describe…with larger amounts of data. My next plan of attack was precisely what you describe – a plugin which uses NSTask to provide the same functionality – but I wanted to check around online to be sure I wasn’t missing some silly fix. Anyway, I acknowledge that the above wouldn’t be difficult, but even due to that fact, would you consider simply making your plugin generally availible for myself (who could make it, but I’m lazy) and others (who might not know any Cocoa at all) to make use of?
To Eben: my use of widget.system() was only to avoid writing a plugin; I didn’t actually need to call through to the shell. As such, my plugin doesn’t do anything with NSTask or anything like that. If you want an example plugin, there’s a good one in /Developer/Examples/Dashboard called Fortune.
Chad - 29 May '05 - 17:18Yeah, widget.system has some flaws… Here’s some info I wrote up on my trials and workaround with widget.system:
Stacey Abshire (link) - 04 July '05 - 13:32The big problem with widget.system() is that the input it reads can only be 4095 characters long. It looks like that xmlHTTP code is the way to go—I’m pleased google found this page!
Brenda (email) - 09 July '05 - 19:08The 4k limit for widget.system() is probably because of the size of the kernel’s pipes. A naive way to implement a subprocess is like this:
wait for process to terminate
read contents of pipe
But if the pipe fills up, then the process will get stuck waiting for you to empty it, while you’re waiting for it to die. It’s a common bug, but it’s shocking that Apple managed to get it wrong for this. You’d think they would have tested it with output larger than 4k; what were they doing during those 18 months of Tiger development?
Anyway, Brenda, I’m happy to see that this article was helpful to someone, even if it was indirectly.
On the plus side though, if you’ve got good reuse skills they will take you a long way past these problems.
For example I managed to easily reuse the scroller, fader and stretcher examples from apple, and yeah they were buggy, but quite easy to fix.
If you are having trouble debugging, turn development mode on in Safari and Dashboard, and get Mozilla which has a great debugger, Venkman.
Debugging scripts can also be faster than debugging compiled code, since you don’t have to wait for compiles to finish, although fix and continue helps for that.
I was betting my business on writing cocoa apps, now I’m going for widgets, in the short term at least.
Mike Amy (link) - 12 July '05 - 10:34That scripting language comment is a total red herring. You can write Cocoa apps in at least half a dozen scripting (by which I mean that there is no compile-link-run cycle) languages, including Perl, Python, Lisp, Ruby, Lua, and F-Script, if that’s all you want.
Being able to reuse code is another red herring. Wonderful that you can reuse code to get something like a scroll bar or window resizing; meanwhile, I’m busy getting real work done in Cocoa, because I get those features for free.
An environment’s worth is not measured in how easy it is to do easy things, but how easy it is to do difficult things. Easy things will be easy regardless, but a poor environment can make difficult tasks nearly impossible. Likewise, it’s not measured in how easy it is for newbies, but how easy it is for people who have taken some time to learn it. You’re only a newbie for a little while, but you have years to be an expert. In both of these respects, Dashboard falls down hard.
Dashboard is great for putting together cute demos, but it’s horrible for making anything truly interesting, and not terribly user-friendly to boot.
eobet (link) - 16 June '06 - 04:05That technote is almost a year old and brings nothing new to the table. All it describes is some very basic debug-via-printf which is really pretty horrible, and was of course possible (and I was doing it) when I wrote the rant. Apple’s unreleased Dashcode looks like it will be the answer to many of my complaints (although the complaints about having to do everything in HTML/CSS/JS and being forced to do a lot of custom controls etc. still stand) once it finally comes out.
Mike Ash - 16 June '06 - 13:23
No comments have been posted.
Add your thoughts, post a comment:
Spam and off-topic posts will be deleted without notice. Culprits may be publicly humiliated at my sole discretion.