a glob of nerdishness

February 14, 2009

Why sync still stinks

written by natevw @ 5:24 pm

Antonio Rodriguez, of the excellent Tabblo service fame, asks “Why does sync still suck?” without giving an answer. Sync is going to become more and more important as we use more software on more devices from more places. I’m a little hesitant to say this, because a) it might be only true for us nerds in our gadget-filled bubbles and b) Internet access may soon become completely ubiquitous for said nerds. But if the nerds ever figure out sync they’ll be really eager to share it with the rest of the world.

It’s frustrating that sync really belongs in the operating system, or even in standards above the operating system level, but for various reasons even where it is present it’s tough to really justify the extra pain of working with it. Apple does have a system framework (Sync Services) that is available to third party developers, but it is not designed to handle large chunks of media. It can’t be used to sync with iPhones, and MobileMe’s continuing bad reputation gives it a bad stigma as well. Maybe Microsoft has their own solution, but it probably has its own problems and certainly wouldn’t be compatible with Apple’s, or Google’s…

To answer Antonio’s question: Sync still stinks because file formats still stink and file system models still stink. And, in practice, the web hasn’t solved many of the underlying problems either. Standard formats lead to stagnation, proprietary solutions lead to fragmentation. File systems are stagnant, and file formats are usually fragmented. I’m very interested to learn how these difficulties can be overcome, but after so many years of not solving these problems, I don’t expect it will be easy.

January 6, 2009

Exceptions versus NSError

written by natevw @ 10:07 pm

Michael J. Tsai:

“NSError, ugly though it is, actually seems to be a pretty good system for managing and propagating errors generated by different layers of code and even different languages.”

When I first read that, I was taken aback. The way Cocoa uses NSError is almost exactly like exceptions, but with no language support. Instead of getting a return value OR an exception when calling a function, you need to declare storage for both the return value AND the error. With NSError, the return value must also be of a type with “room” for an invalid flag, like a pointer that can be nil or a “succeeded” boolean that can be false. As if the lack of tuples in C wasn’t occasionally frustrating enough, now even many structures must be returned by reference rather than value just because they weren’t able to convey the “failed, check error” message. Even generating an NSError is a pain, and handing a lower one up the stack isn’t much more fun.

But in the end I think Michael is right. In pure C++, where idiomatic code leads to the stack itself doing most of the memory management, exceptions are great. I’d expect similar benefits in completely garbage collected languages as well. Cocoa on the other hand is such a mixed bag: reference counting with varying amounts of autorelease, or garbage collected; with C API usage encouraged, C++ contamination allowed (and fairly well supported as of Leopard). Then factor in the growing trend of bridging Cocoa into other languages. Having to bubble up errors through an ugly old explicit error mechanism starts to look a bit more appealing.

December 10, 2008

Cocoa NSNumber “constant” macro for Objective-C

written by natevw @ 1:22 pm

The following tlnum() macro (which I dedicate to the public domain), will allow you to easily create NSNumbers from constant floats and integers in your Objective-C code:


#define TL_FLOATARG(x) ( (x) ? ((x) / (2 * (x))) : (((x) + 1) / 2) )
#define tlnum(x) (TL_FLOATARG(x) ? [NSNumber numberWithDouble:(x)] : [NSNumber numberWithLong:(x)])

You could even rename tlnum() to simply N() if it won’t conflict with anything in your code. Update: Mike Ash pointed out that the TL_FLOATARG trick will not work if 2 * (x) overflows. So until a better macro can be developed, use this with care.

Why would you use this? Well, Objective-C lets you make a constant NSString-like object at compile-time @”like this”. This is extremely handy, as the next easiest way to create a string object is [NSString stringWithUTF8String:"like this"]. Since string objects are used all over the place — as format specifiers, when querying for localized strings or application resources, in any sort of situation where a key is needed… — the @”" syntax saves a lot of typing! Constant number objects aren’t needed quite as often, but almost every Cocoa programmer has at some point wanted to create constant NSNumber-like objects in a similarly succinct and easy way. Using this macro lets you do just that.

