Vincent Gable’s Blog

January 14, 2009

People Do NOT Want to Register

Filed under: Design,Security,Usability | , , ,
― Vincent Gable on January 14, 2009

Jared M. Spool writes about how removing compulsory registration from a website translated into a $300,000,000 increase in sales. (Via UI and us). The intentions behind the registration were good: make things easier for repeat customers by remembering their information. This would reward the most loyal customers, and for first-time customers registration would only be a small one-time step. But in practice, the registration was universally hated.

We were wrong about the first-time shoppers. They did mind registering. They resented having to register when they encountered the page. As one shopper told us, “I’m not here to enter into a relationship. I just want to buy something.

…Without even knowing what was involved in registration, all the users that clicked on the button did so with a sense of despair. Many vocalized how the retailer only wanted their information to pester them with marketing messages they didn’t want. Some imagined other nefarious purposes of the obvious attempt to invade privacy. (In reality, the site asked nothing during registration that it didn’t need to complete the purchase: name, shipping address, billing address, and payment information.)

Repeat customers weren’t any happier. Except for a very few who remembered their login information, most stumbled on the form. They couldn’t remember the email address or password they used. Remembering which email address they registered with was problematic – many had multiple email addresses or had changed them over the years.

When a shopper couldn’t remember the email address and password, they’d attempt at guessing what it could be multiple times. These guesses rarely succeeded. Some would eventually ask the site to send the password to their email address, which is a problem if you can’t remember which email address you initially registered with.

(Later, we did an analysis of the retailer’s database, only to discover 45% of all customers had multiple registrations in the system, some as many as 10. We also analyzed how many people requested passwords, to find out it reached about 160,000 per day. 75% of these people never tried to complete the purchase once requested.)

The form, intended to make shopping easier … just prevented sales – a lot of sales.

The $300,000,000 Fix

The designers fixed the problem simply. They took away the Register button. In its place, they put a Continue button with a simple message: “You do not need to create an account to make purchases on our site. Simply click Continue to proceed to checkout. To make your future purchases even faster, you can create an account during checkout.”

The results: The number of customers purchasing went up by 45%. The extra purchases resulted in an extra $15 million the first month. For the first year, the site saw an additional $300,000,000.

