Vincent Gable’s Blog

October 12, 2008

Customers are Not Users

Filed under: Announcement,Design |
― Vincent Gable on October 12, 2008

Customers and users are not the same thing. The distinction is important but often missed.

A user is someone who uses the software you make.

A customer is someone who chooses to give you money for your software.

For many classes of software (eg a POS system), the majority of legitimate software users are not customers. They are using software chosen by someone else, often their employer, or an OEM.

The first step to satisfying both users and customers is to not confuse them.

October 11, 2008

Steve Ballmer Admits Microsoft Office For Mac Is Shitty

Filed under: MacOSX,Quotes | , ,
― Vincent Gable on October 11, 2008

Microsoft CEO Steve Ballmer recently admitted Office 2008 for Mac is stunted

can you find the applications you want on the Mac? Well, you don’t really get full Microsoft Office (on the Mac).”

I doubt this surprises anyone, but boy would I be depressed if I worked in the Mac BU (Business Unit), and the CEO came out and poo-pooed my work. That’s not doing right by your people.

I’ve written before about how I dislike using Microsoft Office 2008 for Mac, and how its high sales figures are in spite of it’s quality, not because of it.

Incentive Plans Always Fail

Filed under: Announcement | , , ,
― Vincent Gable on October 11, 2008

This article by Joel Spolsky convincingly argues that incentive plans will always fail damagingly,

As some of your workers substitute making the most of an incentive program for serving customers the best way they know how, the customer experience will suffer. Your best employees will find themselves fighting with incentive seekers to keep the business on track.

Co-incidentally I had a bad experience, caused by an incentive plan, at Best Buy a few days ago. I bought a GPS navigator, because I needed one then, and couldn’t wait for one to be shipped to me (even though it would have been cheaper to get one online). The cashier keep trying to push an “extended warranty” on me, even after I said “no” repeatedly. Undaunted, she switched tactics, and tried to scare me by telling me how often the model I was buying failed. At this point the sale hadn’t yet been made. But the cashier was trying to convince me that the thing I was about to buy broke all the time. Unbelievable!

If the cashier’s story is to be believed, she sees about one GPS unit returned every (6 hour) day, and sells about 20-30 in the same time. So now you know what I know about Best Buy’s quality and service.

An AppleScript Quine

Filed under: Announcement,Programming,Research | ,
― Vincent Gable on October 11, 2008

Here is my first quine. It’s written in AppleScript, because I wasn’t able to find, another AppleScript quine.

When run quine.applescript will make Script Editor create a new window containing the source code. It’s particularly meta if you use Script Editor (the default application) to run the quine, because it’s not just printing itself, it’s writing itself in the IDE!

Fortunately, the problems I’d originally had with Script Editor and the quine seem to have been fixed.

EDITED TO ADD: Here’s the quine’s source, but you really should download it to run it, because wordpress has a habit of subtly mucking with copied code…

set d to "on string_from_ASCII_numbers(x)
	set s to ASCII character of item 1 of x
	repeat with i from 2 to number of items in x
		set s to s & (ASCII character of item i of x)
	end repeat
end string_from_ASCII_numbers
set set_d_to to {115, 101, 116, 32, 100, 32, 116, 111, 32}
set scriptEditor to {83, 99, 114, 105, 112, 116, 32, 69, 100, 105, 116, 111, 114}
set quine to string_from_ASCII_numbers(set_d_to) & quote & d & quote & return & d
tell application string_from_ASCII_numbers(scriptEditor) to make new document with properties {contents:quine}"
on string_from_ASCII_numbers(x)
	set s to ASCII character of item 1 of x
	repeat with i from 2 to number of items in x
		set s to s & (ASCII character of item i of x)
	end repeat
end string_from_ASCII_numbers
set set_d_to to {115, 101, 116, 32, 100, 32, 116, 111, 32}
set scriptEditor to {83, 99, 114, 105, 112, 116, 32, 69, 100, 105, 116, 111, 114}
set quine to string_from_ASCII_numbers(set_d_to) & quote & d & quote & return & d
tell application string_from_ASCII_numbers(scriptEditor) to make new document with properties {contents:quine}

October 9, 2008

Function Over Brand

Filed under: Design,Quotes | , ,
― Vincent Gable on October 9, 2008

There is something to be said for the fact that the phone with the strongest brand in the world has no visible branding whatsoever on its front face.

John Gruber on the iPhone. But you knew what phone he was talking about.

I’ve always been deeply opposed to any branding strategy that values a brand over a product. Adding branding to something’s “face” makes it harder to use, because it adds visual noise to the very part of the thing you have to interact with (and figure out how to use). For example, an “Intel Inside” sticker next to a keyboard is one more square-thing you have to rule out when looking for the right button to press.

October 8, 2008

Drawing the floor()

Filed under: Bug Bite,Cocoa,Design,MacOSX,Objective-C,Programming | , , , , ,
― Vincent Gable on October 8, 2008

So when drawing a custom-Cocoa-control, I had an issue where an NSImage (bitmap) and an NSBezierPath (vector-shape) didn’t move in sync with each other.

Using floor() to force all pixel-coordinate to be a whole number fixed the problem. There is probably a much better solution — after-all this was the first custom-control I have ever done in Cocoa. But when a simple solution works…

UPDATED: 2009-05-25: @cocoadevcentral tweets,

