Wiring iPhone to Java with JSON
Estimation is really hard, we all know that. Much harder in software than it is in manual things. Think about the band of DIYers, who beat their chest about the fact that they saved a few bucks by putting down their own tile, for example. They are doing something that has been done 10000x, and sure, there are going to be a few little unknowns that will come up on site that can throw such things off track, but the amount of potential loss and error (nevermind entropy) is really limited. Furthermore, every DIYer is walking a tightrope with a net underneath: they can just call a real contractor if they hose it up or run out of time.
The true terror of software is that:
- There are no real gating factors for error and order of magnitude misassessments are not only possible, but in many projects, de rigueur.
- Quite common for us to be doing things that have never been done before. Even if we are building the 1000th brick shithouse, it‘s probably with some combination of materials that means if the net is under the rope, it‘s got some rather large holes in it.
- Developers, like most human beings, prefer anecdote to statistical reality. Most challenges become personalized very quickly and the people doing them see them through their own blindered frame of reference.
Serialization is done in every language. You have a graph of objects, you need to turn the graph into a representation of bits, put it somewhere else, then magically rehydrate it when needed.
Remember Axis? The magical open source project that was going to make your domain models into services? Axis 1 was useless in the worst way: you tried something simple with it, it worked, so you waded into the swamp, only to find once you were neck deep, that the little rat trap could not deal with even a moderately complex object graph. As usual, version 2 was promised, took forever, and failed (hello dustbin). I looked at the Thoughtworks serializer, and decided to do my own a couple years ago, to talk to a Flex front end. It was pretty fun. Used reflection, and the core of the code was not that difficult. When I got to the point where I needed to have a means of saying I only needed certain attributes from a given type, I just made it possible to register a schema (xsd). Worked fine. Later, I did the Visitor pattern as an ITD injected into classes annotated with @Entity and looked at my dehydrator/rehydrator and realized I could redo it and drastically reduce the code.
Recently, I needed to add serialization to Objective C, so I could send data from the phone to a Java server app. Found [this project|http://iphoneonrails.com/] which bolts O-C to Ruby via Active Resource. Their screencast is kind of cool, worth watching, but it leaves a lot of questions: can this deal with graphs? are these real objects on the client? I mean they are clearly not CoreData objects so there is no local storage so if the server is offline or down, the magic is nil. Under the covers, there is not much going on. The O-C types are being turned into JSON by another project: SBJSON. So I went spelunking into that hole.
SBJSON is classic open source: no documentation to speak of, no unit tests, no examples. After a cursory look, I thought ‘why is this thing completely ignoring the NSCoding protocol?‘ Of course, the next question: ‘so we need 2 protocols for each supported file type?‘ Yeah, that‘s ugly.
In digging around in the code a bit, the front side of it is a pretty crude but clean lexer/parser that breaks down the JSON and the other side of course, produces it. On the production side, the strange thing is that there is some chatter about being strict, but the route taken does not deliver on that promise.
Maybe I'm missing something, but the whole point of NSCoding is it's format independent so each object implements its own encode/decode routines and then different formats are supported through subclassing NSCoder This would also solve SBJSON‘s tribulations about how best to be strict: convert only supported types and throw exceptions on others, or force them to other types with warnings in the logs.
But we‘re not done yet. NSKeyedArchiver/NSKeyedUnarchiver are subclasses of NSCoder. The problem I have with this is should I extend NSCoder or NSKeyedArchiver/deArchiver? If you just extend NSCoder, you have to implement a bunch of the stuff the archivers do, especially support for conditional objects. To me, it would have been ideal if this relationship had been like Director/Builder in that I could just plug in different NSCoder implementations to NSKeyedArchiver. The Apple Guide to Serialization, which, as usual, is excellent, but requires multiple readings, seems to make it sound like that is possible. If it is, it‘s not straightforward. Something like initWithCoder would have been simple. Anyway, this seems like the road.
In retrospect, the dream of just dehydrating things without having to have them implement any methods, through reflection, is probably not worth all the trouble. Once again, the Apple approach seems a tad less flamboyant, but prudent. The docs say there is a specialized visitor inside NSCoder, which is fine, because actually, the types that are being visited are the integrals, not each type that‘s being coded. I saw Tim Bray‘s explosion about the iPhone/store being a Disney walled in hell and him running off to join the android camp. If he promises to leave android in the same state as XML is a decade later, Apple should offer to pay his fare.