While it would be impractical (if not impossible) to create truly constant NSNumber-like objects at compile time using preprocessor macros, I still wanted something that would allow me to replace code like [NSNumber numberWithInt:42] and [NSNumber numberWithDouble:3.14] with something shorter. Furthermore, I wanted *it* to worry about the number’s type for me. I didn’t want to have to call a different macro depending on the number, as this would be require more thought for each use and maybe even more typing.

My first thought was to do something like this, following similar tricks that Dave Dribin used for his to-NSString converter:

// WRONG!
#define tlnum(x) ({ typeof(x) _x = (x); [NSNumber value:&_x withObjCType:@encode(typeof(_x))]; })

This has two problems. For one, the NSNumber subclass does not override -[NSValue value:withObjCType:] and so the object created does not work as an NSNumber at all! I worked around this with my own function that checked the encoded type, but that seemed like overkill. The second problem is that even with a helper function, the code depends on GCC extensions for the block macro and the typeof() operator. I wanted to keep my code within the C99 standard.

Since I was intending this for constant numbers only, and since NSNumber (or at least the CFNumber implementation in the most recent CFLite distribution) uses at least 8 bytes of storage for even chars and bools, the only important distinction is between floats and integers. Thus the TL_FLOATARG, which takes advantage of the fact that 1 / 2 yields the integer 0, while 1.0 / 2 yields a floating-point 0.5. The one gotcha with the final version is that it evaluates its arguments multiple times. My compile settings give a warning, but be careful not to do something like tlnum(i++), as you’ll end up incrementing i multiple times. Jens Ayton kindly provided another macro trick to turn this into an error, but in the end I opted to leave it out for simplicity.

Please enjoy, and I’d be glad to know if this is helpful!

December 2, 2008

Using fully synthesized instance variables in Objective-C 2.0

written by natevw @ 7:12 pm

One of the great new features added to Objective-C in version 2.0 was property declarations. While I’m not a big fan of the dot syntax, the ability to clarify the semantics of setter methods is a big win in my opion. With old-style setters, one was rarely sure if the value passed would be copied, retained, or simply referenced. The other neat feature of properties is that the compiler can provide instance variable storage automatically when compiling for the “modern” ObjC runtime. So you don’t have to declare an instance variable matching (or matched to) a fully-synthesized property if you’d prefer not to.

If you intend to take full advantage* of synthesized variables in the future, you must never use the instance variable directly. Unfortunately, if you’re also compiling an application that needs to run on 32-bit Leopard (as is pretty likely these days whether you’re supporting a PowerPC desktop app or testing an iPhone app in the simulator) you will need to declare these storage for your properties for the sake of those builds — Leopard needed to be backwards compatible with the “legacy” ObjC runtime, and the compiler relies on runtime support to implement this ObjC 2 magic. This conflicts with best practice for init/awake and dealloc methods, which should prefer to use the instance variable directly to avoid unwanted side effects of custom setters (undo, notifications, redisplay, etc.). If you’re in the habit of using instance variables directly in other places, you may need a little help from the compiler to remind you that the ivar may not exist.

What we might want is a set of macros that does the right thing in these special circumstances, but yet will cause compiler errors during universal builds for any other direct use of the instance variables:


/* The following macros allow one to mark uses of declared instance variables
 that could be replaced by automatic property storage when only the modern ObjC
 runtime needs to be supported.

 TL_SYNTHESIZABLE_IVAR_DECL is used to declare the instance variable.
 TL_SYNTHESIZABLE_IVAR_SET should be used only in init/awake implementations.
 TL_SYNTHESIZABLE_IVAR_RELEASE should be used only in dealloc implementation. */
#ifdef __OBJC2__
#define TL_SYNTHESIZABLE_IVAR_DECL(type, name)
#define TL_SYNTHESIZABLE_IVAR_SET(name, value) (self.name = value)
#define TL_SYNTHESIZABLE_IVAR_RELEASE(name) (self.name = nil)
#else
#define TL_SYNTHESIZABLE_IVAR_DECL(type, name) type name
#define TL_SYNTHESIZABLE_IVAR_SET(name, value) (name = value)
#define TL_SYNTHESIZABLE_IVAR_RELEASE(name) ([name release])
#endif /* __OBJC2__ */

You would use them like this:


@interface MyClass : NSObject {
@private
	TL_SYNTHESIZABLE_IVAR_DECL(id, myVar);
}
@property (nonatomic, retain) id myVar;
@end

