Vincent Gable’s Blog

January 18, 2009

Touching The Information

Alan Kay talking about GRaIL, Graphical Input Language, a system implemented in the late ’60s that was so far ahead of it’s time, it’s still pretty impressive today.

“I felt like I was sticking my hands right through the display and actually touching the information structures directly.”

I had no idea this sort of interface was done so early.

January 17, 2009

Lessons From Fast Food: Efficiency Matters

Filed under: Design,Programming,Quotes,Research,Usability | , ,
― Vincent Gable on January 17, 2009

Every six seconds of improvement in speed of service amounts to typically a 1% increase in sales. And it has a dramatic impact on the bottom line.

–John Ludutsky, President of Phase Research, quoted on the “Fast Food Tech” episode of Modern Marvels, aired 2007-12-29 on the History Channel.

I wouldn’t expect things to be much different in the software world. The faster you get your burger bits the better.

UPDATED: 2009-02-05:
Apparently people want service much faster from software. Greg Linden reports,

Half a second delay caused a 20% drop in traffic. Half a second delay killed user satisfaction.

This conclusion may be surprising — people notice a half second delay? — but we had a similar experience at Amazon.com. In A/B tests, we tried delaying the page in increments of 100 milliseconds and found that even very small delays would result in substantial and costly drops in revenue.

If the Mr Ludutsky’s figure is accurate, a 20% drop in fast-food revenue would require a two minute delay. Does this mean every second spent waiting on a computer is as bad as waiting 4 minutes in meatspace? I don’t know — I’m doing a lot of extrapolation from hearsay. But it’s something to consider.

January 15, 2009

Even a Small Child Can Do it

This segment of an Alan Kay presentation (pt 2) really jumped out at me.

She’s never lived in a world that wasn’t densely populated with Macintoshes. …She literally learned to use it by sitting on her mother’s lap while her mother was working. So for this child, the Macintosh is not a piece of technology, but simply more material in the environment to manipulate.

Another interesting point to note is that even though she can’t read, she’s able to recognize standard textual menu items.

And in fact we discovered that she was about 70% literate — that about 70% of the generic window commands that are found in any Macintosh application, she’s able to use. Not just in a visual program like Mac Paint.

One message Alan Kay really drove home is not just that that computers can be simple enough for children, but that designing for children can lead to better designs for adults. But remember that that just because a child can use a computer does not make it a silver bullet for education.

January 13, 2009

Running in the Background

Filed under: Bug Bite,MacOSX,Programming |
― Vincent Gable on January 13, 2009

If you want your bundled application to run in the background — not show up in the dock — here’s what you do. Add

<key>LSUIElement</key>
<string>1</string>

(exclusive) or

<key>LSBackgroundOnly</key>
<string>1</string>

To your info.plist file. Use only one or the other.

LSUIElement will let you put up windows and dialogs. They’ll appear in the context of whatever application is frontmost at the time. If your process might ever need to put up an alert, this is what you should use.

If you choose LSBackgroundOnly, then windows and dialogs won’t work. Note that if you are writing a daemon, there are frameworks that you can not use!

January 12, 2009

Stopping an AMWorkflow Workaround

Filed under: Cocoa,MacOSX,Objective-C,Programming,Sample Code | , , ,
― Vincent Gable on January 12, 2009

-[AMWorkflowController stop:] does not stop a workflow from executing (more info). Here is a workaround that will stop all workflows your application is be running.

When you execute a worklfow using Automator.framework, the workflow is run in its own process, which insulates it from the invoking application, and vica verca 1

. At least on Leopard, the program that runs the workflow is /System/Library/CoreServices/Automator Runner.app/Contents/MacOS/Automator Runner . It has the bundle-identifier com.apple.AutomatorRunner , and it will be a sub-process of your application, since your application kicked it off.

That gives us enough information to kill just the instances of Automator Runner that are running your worklfows. This will stop workflow execution dead in it’s tracks.


- (void) killAutomatorRunnerSubprocesses; {
   ProcessSerialNumber   PSN = {kNoProcess};
   while(GetNextProcess(&PSN) == noErr) {
      NSDictionary *info = (NSDictionary*)ProcessInformationCopyDictionary(&PSN,kProcessDictionaryIncludeAllInformationMask);
      if(info) {
         NSString *theirBundleID = [info objectForKey:@"CFBundleIdentifier"];
         if([theirBundleID isEqualTo:@"com.apple.AutomatorRunner"] && [self processWasLaunchedByUs:PSN]){
            NSLog(@"Killing AutomatorRunner sub-process: PSN={high=%u low=%u}", PSN.highLongOfPSN, PSN.lowLongOfPSN);
            KillProcess(&PSN);
         }
         CFRelease((CFDictionaryRef)info);
      }
   }
}

- (BOOL) processWasLaunchedByUs:(ProcessSerialNumber)PSN; {
   ProcessInfoRec processInfo = {0};
   //we use GetProcessInformation(), and not the more modern ProcessInformationCopyDictionary()
   //because ProcessInformationCopyDictionary stores the "ParentPSN" as a 32 or 64-bit number,
   //and it is not clear to me what the endian-safe way to transform it into a ProcessSerialNumber
   //structure is, see http://lists.apple.com/archives/carbon-dev/2007/Mar/msg00283.html
   if(GetProcessInformation(&PSN,&processInfo) != noErr)
      return NO;
   Boolean   theyAreOurChild = FALSE;
   ProcessSerialNumber ourPSN = {0,kCurrentProcess};
   OSStatus err = SameProcess(&processInfo.processLauncher, &ourPSN, &theyAreOurChild);
   return !err && theyAreOurChild;
}
   

Please let me know if this works for you, of if you have a better solution.


