Vincent Gable’s Blog

June 16, 2008

Hold off on Upgrading QuickTime to Version 7.5

Filed under: Announcement,MacOSX,Tips |
― Vincent Gable on June 16, 2008

The QuickTime 7.5 update appears to have broken sound in VMWare Fusion, and also in some code I’m working on. I will know more once I have fixed the issue in my own code. But for now, I advise waiting to update QuickTime to version 7.5.

UPDATE 2008-06-19: problems in my code solved. Basically I was specifying a bit-rate for a compressed audio stream, and QuickTime expected it to be 0. Earlier versions of QuickTime didn’t care, but 7.5 was more strict. Also, the VMWare problems have been fixed.

June 11, 2008

Bring an Extra Battery for WWDC

Filed under: Programming,Tips | , ,
― Vincent Gable on June 11, 2008

I was chatting with a saleswoman at the San Francisco Apple Store, a few blocks from where WWDC is being held this year. According to her, the top things people wearing WWDC badges bought from the Apple Store are (most popular to least popular):

Laptop Batteries. Specifically, 15″ MacBook Pro batteries. This is apparently #1 by a wide margin. It’s what I was in the store to buy. I don’t normally carry a brick spare battery with me, because in my experience you can’t rely on it being charged when you need it. But at WWDC, there are stations which charge your battery while you work, so you always have a fresh battery ready to swap in. You can go the whole day without plugging in!

Power Adapters. (I guess battery chargers are not a panacea)

Laptop bags/backpacks. This one is funny, because Apple gave out a laptop case to every WWDC attendant. I’ve always thought that giving out laptop carriers to people at a tech conference was a bad idea, because everyone there already has a laptop and a laptop carrier that fits them. Mass-produced swag is probably not going to be better quality then something a nerd picked out for their computer. More people purchased a backpack then a smaller brief-case-sized carrier (presumably so they could haul around extra gear).

So when you go to WWDC, bring an extra battery. It’s the number-one thing attendees (including me) regretted not bringing so much that they ran out to buy one.

June 8, 2008

Michigan Flyer

Filed under: Tips | ,
― Vincent Gable on June 8, 2008

I’m writing this on Michigan Flyer 344, in transit from East Lansing to the Detroit Airport (DTW). So far, I’m happy. Wireless internet is available on the bus, and there are maybe one or two power-outlets (125 volts @ 60Hz) if you look carefully. So far, it’s been a better experience then catching a connecting flight to DTW.

The verdict so far: recommended.

UPDATE: So on my return trip, there was no internet. I suspect this might have been because the lights and TVs were turned off, but I am not sure. Also, I had to wait around 3 hours for the bus to show, so I didn’t get home until 1 AM. Not good. On the other hand, no delays or rescheduling. The airline industry is in a crisis right now, and about one in four flights are delayed. Busses are more predictable.

UPDATE 2008-10-19 5:48 AM: No internet this time either; the driver said it went out last night and hasn’t been fixed yet. The power-outlets still work however. (And during a stop I was able to check my email over hotel-wifi that leaked into the bus.) This time the bus-schedule matched up very well to my flight schedule.

June 6, 2008

case:

Filed under: Bug Bite,C++,Cocoa,Design,Objective-C,Programming
― Vincent Gable on June 6, 2008

This bug was frustrating enough that half-way through squashing it, I promised myself I would document the solution. Unfortunately, it’s not a particularly interesting bug, but a promise is a promise!

I had some code very much like:

typedef enum {NoError, ReadError, WriteError, NetworkError, UnknownError} ErrorType;
...
void DescriptionOfError(ErrorType err, char *string)
{
   switch(err)
   {
      IOError:
         strcpy(string, "Could not read data.");
         break;
      
      WriteError:
         strcpy(string, "Could not write data!");
         break;

      NetworkError:
         strcpy(string, "Network Error. Make sure you have an internet connection and try again");
         break;
      
      NoError:
         strcpy(string, "No error.");
         break;

      default:      
      UnknownError:
         strcpy(string, "Unknown error.");
         break;
   }
}

int main (int argc, char** argv)
{
   char desc[1024];
   DescriptionOfError(ReadError,desc);
   printf("error: %s\n", desc);
   return 0;
}

And it just wouldn’t do the right thing, but for the life of me I couldn’t see what was wrong.

The “solution” was very simple, and somewhat embarrassing. I forgot the case keyword before the labels in the switch statement. Turns out that if you don’t have a case in-front of a label, it’s treated like a goto label, not a switch label. And this is something that I’ve known for years, but for 20 minutes I kept reading the code, and my brain would interpret what it should say, not literally analyze it.

This was extremely frustrating, not because it took me a long time to fix (I wish all my bugs could be squashed in just 20 minutes!), but because the results I was seeing totally violated my mental model of what should have happened. Violating someone’s mental model is more unsettling then you might imagine — avoid doing it at all costs.

My First Octal Value

Filed under: Bug Bite,C++,Cocoa,Objective-C,Programming | , , ,
― Vincent Gable on June 6, 2008

Octal is useless today. It is easy to convert between octal and binary, so octal was used in some early computers. But hexadecimal has totally replaced it in modern use. There’s no advantage that octal has over hexadecimal, which is why hexadecimal has replaced it.

The C programming language has support for values in octal. This wouldn’t be a problem, except for the horrible syntax used to define octal values.

In C, any integral value that starts with 0 is interpreted as octal! So 010 is eight, not ten. I’ve been bitten by this before. I don’t know why this syntax was chosen over an 0o prefix (which google calculator uses), that would match the 0x prefix for defining hexadecimal values. In retrospect it was almost certainly a mistake to go with the current syntax.