@implementation MyClass
- (id)init {
	self = [super init];
	if (self) {
		id defaultValue;
		TL_SYNTHESIZABLE_IVAR_SET(myVar, defaultValue);
	}
	return self;
}
- (void)dealloc {
	TL_SYNTHESIZABLE_IVAR_RELEASE(myVar);
	[super dealloc];
}
@synthesize myVar;
@end

*Now the real question is, what advantage is there to synthesized instance variable storage? In short, you’re able to declare the property in one place only, which results in less duplicate code. So why would you use these macros, when they require you to declare the property twice anyway? I’ll tell you: I don’t know. If you like to mark “deprecatable” code, TL_SYNTHESIZABLE_IVAR_DECL will be handy. The other two could be replaced by their __OBJC2__ setter equivalents with no real harm. Regardless, here they are, and I dedicate them to the public domain. If you think they’d be helpful, feel free use them at your own risk.

November 22, 2008

Short days for long work

written by natevw @ 6:27 pm

The days are getting shorter and the nights are getting colder; 2008 is almost over. The work at Calf Trail is progressing well, but there’s still a lot we’d like to get done before calling it a year. We’ve released two and a half alpha versions of Mercatalog, our Mac geotagging application, and are trying to get to beta as soon as possible. Letting other people finally try Mercatalog has been a great experience, though quite humbling. I feel like I’ve learned so much this year, and hope to eventually find time past this 100th post here to share more thoughts and more code!

September 13, 2008

Buy low, sell high

written by natevw @ 10:26 am

Our little two man company just got back from our second trip to attend Seattle Xcoders. Once again, we had great conversations with friends and developers there. Among ourselves on the way there and back, we talked about many hopes and ideas for our company’s future. We discussed the temptation to let overlofty ideals about how software “should be” hamper the smaller goals that must first be achieved along the way. And we imagined ourselves writing great software that helps people do great things, built on top of a great platform.

Then we came back to this bad news. Apple have decided not to reward yet another developer’s hard work, this time on a very legitimate iPhone application. When the iPhone developer’s kit was announced, developers were warned that certain limitations would be enforced — Apple wouldn’t allow apps that were (for example) malicious, violated users’ privacy, “illegal” and other such things to be sold. This generated some immediate speculation about how Apple would use this power they’d reserved. After months of having to work under an NDA that would forbid developers from learning this new operating system as a community, now comes this confirmation of a once-latent fear. It’s a tough struggle to turn ideas, time, money and other limited resources into a product that will improve user’s lives. Now Apple are using their control in a way that makes the expected return on this investment even lower, especially for competitors of Apple or Apple’s partners. They’ve set up a game where they are the only ones who can’t lose, unless customers and third party developers stop playing.

Already one talented developer has announced that he will not be writing any more iPhone applications until the rules are made clear to all contestants and the referees are no longer hidden behind one-way glass. Apple claim they are still “processing” our application into this Secret Sharecropper Society. Should we email them and tell them not to bother, that we don’t want any share in this? If we believe Apple’s market is unnecessarily risky for us (it is) and if we believe Apple’s censorship will hurt our customers (it will) and if we believe this kind of human-centralized control will end up harming everyone everywhere (it may) — if we believe all that — is it hypocritical of us to still want to make iPhone software?

Worse, it is also Apple who control the equally amazing desktop platform for which we have been writing software since before January. What if this is also the future Apple intend for Mac development? Will we be legally obligated to learn and grow alone and leave others to do the same? Will we be unable to properly test our code in real world conditions? Will we have no choice but to give a cut of all our revenue to yet another bureaucracy that thinks it knows what’s best? And after all that, will we occasionally have the freedom to sell our work simply taken away? If so, we’re making a very bad investment.

What should we do? In a number of countries, the World Wide Web still has many of the freedoms and opportunities that the Wild Wild West is rumored to have once held. But just as many covered wagons never made it, and the ones that did learned to do without the modern conveniences they once enjoyed, we like the comfort of the desktop and our software is better for having the plumbing and wiring a web cabin just doesn’t provide. If we stay on Apple’s good side, we might be able to make a lot of money. And except for the ideals we’d have to disregard, it would be honest money too.