1
Automator.app does not appear to spawn an Automator Runner when it runs a workflow. I’m not sure why. But since the stop button works in Automator.app, understanding why might lead to a better work around. Or not.

January 7, 2009

Software Disasters In The News: Dear John Doe

Filed under: Programming | , , , ,
― Vincent Gable on January 7, 2009

As the LA Times Reports, About 7,000 letters sent to families of soldiers killed in Iraq and Afghanistan had the salutation ‘Dear John Doe.’

Fortunately, the situation appears have done less harm than it sounds like it would.

J. Paul Boyce, an Army spokesman, said the service had not received any angry complaints, but several families called to alert the military to the error. …

Bonnie Brown of Troy, Ala., whose son John E. Brown was killed in Iraq on April 14, 2003, said she received a copy of the letter this week. She said she found the salutation odd but not offensive.

“I did notice it said, ‘Dear John Doe,’ ” she said. “But it didn’t really bother me. I didn’t think too much about it.”

Of course, the public relations fallout is immense, and all the more heated because of the political volatility surrounding the wars in Iraq and Afghanistan. This was still a disaster.

Paul Rieckhoff, founder of the Iraq and Afghanistan Veterans of America, was less forgiving, arguing the Army needed to do more to support military families…. (and) take extra care when communicating with the families of fallen troops.

“How much does it take to proofread letters?” Rieckhoff asked. “You have to remember the amount of hurt the families are going through.”

That’s a very legitimate question. I don’t understand enough about how mass-mailing operations work, or the technical cause of the error, to be able to answer it. (Remember, the letters were correctly addressed.)

I look forward to learning more about this unfortunate glitch, understanding what caused it, and (hopefully) how to avoid the underlying class of mistake.

The Army declined to release the name of the California company that printed the letters, insisting the responsibility for preventing the error was the military’s alone…Military officials did not immediately respond to a Freedom of Information Act request seeking the name of the company.

Hopefully, we won’t have to wait too long for that FOI query. The smart thing for the as-yet-unnamed company to do would be to come clean on their own, honestly explain the problem, and convincingly demonstrate that they have learned from their mistakes and won’t let something like that happen again. Given that an FOI request has already been made, they shouldn’t expect to remain anonymous and brush this disaster under the rug.

Objective-C 1.0 Style: Don’t Name Your Enumerators “enumerator”!

Disclaimer

There is a better way to iterate over collections in Objective-C 1.0. You really should use it. It’s easier to write, easier to read, less prone to bugs, faster, and makes what I’m going to rant about here a non-issue, because you won’t have any NSEnumerator variables in your code.

Badly Named Problem

The standard iteration idiom in Objective-C 1.0 is:

NSEnumerator *enumerator = [collection objectEnumerator];
id element = nil;
while( nil != (element = [enumerator nextObject]) ) {
   ;//do stuff...
}

Unfortunately, I see otherwise steller programmers name their NSEnumerator variables “enumerator”. That’s always wrong, because it does not tell you what the enumerator enumerates. We already know that enumerator enumerates things, because it’s type is NSEnumerator, unless it’s name tells us more then that it’s hardly better then no name at all.

This is an especially amateurish practice because …

Naming an Enumerator Well is Easy!

Call it, the plural of the element variable. And if that won’t work you can always fall back on calling it collectionEnumerator.

For example, to fix:

NSEnumerator *enumerator = [input objectEnumerator];
NSString *path = nil;
while (path = [enumerator nextObject])

We should name enumerator paths or inputEnumerator. You might find “paths” to be too close to “path” in which case let the “plural form” of element be everyElement, giving everyPath.

These rules can be applied without much thought, but will improve the clarity of code.

Why enumerator is Worse Than i

Firstly, the practice of naming an the index in a for-loop i is not good. You can avoid it by renaming i to thingThatIsIndexedIndex.

But at least, for(int i = 0; i < collection.size(); i++), is concise; therefore better than a equally-poorly-named NSEnumerator.

Also, there is something to be said for the idiom you can just use collection[i] over declaring an extra element variable.

The Right Choice

Everyone agrees informative names are good, yet poorly named enumerators are everywhere (just browse Apple’s sample code!) Poorly named enumerators persist because nobody really uses an enumerator per se, they are just part of an iteration idiom. (So stop declaring them and iterate smarter). When was the last time you saw code that did anything with an enumerator besides [enumerator nextObject] in a while loop?

But bad habits matter. Don’t pick up the habit of naming something poorly when it’s easy to do the right thing.

January 4, 2009

Conway’s Law

Filed under: Design,Programming,Quotes | , , ,
― Vincent Gable on January 4, 2009

Any organization that designs a system (defined more broadly here than just information systems) will inevitably produce a design whose structure is a copy of the organization’s communication structure.

Melvin E. Conway

As Wikipedia points out, “Conway’s law was not intended as a joke .. but as a valid sociological observation. It is a consequence of the fact that two software modules A and B cannot interface correctly with each other unless the people who made A communicate with the people who made B. Thus the interface structure of a software system necessarily will show a congruence with the social structure of the organization that produced it.”

How To Beat Web Apps

Filed under: Cocoa,Design,Quotes,Usability | , , ,
― Vincent Gable on January 4, 2009

The way Apple stays ahead of the web app trend is by creating native Cocoa experiences that can’t be duplicated in web apps — both on the Mac and iPhone.

John Gruber

December 29, 2008

Thread Local Storage in Cocoa

Filed under: Cocoa,MacOSX,Objective-C,Programming,Sample Code | , ,
― Vincent Gable on December 29, 2008

[[NSThread currentThread] threadDictionary] gives you an NSMutableDictionary that you can use for thread-specific storage.

« Newer PostsOlder Posts »

Powered by WordPress