Vincent Gable’s Blog

September 27, 2009

Python Programmers Don’t Get Laid Much

Filed under: Programming | , , ,
― Vincent Gable on September 27, 2009

Or Python Programmers are Wankers

Good recommendation systems are a win for everyone. But inevitably, they show correlations to undesirable products, and in that sense they also all give condemnations, which sometimes can be quite funny.

According to amazon.com, customers who bought a tube of Swiss Navy Cream Masturbation Lubricant also bought Learning Python, 3rd Edition,

CorrelationSmaller.jpg

Find Your Own

The only trick to finding a juicy “condemnation” is to start with something embarrassing to buy. Amazon has a filtering system, so regardless of how strong the correlation is, it shouldn’t ever show embarassing purchaces from the Learning Python book page. And even for systems without a filter, this approach maximizes your chances of finding something, since every recommendation from a disreputable product is a condemnation.

I’m not sure where the sweet-spot in popularity is for finding a condemnation.

If an item has fewer purchases overall, that should mean that it takes only a few purchases of it and X for X to be recommended. On the other hand, that means fewer items will be recommended from it.

Things can be too popular. Because Amazon only shows up to 100 recommendations, if an item has enough purchases, all of the recommendations from it will be so similar to it, that finding a “deviant” condemnation is impossible. Again I don’t know exactly where this popularity threshold is.

Good luck!

September 17, 2009

Installing Mac Apps

Filed under: Accessibility,MacOSX,Programming,Usability | , , ,
― Vincent Gable on September 17, 2009

Today’s Daringfireball article on the shortcomings of the Mac application-install procedure is worth a skim. Gruber’s suggestion that Mac OS X automatically move 3rd-party applications into the /Applications/ folder on first-run, (a la the dashboard widget install process) is a good one1. Since Mac OS X already prompts you on first run (“Are you sure you want to run a program Apple didn’t write?”) it’s hard to see any downsides to this idea.

But that’s not the behavior we have today1.

Don’t Use a Damn .dmg!

As it stands today, I don’t see a good reason to ship your apps as a .dmg. I’ve been suspicious of disk images for a few years now; and usability tests show that people get confused by them.

Distribute your application as a single .app in a .zip archive. What possible use are other files besides the application? If a “Readme” file should be read before using the application, then show it when the application is first launched.

Installers are opaque and un-Mac like. There’s always a risk that they’ll install something that breaks the computer. As a developer I am even more suspicious of installers on the Mac, because I know how broken Apple’s installer tools are.

Of course, as a developer, I know that applications do sometimes need to install components. And here the best solution is for the application to check it’s environment and ask to install missing components as needed (in essence be it’s own installer). It’s more robust, since it detects-and-corrects missing or damaged components. It always preserves the user-facing abstraction that the icon is the application.

Applications shouldn’t install hacks dangerous enough to require a bundled user-facing unisntaller. To make IMLocation work, I had to install a background process — but I made it intelligent enough that it would uninstall itself if the main application had been deleted. Yes, this is more work, but it’s worth it.


1Another idea is to make Safari and Firefox smart enough to download applications directly into the right /Applications/ folder, bypassing the usual downloads folder. This elegantly solves the instillation problem, although it creates some new problems.

2Although it would be a cool hack to write.

Big Freaking Systems

Filed under: Programming,Quotes,Research | , , , ,
― Vincent Gable on September 17, 2009

A programming language is a tool for handling design complexity. That’s what all of computer science is, really — languages, libraries, type systems, garbage collectors, everything you learn about programming. They’re ways to build more and more complex designs without losing your grip.

The way you manage complexity is to be able to ignore it. A good programming tool lets you forget about some part of the problem, so that you can focus on some other part. And it ensures that when you return to the parts you forgot, you haven’t accidentally broken them.

Andrew Potkin

Years ago, When I was taking to programmers about what college I wanted to attend, I had in interesting conversation about how Computer Science education is an utter failure at preparing students for real-world programming. Outside of Software Development, no technical field accepts (sometimes prefers) candidates with “N years of experience” in place of a degree. I’m not sure I know why CS education fails so badly and universally. But my current best guess is that it’s because school never exposes you to enough complexity. Projects have to end in a semester. You never have to deal with a multimillion-line program, written by hundreds of co-workers, dozens of which you need to collaborate with, at unexpected times, for surprising reasons.