The first version of our software will not do all we think it should do for our paying customers. We don’t intend to rip anybody off, and it’s not because we disrespect our users. It’s because we are learning, at least with software development, that sometimes it is impossible to get to where we want to be without making some practical compromises along the way. We’ll always try to avoid doing things the wrong way, but sometimes we don’t yet have the ability to do them the best way either. I wonder if more of life — or at least this business struggle we’ve found ourselves a part of — I wonder if it’s okay to invest in a system we don’t fully agree with, at least until we have the opportunity to trade in for something better? Our company would be grateful for your advocacy to the one who is really in control on our behalf, and I would appreciate reading your thoughts about these “compromises” as well.

August 21, 2008

Fighting frustration: Bacon grease and cold water?

written by natevw @ 2:51 pm

Corporations don’t value my warm fuzzy feelings. Computers go bonkers. Code is hard to write well. Cars keep breaking down; colonies of mold keep forming on things once clean; creepy crawly critters keep coming through the walls; cats keep turning kibble into feral kittens; crooks keep on, who knows when they’ll be back.

Complicated issues don’t have concrete answers, or even easy questions. I keep letting myself settle into the sidelines — the world doesn’t spin the way I think it should, so I stand with my arms folded making cynical, sarcastic and even snide commentary on just how screwed up the entire shebang is.

I’ve been fighting fire with spoonfuls of rancid bacon grease.

Even in my best moods, I still believe that human pride trumps human progress, that people who set out to change the world end up content to just control it instead, that human history teaches history teaches humans little. So if success is simply continuing forward, why bother succeeding? Because failure is unpleasant? Because real men ship? Because my addled programmer brain has no other mode but to find the underlying patterns, implement the missing features, fix the major bugs, of THE ENTIRE UNIVERSE?

I’m not pressing on because I think I can fix the problem, clean up the mess, and squelch the fire. I’m pressing on because, yeah there are messes and I keep making more, yet the world is in good hands. I’ve been blessed despite my brokenness, and from what I’ve been given I hope to give a bit of cool water. And specifically, today’s next step: maybe some of that could affix a mess of pictures to something that resembles a map; I can’t fire myself just yet.

August 1, 2008

Control

written by natevw @ 3:14 pm

I paid $359 for my iPod touch on March 6, and when it arrived I paid another $20 for the software upgrade that had come out by then. Last month, I paid $10 more to upgrade to the latest version. But after all the money I’ve spent on this iPod, I still don’t own it.

It’s an issue of control. I’m not referring to the fact that I have to send it back because its “Home” button stopped working. That’s a little bit of a bummer, but when the new one comes back all working and shiny and new again, the big bummer will still remain: my iPod is controlled by Apple, through iTunes its government handler. That last $10 upgrade enables iTunes to install third-party applications on my iPod. But even there, I can only decide what not to do with my iPod. It’s still Apple deciding what I can do.

Notice that this iPod I bought isn’t bundled with contract like an iPhone. It’s not locked to a cell carrier, there’s no “West Coast [telephone] network” it could take down, or anything like that. Anything nasty I could do with this iPod I could do with my Macbook at 5 times the speed backed by 20 times the memory. But users can’t do anything shady, or anything cool, without doing it through an application Apple has decided to carry in their store.

My first computers were my dad’s first computers. I learned to program mostly on an Apple /// that worked just fine even though Apple had probably long stopped supporting it. I have fond memories of playing StarBlaze on his TRS-80 Model 100, loaded from a squawky old cassette tape after a few tries. When I was given an eMate 300 by some friends, I was able to try out all kinds of old utilities from a Newton abandonware archive. Will my offspring be able to do the same sort of things with this iPod? Or will the encrypted applications I collect today no longer “authorize” by the time they discover the shiny obelisk in a box somewhere? Will they learn to use an old version of the developer tools and wonder why, if it works on the simulator, it won’t work on the device? Vive the jailbreakers! — immature as they act, I sure hope they’ve left good notes ten years from now. Otherwise, Apple really should just rent these things instead of selling them.

I hate to assume that a worst case DRM scenario will become the status quo, but it has become abundantly clear that Thoughts on Music was just a PR stunt. Apple loves them some DRM, and they’ve turned their top resources to a “revolutionary” new iPhone/iPod platform that has Digital Restriction Management at its center.