NSIntegralRect() and CGRectIntegral() take a rect and return a copy which is aligned to integer coordinates. Good to avoid blurriness.

They sound like a better solution then calling floor() on each element of an image.

October 7, 2008

Photoshop Upgrade Refusenik

Filed under: Design,Quotes | , ,
― Vincent Gable on October 7, 2008

I hadn’t heard of Bob Staake before but, according to Wikipedia, he’s kind of a big deal:

Illustrations by Staake appear in The New Yorker, Time, The Washington Post, The Chicago Tribune, The Wall Street Journal, The Los Angeles Times, The New York Times, and others. Illustrations by Staake are used in advertising by such companies as McDonald’s, American Express, Sony, United Airlines, Nickelodeon, Sports Illustrated For Kids, Ralston Purina, Hallmark Cards, Kenner Toys, and others.

Starting in 1993, Staake illustrated and contributed concepts to The Style Invitational, which is a humor contest at The Washington Post.

In 1995, Staake became a regular contributor to Mad Magazine.

In the September 4, 2006 issue of The New Yorker, Staake created the first of many cover illustrations to follow for that magazine.

Interestingly, he still uses Photoshop 3, first released over 12 years ago,

Let me clear up today’s rumor: I do NOT work in OS 7. I use OSX and run classic (9.0) in the background. Photoshop 3.0? Yes, STILL use that.

Responding to some brouhaha over his tools, he made it clear that it’s by choice,

I love how every tech geek out there goes POSTAL over the idea of an artist using software that they’re comfortable with – even if it’s old.

Reminds me of people who still think Microsoft Word 5.1 was the best version ever. Personally, I don’t think they are off by much, although given my spelling, a word processor without spellcheck-as-you-type just won’t cut it.

A Dishonest Move I Wish They Would Make

Filed under: Quotes,Security |
― Vincent Gable on October 7, 2008

Bruce Schneier has a great scheme I wish every dishonest company would follow,

Turns out you can add anyone’s number — or remove anyone’s number — to/from the Canadian do-not-call list. You can also add (but not remove) numbers to the U.S. do-not-call list, though only up to three at a time, and you have to provide a valid e-mail address to confirm the addition.

Here’s my idea. If you’re a company, add every one of your customers to the list. That way, none of your competitors will be able to cold call them.

Underhanded corporate shenanigans ending cold-calls once and for all would really make my day.

October 6, 2008

Returning Linux

Filed under: Quotes,Usability | ,
― Vincent Gable on October 6, 2008

Our internal research has shown that the return of netbooks is higher than regular notebooks, but the main cause of that is Linux. People would love to pay $299 or $399 but they don’t know what they get until they open the box. They start playing around with Linux and start realizing that it’s not what they are used to. They don’t want to spend time to learn it so they bring it back to the store. The return rate is at least four times higher for Linux netbooks than Windows XP netbooks.

MSI’s Director of U.S. Sales Andy Tung

October 5, 2008

Restarting Your Mac OS X Cocoa Application

Filed under: Bug Bite,Cocoa,MacOSX,Objective-C,Programming,UNIX | , ,
― Vincent Gable on October 5, 2008

Restarting your own application is a tricky thing to do, because you can’t tell yourself to start up when you aren’t running. Here is one solution, use NSTask to run a very short script that you can embed right in your Objective-C code:
kill -9 YourPID
open PathToYourApp

Something to be aware of, kill -9 will immediately terminate your application, without going through the usual applicationWillTerminate: business that happens when an application quits more gracefully.

- (void) restartOurselves
{
   //$N = argv[N]
   NSString *killArg1AndOpenArg2Script = @"kill -9 $1 \n open \"$2\"";
   
   //NSTask needs its arguments to be strings
   NSString *ourPID = [NSString stringWithFormat:@"%d",
                  [[NSProcessInfo processInfo] processIdentifier]];
   
   //this will be the path to the .app bundle,
   //not the executable inside it; exactly what `open` wants
   NSString * pathToUs = [[NSBundle mainBundle] bundlePath];
   
   NSArray *shArgs = [NSArray arrayWithObjects:@"-c", // -c tells sh to execute the next argument, passing it the remaining arguments.
                killArg1AndOpenArg2Script,
                @"", //$0 path to script (ignored)
                ourPID, //$1 in restartScript
                pathToUs, //$2 in the restartScript
                nil];
   NSTask *restartTask = [NSTask launchedTaskWithLaunchPath:@"/bin/sh" arguments:shArgs];
   [restartTask waitUntilExit]; //wait for killArg1AndOpenArg2Script to finish
   NSLog(@"*** ERROR: %@ should have been terminated, but we are still running", pathToUs);
   assert(!"We should not be running!");
}

WARNING: don’t make the same mistake that I did and test restartOurselves without some kind of guard to keep your application from restarting forever. It is very difficult to kill such a beast, because whenever it starts up it takes keyboard focus away from what you are doing…. well I’m sure you get the idea.

- (BOOL) weHaveRunBefore {
   NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
   BOOL weHaveRunBefore = [prefs boolForKey:@"weHaveRunBefore"];
   [prefs setBool:YESs forKey:@"weHaveRunBefore"];
   [prefs synchronize];
   return weHaveRunBefore;
}

« Newer PostsOlder Posts »

Powered by WordPress