September 11, 2009

Never Start An Integer With 0

When programming, never start an integer with 0. Most programming languages treat a decimal number that starts with 0 as octal (base-8). So x = 013; does not set x to 13. Instead x is 11, because 013 is interpreted as 138 not 1310.

Languages with this quirk include: C, C++, Objective-C, Java, JavaScript, Perl, Python 3.0, and Ruby. If you add up the “market share” of these languages, it comes out to above 50%, which is why I say most languages.

“But I use {Smalltalk, Haskell, Lisp, etc.}”

I’m jealous that you get to use such a nice language. However, it’s bad programming hygiene to pick up habits that are dangerous in common languages.

Now, I assume you wouldn’t write 7 as 007, unless the leading zero(s) carried some extra meaning. There are cases where this clarity outweighs “cleanliness” (unless the code meant to be ported to a C-like language).

But you should at least be aware of this inter-lingual gotcha.

July 3, 2009

When In Doubt, UTF8

Filed under: Accessibility,Programming | , , , ,
― Vincent Gable on July 3, 2009
/* If you are uncertain of the correct encoding, you should use UTF-8, */
/* which is the encoding designated by RFC 2396 as the correct encoding */
/* for use in URLs.… */

CFURL.h

This echos my experience, when in doubt, choose UTF8 for the web. UTF8 is backwards compatible with 7-bit ASCII (eg. ‘A’ is 0x41 in ASCII and UTF8).

But know that UTF8 is a variable-length encoding: non-ASCII characters maybe represented by > 1 byte. As a general rule with Unicode, I do not expect a char or wchar_t to always map to a character in a string. Encoding details can be messy, e.g. “É” might be represented as one character, or two composed characters “´E”. It never hurts to brush up on Unicode.

June 15, 2009

Ignoring Just One Deprecated Warning

Switching projects over to iPhone OS 3.0 means discovering that functions I’m using are deprecated. Occasionally there isn’t a totally straightforward replacement, and the best thing to do is to file a bug/TODO/note for myself, and ignore the warning until a later version, when major refactoring will be possible. But bitter experience has taught me to have Xcode treat warnings as errors1, so it’s necessary to trick the compiler into ignoring the warning for things to build.

-Wno-deprecated

The -Wno-deprecated flag tells GCC to suppress warnings about deprecated code. But adding it to an Xcode project means you won’t get useful warnings about other depreciated code.

You could file a bug telling yourself to turn that warning back on after the deprecated functionality has been updated. That should work just fine. But it feels like bad project hygiene to me.

Casting and Protocols

Type casting is a dangerous old-C technique that’s earned its infamy. But it’s undeniably fitting to use a deprecated language feature to get deprecated code to build. The basic idea is to declare a protocol that includes the method you want to suppress warnings for,

@protocol DeprecatedHack
- (void) myDeprecatedMethod;
@end

then just cast your objects so the compiler thinks they implement the protocol,

[foo myDeprecatedMethod]; //warnings
[(id<DeprecatedHack>>)foo myDeprecatedMethod]; //no warnings

Although having to declare a protocol is somewhat heavyweight, it leaves a nice artifact in the code reminding you to replace deprecated functionality.

Protocols Not Required

Sometimes just casting to id is enough. This happens if another object has a non-deprecated method with the same name.

1For experimental or prototyping projects I let warnings slide. But in the main project I always treat warnings as errors. Ignoring them in production code has never worked — warnings fester and grow on each other.

Because Objective-C is so dynamic, there are many errors that the compiler can warn you about, but can’t be totally sure are errors. For example, methods can be added to a class at runtime, so if you call -someMethodThatDoesNotExistAnywhere, the compiler will warn you that something is up, but won’t stop the build, because the necessary code could magically appear at runtime. Of course, 99% of the time, it’s me accidentally using count when I meant length, etc. What I’m really trying to say here is that treating warnings as errors is an even better idea in Objective-C.

June 4, 2009

links for 2009-06-04

Filed under: Announcement,iPhone,Programming,Quotes,Research,Usability
― Vincent Gable on June 4, 2009

This was an experiment, in doing more with my delicious bookmarks. I was hoping that I could get more feedback and discussion on things I found interesting enough to bookmark by automatically posting links to them here. Many sites that I enjoy reading do something similar. But it hasn’t felt like a good fit for me.