Personally, I am in complete sympathy with the test’s participants. I don’t want to have to register to do something. In fact, I’ve re-registered for ADC a few times, because I lost my login information. (I really wish I could reclaim my first ADC membership from highschool, now tied to a defunct AOL address, because the member # is one digit shorter!)

Security Implications

Unfortunately, people have good reason to be wary of registration — it puts their credit card information at risk. And we’ve all been burned by spam and junk-mail from someone who abused registration information.

The Future is Here

Modern web browsers all have some kind of auto-fill that can remember and enter shipping/billing information. This technology obsoletes the benefits of registration in the story.

There’s more that could be done to be smarter about registration. For example, not exposing it in any way unless a person has made several orders.

Of course, the smartest thing is to avoid registration, because your users hate it. Services like BugMeNot prove this.

Why Work

Filed under: Quotes | ,
― Vincent Gable on January 14, 2009

Psychologists talk about two kinds of motivation: intrinsic and extrinsic. Intrinsic motivation is what drives you to do something regardless of whether you will receive a reward. Why do you spend an hour cleaning the inside of your stove? Nobody looks in there. Your intrinsic motivation compels you to do a thorough job. We all have it — in fact, most people start out with the desire to excel at whatever they do. Extrinsic motivation is the drive to do something precisely because you expect to receive compensation, and it’s the weaker of the two.

The interesting thing, according to psychologists, is that extrinsic motivation has a way of displacing intrinsic motivation. The very act of rewarding workers for a job well done tends to make them think they are doing it solely for the reward; if the reward stops, the good work stops. And if the reward is too low, workers might think, Gosh, this is not worth it. They will forget their innate, intrinsic desire to do good work.

Joel Spolsky

I’ve quoted Joel before about bad incentive plans.

January 13, 2009

Automatically Closing NSFW Content (Beta)

Filed under: Announcement,MacOSX | , , ,
― Vincent Gable on January 13, 2009

I’ve finally implemented a neat feature for IMLocation that I’ve wanted to do for a while now, when you arrive at work, it can automagically close NSFW webpages. NSFW content is detected using the same technology behind Mac OS X’s Parental Controls.

I recommend downloading IMLocation to get the full effect, but you can also get just the automator action. Leopard is required, and it only works with Safari right now.

As you guessed, there is a trade-off between accidentally closing important webpages and letting questionable content slip through. I’m not yet sure what the best way to expose tweaking this tradeoff is. In the mean time I’ve chosen the more-confusing-but-powerful road, because I think it’s best to start with something that can do the job, and then refine and simplify it.

Firefox?

I want this to work with Firefox, but I am hamstrung by Firefox’s poor-to-nonexistant AppleScript support. (In the meantime you can try the worksafer Firefox plugin, but it’s not a true substitute).

Firefox is geared towards extension through plugins, while Safari has a less-rich plugin architecture, but good scripting support. Arguably, the Firefox way is better for a web-browser. I’ve seen some really cool Firefox plugins that extend the web-browsing experience in ways a script just can’t. Unfortunately, what I’m trying to do — have NSFW content automatically closed for you when you get to work — is the sort of thing a script does well, and a plugin does cumbersomely, if at all.

If anyone has some advice on how to hack around Firefox’s limitations please drop me a line. Right now my prognosis is “a lot of work for a clunky payoff”, so right now I’m focusing on more pressing concerns.

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!

Wireless Network Names Don’t Tell You Much

Filed under: Design,Research
― Vincent Gable on January 13, 2009

It’s been my experience that the names of wireless networks do not tell you much about where they are. I do not use wireless network names as default names for anything.

Be aware that wifi network names are sometimes offensive! as I write this, one of the visible wireless networks is “DANKNASTY BALLASAUCE” — I kid you not. But more importantly, they are mostly generic and useless: “linksys”, “netgear1”, “2WIRE985”, etc.

Before you use a wireless network name to for something, make sure there isn’t something more appropriate you could 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 9, 2009

Biometrics

Filed under: Design,Quotes,Research,Security | , , , ,
― Vincent Gable on January 9, 2009

Summary of an article by Bruce Schneier for The Guardian,

Biometrics can vastly improve security, especially when paired with another form of authentication such as passwords. But it’s important to understand their limitations as well as their strengths. On the strength side, biometrics are hard to forge. It’s hard to affix a fake fingerprint to your finger or make your retina look like someone else’s. Some people can mimic voices, and make-up artists can change people’s faces, but these are specialized skills.

On the other hand, biometrics are easy to steal. You leave your fingerprints everywhere you touch, your retinal scan everywhere you look. Regularly, hackers have copied the prints of officials from objects they’ve touched, and posted them on the Internet. …

Biometrics are unique identifiers, but they’re not secrets.

biometrics work best if the system can verify that the biometric came from the person at the time of verification. The biometric identification system at the gates of the CIA headquarters works because there’s a guard with a large gun making sure no one is trying to fool the system.

One more problem with biometrics: they don’t fail well. Passwords can be changed, but if someone copies your thumbprint, you’re out of luck: you can’t update your thumb. Passwords can be backed up, but if you alter your thumbprint in an accident, you’re stuck. The failures don’t have to be this spectacular: a voice print reader might not recognize someone with a sore throat…

In Why Identity and Authentication Must Remain Distinct, Steve Riley cautions,

Proper biometrics are identity only and will be accompanied, like all good identifiers, by a secret of some kind — a PIN, a private key on a smart card, or, yes, even a password.

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.”

« Newer PostsOlder Posts »

Powered by WordPress