This bothers me as a user, and it bothers me as a software developer. It will cost another $99 to actually develop or test anything new on the iPod I bought. I’d gladly pay that, but I can’t. Our company is still waiting to get into Apple’s secret sharecropper society, though I put our info into the queue on day one. Thankfully we didn’t project any revenue from selling iPhone/iPod software — and now we never will, since one lesson we’ve learned from the whole “You don’t talk about iPhone club” mess is to not take for granted income so far out of our control.

If this dystopian ideal of Apple’s comes to their desktop, as some fear, I hope our little company has saved up enough for a few bays in a data center somewhere. Web apps have many huge drawbacks, but so does being a puppet on some big corporate headquarters’ string.

July 22, 2008

Comparing Objective-C selectors

written by natevw @ 9:58 pm

The key feature Objective-C adds to C is the concept of sending messages to objects. In most lines of code, the messages and receiving objects are basically intertwined: [thisObject getsThisMessage]. But just as you can pass around an object without necessarily sending it any messages, you can also deal with messages without sending them to objects. This is done via message selectors, which can be stored in variables of the single SEL type.

Apple’s Objective-C reference doesn’t make very many guarantees about what is stored in a SEL. It is a mostly opaque structure, to be probed only by functions “in the know”. But one perfectly normal thing to do is to ask an object if it will respond to a particular message selector, or if the action associated with a particular selector is currently enabled. To answer questions like this, the object may want to check if the selector in question is equal to a known selector.

Therein lies the rub. Until 10.5, the Objective-C runtime didn’t provide any function to compare these opaque selectors. The documentation does say that “The runtime system makes sure each identifier is unique: No two selectors are the same”. While this is not completely clear, it is understood by even Apple’s sample code (eg) to mean that the contents of identical SEL structs were identical, and thus could be compared using C’s == equality operator.

Apple is extremely unlikely to change this behaviour lightly (Update: it won’t change), as it would basically break binary compatibility across much code regardless of what the documentation is actually promising. However, the fact that the Objective-C 2.0 runtime added a sel_isEqual() function seems to imply that they do kinda sorta maybe kinda reserve the right to start treating SELs as a truly opaque type. (Even then, I can’t think of a good reason why the bitwise-equivalence would change.) But all this aside…there is now a function we can use.

Unfortunately, the sel_isEqual() function is defined in <objc/runtime.h> — a header that Foundation does not include — and doesn’t exactly blend in with the kind of high-level code discussed here. I’ve filed a bug (rdar://6094233) requesting the addition of an NSEqualSelectors() function next to NSStringFromSelector() and NSSelectorFromString(), but in the meantime I’ve written some wrapper code that is both “legacy runtime” and Objective-C 2.0 compatible:

TLEqualSelectors.h

There’s not really anything to it, it basically just wraps an inline function around sel_isEqual() if available, or does the old == comparison if not. I thought about moving the runtime function wrapper implementation into its own code so as not to leave all the runtime functions in the namespace; this might be something to consider for your own use, but this version optimizes for low overhead. Hopefully within a few years, link-time optimization will be ours, but even then keeping everything in one header is probably the best way to distribute this tiny little wrapping hack.

May 26, 2008

Farewell to trash that never became treasure.

written by natevw @ 8:45 am

I flew to rural Northwest Illinois last week, to visit my childhood house and stomping grounds for perhaps the last time. My parents, who had settled there for two decades, are moving several states westward to a house in the city. Pulling up those kind of stakes is an opportunity to realize just how much junk can accumulate without careful curation.

Nerdishness, it turns out, is genetic. The pack rat tendency may be a learned behaviour, but the hereditary effect is the same. Combine the two and the offspring will look something like this:

A pile of old electronics junk on its way to the salvage yard.

The decades of collecting and the two days of extraction and disposal were a team effort between my dad and me. I’m sure there were some gems in all that junk, but that will be for the salvage yard to figure out. This necessary catharsis might not have cured either of us of our collecting habits, but it was a healthy step in the right direction. The whole week, Dad kept singing a chorus about the freedom we find from the Things We Leave Behind; I felt like I was Mourning the Death of a Dream instead. Dad’s choice of Michael Card song was more appropriate, but the components and computers we did keep still carry kernels of nerdish dreams.

« Previous PageNext Page »