MicroISV

Filed under: Programming | , , , , , , ,
― Vincent Gable on June 4, 2009

The word microISV is all business, in all the wrong ways.

MicroISV stands for “Micro Independent Software Vendor”, which in plain english means a tiny software company, usually on the order of one or three people.

Probably the best reason to buy software from such a small shop is passion. People who build and sell their own software directly tend to care very deeply about it. Their program is their baby. Nobody in a microISV is just in it for the paycheck. No matter how cool a large corporation is, at the end of the day everyone has to compromise on their dream to work together on it. But a one man shop never has to compromise or design by committee.

“Micro Independent Software Vendor” doesn’t communicate this agile vision. It sounds like the same kind of turgid enterprise think that drove the world’s largest software company to rename Netbooks, “low-cost small notebook PCs”. (You just can’t make this stuff up!)

Three people are never going to out-Big-Business a Big Business. So it just doesn’t make sense to label what they do with a Big Business Word. (And by word, I mean several words, because that’s how Enterprise Speak works.)

The most popular synonym for microISV I see in the Mac software scene is indy developer. I think it’s a fine term — better than microISV by about a factor of IBM’s income. But there are many other excellent alternatives to “indie”, like boutique, nano, one-man, etc. The exact term isn’t important; and it need not be short. If someone wants to open their own “Hand Cyphered Soft-Wares Emporium“, then more power to them! What’s important is that their taxonomy reflect the culture of commitment that goes into their unique software.

EDITED TO ADD: Small Batch Business is another fantastic name.

May 31, 2009

The Best Quicksort Ever

Filed under: Design,Programming,Sample Code | , , , ,
― Vincent Gable on May 31, 2009

The first time I saw this quicksort in Haskell was an eye opening moment,

 
qsort []     = []
qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs)

The first line reads: “When you sort an empty list ([]), the result is another empty list”. The second line reads: “To sort a list whose first element is named x and the rest of which is named xs, sort the elements of xs that are less than x, sort the elements of xs that are greater than or equal to x, and concatenate (++) the results, with x sandwiched in the middle.”

The code is so concise, yet clear (even with cryptic variable names like xs). The day my professor wrote it on the whiteboard was the first time I internalized that there might be something good about the alien world of functional programming.

The biggest revelation to me was, filter (< x) xs . It’s amazing that (< x) builds a temporary, unnamed, function equivalent to C++,

bool lessThanX(AnyOrderedType y){
    return y < X;
}
//plus the definition of X somewhere...

Building a function! It’s still profound stuff to me. And clearly it really uses fewer lines of code. Amazingly, using list comprehension syntax is not more concise,

qsort (x:xs) = qsort [i | i <- xs, i < x] ++ [x] ++ qsort [i | i <- xs, i <= x]

compared to the original,

qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs)

I hope this is an ah-ah moment for someone else too. I’d love to know what made you interested in functional programming; or if you know of a more elegant quicksort implementation.

May 29, 2009

Don’t Waste Memory to Save Time

Filed under: iPhone,MacOSX,Programming,Usability | , , ,
― Vincent Gable on May 29, 2009

In the provocatively titled, Space is Time: How Your CS Theory Class Lied to You, Greg Parker explains why hogging memory to speed up your program is a bad idea on consumer-level devices.

Space is time. An optimization that makes your program faster may make the user’s system slower overall. Play well with others.

I think it’s excellent advice. There’s only one point I want to make (and it must be made now, before silent SSD hard disks become more popular).

Every time your whole computer is nonresponsive, it makes that grrnrrnrnrr sound, right? That’s because it ran out of RAM, and the virtual memory system is thrashing to the disk. In the real word, on computers like the one you are on now, low memory plays a part in every system-wide slowdown.

Hogging the CPU can make your application slow. (Although if you pay attention to threading, and the run loop, using 100% of every core shouldn’t kill responsiveness and usability.) But hogging memory makes the whole damn world slow, including your application. And the worst case scenario of bad memory management kills the system deader then a kernel panic.

This isn’t to say that caching never makes sense. But a healthy respect for memory usage generally trumps worrying about the CPU.

« Newer PostsOlder Posts »

Powered by WordPress