It’s an interesting series of articles and the New York Times interactive feature is well worth browsing. And the problems they address are also relevant to web site design and to application development: by clearly segregating instruction from function (in this case, how to fill in the ballot from the ballot bubbles themselves), it makes figuring out the ballot easy and fast.
Category Archives: Commentary
WordPress for the iPhone
Now I can blog on the fly with a new toy for my iPhone! Weeeeeee…
It’s why God created tool tips.
Don’t hide or disable menu items.
This is what separates the User Interface men from the User Interface boys: the suggestion “Instead, leave the menu item enabled. If there’s some reason you can’t complete the action, the menu item can display a message telling the user why” is the most Gawd-aweful suggestion I’ve heard in a long time.
The correct answer, of course, is to create a tool tip which pops up over the disabled item which indicates why the item is disabled. That way we have instant feedback on what a user can do, and if the user is puzzled, he can easily discover why a particular item isn’t currently selected.
In Java, you can do this by calling JMenuItem.setToolTipText(); set the value to an explanation why the menu item has been disabled, and the explanation will pop up when the user hovers over the disabled item.
On the Macintosh, with Cocoa you can do this by setting the ToolTip text field in the IB .xib file with the text describing the item; call NSMenuItem’s setToolTip: method in order to update the text for the disabled menu item.
And even Windows has the ability to create tool tips for disabled menu items, though it takes a hair more work: by watching for WM_MENUSELECT notifications you can then pop up a CToolTipCtrl, or update a status bar text line, showing the appropriate text if the item is disabled.
So as much as I appreciate Joel’s comments on the software development industry, on this particular item, ummmmm… No. I agree more with John Gruber: you’re much better assuming your users are clever. But if your menu command structure contains commands which are just odd or hard to puzzle out at first glance, tool tips are much better than an idiot modal dialog box. It’s just more elegant.
Java sucks and Objective-C is great? Puuuhhhllleeeeaaassseee…
I still remember the brouhaha raised over Java on the Macintosh, and pronouncements by many of the Macintosh Technorati that Java sucks. (I believe Gruber’s words were Cross-platform crippity-crap Java apps.)
By all of the various posts I’ve seen, I’d think that Java was a complete wasteland while Cocoa was the rolling green hills of programmer nerdvana.
Okay, that’s fine. I set forth building a new custom application for the retail market, and faced with the various choices for building a cross-platform system I decided to build a simple data core in C++ with the Mac UI in Objective C++ and Cocoa, and the Windows UI in MFC/C++. (The common data core is to assure that data can be easily shared, but is a very small kernel: perhaps right now about 10% of the overall code base. So I’m not trying the YAAF-lite solution of building a UI framework on top of Objective C++ or MFC; rather, I’m building the UI twice, with a common set of data accessor routines at the bottom of the stack.)
Nerdvana? Hardly.
Today’s fun-filled afternoon was spent trying to figure out how to do an easy gradient fill for a custom control so it doesn’t have a flat, 2D appearance. With the sheer beauty of the Macintosh UI environment, you’d think would come convenience routines–but not really: the amount of work to build a gradient filled background was about what I’d expect using the Graphics2D class in Java.
And I’ve come to a couple of conclusions while engaging in this little exercise.
(1) The advantages outlined in Jens Alfke’s essay about making superior interfaces only gets you half-ways through the front door. To make it across the finish line requires a lot of nit-picky detail work that the Macintosh Cocoa libraries only sorta help you with. Sure, there is plenty of support for animation stuff which is really freakin’ cool. But to draw my simple gradient in a way which was portable back to MacOS 10.4 (and my business app needs to be supported by the current version and the previous version of MacOS X) required about 120 lines of code–which, while it took a couple of hours to toss together and test, wasn’t the easy exercise that many Cocoa advocates seem to suggest awaits all who come to the Cocoa big tent.
This isn’t to say that there aren’t advantages to Cocoa over Java Swing or MFC. However, there are many places where Java’s framework has a clear advantage: the JScrollPane class, for example, is a lot more flexible to work with than the NSScrollView class. And don’t even get me started on NSTreeController, though Rentzsch’s comments on enabling NSZombieEnabled was a god-send.
A corollary to this is:
(2) Macintosh applications look great because Macintosh programmers sweat the details, not because the Macintosh environment makes sweating the details any easier than in Java or Windows MFC. It could very well be the Macintosh market: people expect pretty applications, and so a lot of attention goes into making pretty applications on the Macintosh. This attention to detail, however, doesn’t really exist in the Windows market–and don’t even get me started on Enterprise Java applications. (I will agree with Gruber on this: a lot of Java Enterprise Swing applications do look like crap.)
However, this does not mean that the look and feel of Java applications are doomed, any more than it means Cocoa applications are uniformly great–nor does it mean to get the same level of greatness on a Java application you must spend two or three times more effort than on a corresponding Cocoa application. (And it’s not like Cocoa has inherently better support for creating icons like Panic’s beautiful icons, as opposed to the type of 1980’s icons you see in Java: nowadays they’re both PNG files.)
This attention to UI detail, by the way, predates Cocoa, and even predates NeXT, as anyone who ever read the original Apple Macintosh Human Interface Guidelines would attest. In fact, if anything, NeXT programmers and Cocoa programmers prior to the Apple merger weren’t exactly producing stellar examples of UI goodness: I’d say the biggest problem that I saw as an outsider when Apple and NeXT merged was having Apple’s attention to UI detail and usability drilled into the NeXT programmers–much to their shock. Even today I’d say that Apple’s attention to UI detail is only about 90% of what it used to be in the Mac OS System 7 days.
And that attention to UI detail wasn’t because Mac OS System 7 was a fantastic object-oriented development environment. (I should know; I was writing software for System 6 and earlier.) It was because you would sweat details like the fact that on System 6, an OK button was offset 14 pixels–not 15, not 13, not 8–from the lower right of the screen and was 58 pixels wide, not 57, not 59. (Now I will say that System 6 was superior in one aspect to Microsoft Windows–a superiority which existed for quite a few years: Macintosh QuickDraw’s CopyBits() routine was light-years ahead of any bit blitter available on Windows or on X windows: it would anti-alias, crop, stretch, extrapolate, and even fold your laundry and put it away for you, giving the Mac OS System 6 platform a clear advantage over Windows 3.1. But Windows and X windows caught up in that department long ago.)
So anyone from the Macintosh Technorati who suggests that Cocoa is inherently superior–I’m used to religious wars, even from people who should be intelligent enough to know better.
Oh, and for the curious, I’ve attached my GraidentFill class in Objective C using the CGShading routines to handle my custom control shading. It’s really not as flexible as the 10.5-only NSGradient class, but it does the trick.
Common edit design pattern.
Messaging is an important aspect of application development, especially in a UI-driven application.
While working on the undo architecture of an application I’m putting together, I ran into an interesting problem, and a general-purpose architecture which could handle this popped into my mind, that I thought I’d jot down for future reference. Feel free to borrow the idea if it seems useful, and pardon me if the idea is blindingly obvious.
A typical editing architecture essentially can be represented as a state S which represents the current state of the document, and a set of messages fi which transforms the state Si to a new state Si+1. Each message f represents an editing change to the document S.
Now a typical undo architecture handles undoing messages by storing the creation of messages f’ which is the inverse of f. When an edit operation f is generated and document S is transformed, an inverse operation f’ is created (in practice, as part of the code implementing the change message f) and added to a stack of undo operations, which can then be used to undo the operation on S. In theory as long as each operation has an inverse, we can maintain a perfect undo stack. In practice, of course, user considerations muck up this perfect world: for a text editor, for example, individual keystrokes f(key) may be coalesced into a single insert operation for purposes of an undo operation. (In that case, the easiest way to maintain this undo state is to allow the code creating the f’ function to peek at the top of the undo stack, to determine if the existing top of the undo stack can simply be extended.)
A second thing that one can do with messages f to a state S is that you can then use those messages to determine if S has changed, in order to update the user interface element displaying the document S. For example, if you have two text editors opened to the same document, each keystroke f(key) can trigger a message from S (call it ui) which triggers a user interface update.
Now I was working on an application which had multiple user interface elements editing the same object, and I was generating messages ui which was being used to update my user interface elements. The bug I had was that, when I would edit a state, the user interface would be updated–because my UI handling code would do:
myDocument.sendEditRequest();
updateMyUserInterface();
And of course on undo, the undo code would do the equivalent of:
myDocument.sendEditRequest();
It strikes me that there are two solutions to this problem, though unfortunately most UI frameworks I’ve encountered makes the second solution a bit harder to implement in a natural way.
The first solution is to always use the state changed messages ui in order to drive the user interface refresh cycle. Sometimes this may not be the easiest thing to implement, however: some basic controls (such as check boxes and radio boxes) update their state automatically and really, updating their state again on receiving a state changed message is redundant.
The second solution is, on creation of an edit change request, to automatically note in that request the source of the change: thus, one of the parameters of a change request f is the originating object that sent the change. (For an undo change, the requester would be set to a value indicating that the message came from the undo manager.) The state changed messages would then pass the source of the change request on in the ui messages, so that a user interface element receiving the message can then choose to ignore the message if needed.
I personally like the second solution better than the first; the added flexibility allows my user interface control code to decide how to handle a state change. Unfortunately the undo manager in both the MacOS X Cocoa Framework and the Java Swing Undo manager would require a bit of extra bookkeeping in order to properly set the source of a state change. However, I think the extra work may be worth it on a future project.
Macintosh Programming
One of the more interesting aspects of Macintosh programming is that you find yourself sweating the details. You find yourself spending a day or two sorting out NSViewAnimation in order to get your inspector window to open and close subsections gracefully. You find yourself worrying if “Lucidia Grande” is properly selected as the default font for a number of controls. You find yourself wandering how to create an anti-aliased box around a group of items in a tree view.
This fits very well into my theory as to the different levels of software development, and why I don’t think I want to work for a dot.com anymore.
At the bottom level are the business analyst programmers. Their job is to take data and write a program to generate a report–and in many ways this is the easiest sort of programming, since you are probably the only person who will ever run your program. The goal is not code elegance, but the report–and if you have to hack your code together in a mix of Visual Basic and SQL and a little Microsoft Excel bit fiddling, it doesn’t matter, since the product is the report.
Next comes back-end “enterprise” software development. Most of Yahoo!’s Panama system consisted of this sort of development. The audience for your software will either be analysts or internal people (such as Yahoo’s advertising editors and sales people); if a feature isn’t elegant or doesn’t quite work right, you just send out a memo warning people not to use the feature until the next version is rolled out. What makes this sort of development a pain in the neck are the number of Architecture Astronaut wannabes floating around who over-engineer aspects of the system because, well, because it doesn’t matter. (One component I worked on was broken into eight separate EJBs with elements using Hibernate–and the fellow who was nominally in charge of this code justified the design because of the “heavy load” the system would take. Nevermind it made the system impossible to debug or add features to–or the fact that at maximum load it may take perhaps 10 transactions a second, which, with a simpler design, could be handled by a modest box running MySQL…)
Next on the totem pole comes application developers who are releasing boxed software. The audience for this piece of software are end-users–and there could be thousands or millions of them: customers who just plunked down $49 or $199 or $499 or whatever, and they bloody well expect every bit to just work.
And at the top of this totem pole comes embedded developers, whose software could be used by thousands or millions of people and which must be flawless: the end-user doesn’t think he’s buying software, he’s buying a car or a television set or a video camera, and it’s not like you can send him “version 2.0” of his BMW 3-series car to fix a bug in the ignition timing software.
What constrains each level of software development is the audience: as the audience for the software increases, the need to get it right the first time goes up, and the ability to fix bugs “on the fly” goes down. And because the need to get it right the first time goes up, the need to properly manage the project also goes up: you cannot fix managerial mistakes (because you didn’t reign in your 20-year-old architect astronaut wannabe) by just pulling an all-nighter and rolling out a new version of the software. When you’re writing application software or embedded software, you cannot just roll out a new version tomorrow to fix the broken version you rolled out today.
That’s why I don’t want to work for a dot.com anymore. Because most dot.com software development is essentially enterprise development–and because the demand to “just get it right the first time” isn’t really there, you get a lot of mismanaged projects and a lot of screwed up politics which needlessly waste a shitload of time that could be better spent elsewhere.
I’d rather sweat the details today than deal with a “production server push” at 2 in the morning to fix some detail no-one bothered to sort out because, well, it just didn’t matter…
“And dammit foosball doesn’t play itself.”
Architecture astronauts take over.
Why I really care is that Microsoft is vacuuming up way too many programmers. Between Microsoft, with their shady recruiters making unethical exploding offers to unsuspecting college students, and Google (you’re on my radar) paying untenable salaries to kids with more ultimate frisbee experience than Python, whose main job will be to play foosball in the googleplex and walk around trying to get someone…anyone…to come see the demo code they’ve just written with their “20% time,” doing some kind of, let me guess, cloud-based synchronization… between Microsoft and Google the starting salary for a smart CS grad is inching dangerously close to six figures …
Yep.
And the irony is that for Microsoft and Google, with rich cash flows coming from a grand total of three market monopolies between the two of them (Microsoft Windows, Microsoft Office and Google Search Advertising), is that it is in their best interest as companies to pay ridiculous salaries to kids in order to discourage them from coming up with the next best thing that may undermine Microsoft and Google’s monopolies.
What you do on-line, or why Yahoo! is doomed.
I’ve given this a little thought, and I’ve come up with six different activities people do on-line. These are only broad categories, and there is some overlap. But I think you can sum up what people do into the following six things:
(a) Reading Information. That is, you go on-line to find information: the current news, weather, sports scores, and the like. While this somewhat overlaps the “passive entertainment” category, other things in this category may include reading on-line computer programming manuals or reading mathematics tutorials.
(b) Searching. This somewhat overlaps the “reading information” category, but by “searching” I mean actively going to a search site such as Yahoo! search or Google search, and repeatedly iterating through a few keywords until you find something you are looking for.
(c) Interacting. This covers the entire gamut from reading LiveJournal to checking your e-mail on Yahoo! mail to texting people on Twitter. You’re talking to people or reading their responses. And while this does overlap with “reading information” and with both “passive entertainment” and “active entertainment”, the primary focus of this activity is interacting with other people.
(d) Buying Stuff. Amazon.com is a prime example of this sort of activity: you go on-line to buy a good or service or product which is either downloaded to your system or which is sent to you via mail.
(e) Passive Entertainment. Television is an excellent example of this, as is YouTube: you’re sitting in front of the computer being entertained. The flow of information is one-way, and while this can overlap activities such as “reading information”, “interacting” and “searching”, generally the point is to sit back and enjoy.
(f) Active Entertainment. By “active” I mean game playing, as opposed to watching YouTube: you’re online to play a game. And while this can overlap with “interacting”, active entertainment involves both a structured environment (an on-line game) and established goals. (I’d categorize Second Life as “interacting” rather than “game play”, as there is no structured goals within Second Life.)
Now companies like Yahoo! and Google and even on-line publishers make their money through advertising. And there are literally a ton of social web sites cropping up which are based on the idea that once you drive eyeballs to your site, you can somehow monetize those eyeballs through advertising. After all, that’s how Google made it’s money: by driving eyeballs to Google search, they’re making money hand over fist by running ads on Google search.
But…
But let’s think about on-line advertising in terms of the six activities above.
Interacting. When you’re interacting with friends, you’re focused on interacting with friends. Advertising–outside of a recommendation made to you by your friend, which could be a viral ad–simply won’t work. And it won’t work for a simple reason: the advertisement is orthogonal to–and distracting from–what you’re doing. Basically, to convert that eyeball to a sale that person has to stop interacting with his friends: a change of context from one activity to another.
Active Entertainment. Like interacting with friends, active entertainment involves actively participating in a particular activity–and unless what you’re trying to sell directly relates to that activity, such as advertising a sequel to the game, you’re essentially forcing the person to change what they’re doing from one activity to another. And while there is a lot of experimentation in in-game advertising, I suspect the return on investment will suck, because in-game advertising has the disadvantage of being like billboard advertising: we’re programmed to ignore it–but add that to the fact that it’s a path we’ll probably only go down a few times and then never travel again, after we’ve completed the game.
Reading Information. Web sites like CNN and Weather.com are attempting to make money through related advertising–something that Yahoo calls “context match”, where the ad is matched to the content of the web site. But if you’re on a site looking for information, chances are you either are engaged in “passive entertainment”–that is, you’re just reading for the heck of it–or you’re reading information. While I’ll cover “passive entertainment” later, the problem with reading information is that unless there is an ad which is directly related to what you’re reading about (such as a calculus textbook advertised on a web site covering calculus), the chances of converting the person’s information seeking activities into a sale strike me as slim to none.
Passive Entertainment. The advantage of advertising to someone who is engaged in passive entertainment is that if they’re just flipping through a bunch of pages, chances are they may click on your page if it looks interesting enough. So the click-through rate for advertising to someone engaged in passive entertainment may be fairly high. But the ROI will undoubtedly suck, as people engaged in passive entertainment are at best window-shopping–and it’s fairly unlikely they’ll bookmark your page to return on a later date, since your page is just one of hundreds being flipped through by someone who is just “browsing.”
Buying Stuff. Someone who is on your web site looking to buy something could possibly be upsold–so it may be a good idea to make the product your selling easy to categorize so they can easily discover additional products that they may want to buy. But unless you’re running a large web site like Amazon, you may not have a lot of stuff to upsell to begin with.
On the other hand, one problem I’ve experienced with Amazon is that related products are poorly categorized: when searching for a computer game for my Macintosh I may find myself on a page with the Windows version–yet no link to take me to the Mac version. And Amazon’s current algorithm for matching related products sucks, as it seems to simply weigh by what people buy rather than by what is related. (Meaning if I’m looking for a computer game, don’t try to sell me a DVD as well.) In this way I think companies doing on-line sales are leaving money on the table: Amazon, for example, is excellent at allowing me to find something I know I want, but lousy at showing me related things that I may want to buy.
Searching. Here is the cash cow of the Internet: if I’m looking for something, and a ‘sponsored link’ gives the result of what I want, and I’m looking for something to buy–well, chances are you’ll have an excellent ROI since I’m there looking to spend money.
I think Google and Yahoo’s Overture found the cash cow of the Internet: search. Search advertising is a cash cow, and it’s being milked quite nicely–but it’s a cash cow because advertising plays directly into the activity the user is already engaged in. Passive entertainment advertising may currently be a cash cow–but at some point advertisers may start realizing that the return on investment is just not there, since the real goal of most advertisers is not to gain eyeballs–but to sell stuff. And the conversion on passive advertising is really not all that high.
Web sites like Yahoo! Mail and MySpace and LiveJournal–advertising there is going to suck big time, as unless you’re doing “feel good” brand awareness ads, chances are, you’ll never get a conversion. And for web sites like Wikipedia, the only way advertising will work is if it is specific and specialized: a wiki link on statistics won’t sell a lot of windows games, but it may sell a lot of scientific calculators and statistics books.
Unfortunately, however, most Internet companies are still thinking of their users as undifferentiated eyeballs–and are operating under the delusion that those eyeballs can convert at the same rate. Which is why companies like Yahoo! are doomed: unless Yahoo! can figure out a better way to bolster its search advertising by driving more users to on-line Yahoo! search, they’ll never be able to monetize the eyeballs to the degree they think.
Blogging My Successes And Failures
As I move from employee to self-employed software developer and attempt to build a company around my ideas, one central point sticks in my mind that I read from Paul Graham: if one is to succeed one has to make failure more costly. Not just in terms of wasted time or in terms of lost money–no, one has to make failure personal.
Making failure personal is actually rather easy: first, make what you’re doing part of your identity. When we introduce ourselves we often introduce ourselves with our status or our position: “Hi, I’m Joe, and I’m a sophomore student at cool college.” “Hi, Joe; I’m Jeff and I’m a senior developer at awesome corporation.”
So, in two weeks, I’d like to introduce myself as Bill Woody, sole proprietor and principal software developer of Chaos In Motion, a startup corporation specializing in business communications and management software. It’s now part of my identity–it is now part of who I am. Which means this must be a single-focused part of my identity: I cannot be “a part-time student and chief programmer” because if the chief programmer fails, well, hell–I was always just a part-time student anyway. Who cares about the fact that my company fails.
But if I’m not anything else, well, who wants to go through life being a personal failure?
The second step is equally easy: announce it to the world. Announce it to your friends, to your family, to your wife and kids–make your personal success or failure as public as possible. Join social groups or alumni luncheons and make it part of your identity. It is who you are. It is what you are all about.
And as soon as everyone else around you has bought into your own identity, and as soon as you have bought into your own identity–well, now you have no choice but to succeed regardless of what hell you must put yourself through.
Because it’s either that or acknowledging the most hateful thing we can possibly do: that we haven’t just failed to start up something–but that we are in fact a failure. We’ve failed our friends, our families, the people in our social circles. We’ve failed ourselves.
So you’ll excuse me if I make blogging about my own startup a core element of this blog. Because it’s my intention to be about as public as humanly possible, in order to make the price of my failure as expensive as humanly possible.
A theory as to why many startups are done by college kids.
It’s rather simple, really.
College age kids are not better programmers: age and practice generally makes you better, not worse. One doesn’t lose one’s ability to write code at 40 if one keeps on writing code from the age of 20: 20 years of practice is for any skill better than 2 years of practice, assuming one keeps on trying at the same level at 40 that one used at 20.
College age kids are not better business people for pretty much the same reason.
No; college age kids have two advantages over most software developers. One, they’re young and unattached: they don’t have kids and a mortgage and the trials and tribulations of life to distract them from being single-focused on a task. Sure, it may take even a really good hot-shot college age programmer four times as long to solve the same problem as someone with experience. But they have the time and the lack of distractions.
Second, and on a related note, they’re cheap: Paul Graham’s Y-Combinator is able to provide the initial funding for two college-age students to start a startup company for $20,000. For someone who has an established career and some modicum of success, $20k represents maybe two months pay–or even less if one has a good stock sharing program with a tech company on the way up. But for two college-age kids, $20,000 is enough seed funding to start running a startup.
With so little to risk, relatively speaking, it makes sense that someone who doesn’t have much to loose and who can live on so little can then run a startup.
But it has nothing to do with age per se: the guys who founded Adobe were in their 40’s.
Well, it’s time for me to put this idea to the test. After the past 6 years of working at Symantec and Yahoo! (and you can tell I work at Yahoo! because I remember the exclamation in the company name), I’ve managed to save enough to keep me going for a while without drawing a salary. So it’s time to quit my job, start my software project, and build something for myself.
We’ll see how quickly I can come up to speed doing Objective C++ on a day by day basis, though my idea involves data both on the desktop and “in the cloud”–which implies that I’m also going to be doing some web programming in Java. And we’ll see if after a year I either run out of cash without a single thing to show for it, or if I can make my savings stretch long enough to achieve some degree of success.
Because the reality is, in the tech world, you don’t get promoted without changing jobs, and you don’t reach upper management without running a startup.