Anyway, the reason I’m writing this is because for the first time ever, I used an octal value in a C program. I had to create a directory structure that could be be accessed by different accounts on the same system. So I had to explicitly set it’s permissions when I created it with createDirectoryAtPath:attributes: . I wanted the NSFilePosixPermissions value that determines the folders permissions to have the same format that the chmod command takes. And it takes an octal value. So 0777 is the first, and only, octal constant that I’ve written in any program. Even when I’ve written in assembly I’ve used hexadecimal. There’s a good chance I will never write another octal value — I hope that’s the case.

June 3, 2008

AppleScript is the Uncanny Valley

Filed under: Design,MacOSX,Programming,Quotes,Usability | , , ,
― Vincent Gable on June 3, 2008

A interesting theory:

I think this “like English but not quite” aspect of AppleScript is the Uncanny Valley of programming languages. Because AppleScript looks like English it is easy to fall into the trap of believing it has the flexibility of English. When that mental model fails its more unsettling than when you screw up the syntax in a regular programming language because your mental model isn’t making unwarranted assumptions.

Mark Reid

May 31, 2008

Links: Less Code Is Better

Filed under: Design,Programming,Quotes
― Vincent Gable on May 31, 2008

I happen to hold a hard-won minority opinion about code bases. In particular I believe, quite staunchly I might add, that the worst thing that can happen to a code base is size.

–Steve Yegge

The fundamental nature of coding is that our task, as programmers, is to recognize that every decision we make is a trade-off. To be a master programmer is to understand the nature of these trade-offs, and be conscious of them in everything we write.

Now, remember, these dimensions are all in opposition to one another. You can spend a three days writing a routine which is really beautiful AND fast, so you’ve gotten two of your dimensions up, but you’ve spent THREE DAYS, so the “time spent coding” dimension is WAY down.

So, when is this worth it? How do we make these decisions?

The answer turns out to be very sane, very simple, and also the one nobody, ever, listens to:

“START WITH BREVITY. Increase the other dimensions AS REQUIRED BY TESTING.”

— Wil Shipley

Shared Code

Filed under: Programming,Quotes
― Vincent Gable on May 31, 2008

I’m very picky this time about what I consider “shared” — I have to actually USE code in two different projects to consider it shared, not just think “Hmm, someday somebody may want to re-use this.” Because, in truth, most of the crap people put into shared code directories is either too specific to really be shared, OR (more commonly) it’s written in a general way but the particular app it was written for only tested some of the pathways, so it is essentially a bunch of buggy code that’s not actually being used and is waiting to trip you up.

Wil Shipley

Messages to Nowhere

Filed under: Bug Bite,Cocoa,iPhone,MacOSX,Objective-C,Programming | , , ,
― Vincent Gable on May 31, 2008

If you send a message to (call a method of) an object that is nil (NULL) in Objective-C, nothing happens, and the result of the message is nil (aka 0, aka 0.0, aka NO aka false). At least most of the time. There is an important exception if sizeof(return_type) > sizeof(void*); then the return-value is undefined under PowerPC/iPhone, and thus all Macs for the next several years. So watch out if you are using a return value that is a struct, double, long double, or long long.

The fully story:

In Objective-C, it is valid to send a message to a nil object. The Objective-C runtime assumes that the return value of a message sent to a nil object is nil, as long as the message returns an object or any integer scalar of size less than or equal to sizeof(void*).
On Intel-based Macintosh computers, messages to a nil object always return 0.0 for methods whose return type is float, double, long double, or long long. Methods whose return value is a struct, as defined by the Mac OS X ABI Function Call Guide to be returned in registers, will return 0.0 for every field in the data structure. Other struct data types will not be filled with zeros. This is also true under Rosetta. On PowerPC Macintosh computers, the behavior is undefined.

I was recently bitten by this exceptional behavior. I was using an NSRange struct describing a substring; but the string was nil, so the substring was garbage. But only on a PPC machine! Even running under Rosetta wouldn’t have reproduced the bug on my MacBook Pro.Undefined values can be a hard bug to detect, because they may be reasonable values when tests are run.

Code running in the iPhone simulator will return all-zero stucts when messaging nil, but the same code running on an actual device will return undefined structs. Be aware that testing in the simulator isn’t enough to catch these bugs.

A few simple guidelines can help you avoid my misfortune:

  • Be especially careful using of any objective-C method that returns a double, struct, or long long
  • Don’t write methods that return a double, struct, orlong long. Return an object instead of a struct; an NSNumber* or float instead of a double or long long. If you must return a dangerous data type, then see if you can avoid it. There really isn’t a good reason to return a struct, except for efficiency. And when micro-optimizations like that matter, it makes more sense to write that procedure in straight-C, which avoids the overhead of Objective-C message-passing, and solves the undefined-return-value problem.
  • But if you absolutely must return a dangerous data type, then return it in a parameter.
    Bad:
    - (double) crazyMath;
    Good:
    - (void) crazyMathResult:(double*)result;.

I love Objective-C’s “nil messaging” behavior, even though it is rough around the edges. It’s usefulness is beyond the scope of this article, but it can simplify your code if you don’t return a data-type that is larger then sizeof(void*). With time, when the intel-style return behavior can be universally relied on, things will be even better.

May 28, 2008

PayPal Reliability Problems

Filed under: Uncategorized | , ,
― Vincent Gable on May 28, 2008

It is rather worrying that:

a) PayPal broke something so fundamental as subscription payments. Don’t they have proper testing before they roll out changes?

b) It still wasn’t fixed 12 days later.

c) PayPal seem completely unresponsive to requests for information from developers when problems occur.

According to Andy Brice

UPDATE: 2009-12-17: A terrifying and Kafkaesq story of Paypal shutting down an indie developer’s account, because of a spike in sales due to a bundle sale.

« Newer PostsOlder Posts »

Powered by WordPress