Archive for August, 2007

Austin Cocoa Programming

If you’re near Austin, Texas, there are Cocoa meetings organized by http://cocoacoder.org. Happy hours and lunches, too. I’ve only been to one meeting, and plan on attending again. The level of experience ranges from novice to actually making a living on Cocoa.

Leave a Comment

Blog feedback

Planet Cocoa is requesting that Cocoa bloggers provide a means for giving feedback to the writer. Fair enough, but who wants to be listing their email on a webpage? Daring Fireball uses a good method (as opposed to some online Post-a-Message-to-me page); “enkode” the email. Instead of an email address showing, your site embeds a befuddling piece of JavaScript. A browser can interpret this correctly, but with any luck the spam agents cannot.At A Single Pixel, you can find a contact link over to the right, and of course there’s the forums too.

Leave a Comment

Core Data – persistence or data model?

Is Core Data for your Data Model or your Persistence Model?

Apple says, in their introduction to Core Data:

Core Data, new in Tiger, completes the Cocoa vision for building well-factored applications based on the Model-View-Controller (MVC) pattern by providing a strong, flexible, and powerful data model framework.

Apple says Data Model. As a data model, it fails. Only a few types of data are handled – strings and numbers primarily. If you want colors, “attributed strings” (text with fonts & formatting), images, or anything else, you end up having to go through NSKeyedArchiver and storing generically as binary.

From the Core Data Programming Guide:

To use non-supported types, in the managed object model you define two attributes. One is the attribute you actually want… The other is a “shadow” representation of that attribute.

So immediately you are mixing data and persistence models.

What you end up with is two fields, one persisted, called for example, “ColorArchived”; the other field called “Color” which is not archived and is suitable for the rest of your code to treat as a regular property. But of course now you have to subclass NSManagedObject and in your subclass write code to keep these two fields synchronized. Pain.

Your nice simple data model you thought you were defining is suddenly polluted with items created specifically for persistence. It has “ColorArchived” and “Color” can be moved out of the Core Data model entirely as a property of your class. Crazy because “Color” is the actual data you’re modeling! All that’s left is the persistence model!

A persistence model, not a data model! Core Data is all about persistence, really. It gives you choices about how to persist – such as XML or SQLite. This is a problem though. People are expecting to create a data model.

So, Core Data is about persistence. So it had better be pretty good at that, right? Well, it is. Very good. For version one of your application.

But then comes version two. You want to add some fields. As I previously blogged, Apple & Cocoa give very little help here. Apple says in their Core Data FAQ:

Mapping data from one schema to another is a difficult problem to solve, and Core Data does not provide a generic solution—you must perform the transformation yourself.

Does that sound like a Cocoa solution? Not to me. Cocoa is supposed to make powerful tasks simple. IMHO Core Data is a failure in this regard. It’s great for version one of your application – but it badly drops the ball after that.

You wind up with data model classes that have to read all versions of your schema, and write to the current version. Cocoa could, but doesn’t help here by for example, identifying schema versions, noticing migration is needed, iterating over the old schema and calling your persistence-related code to handle migration to the next schema version. It doesn’t, so while Core Data does the basic persistence well, it’s not a good persistence architechture.

There’s just not enough separation between the persistence model and the data model. Your NSManagedObject subclass starts out as the data, but has to understand the persistence model and be able to deal with all the versions. It shouldn’t have to. Persistence and migration should be separate from the data model; it would be great if migration could happen before your data model even gets loaded. Cocoa would see your persistent store is outdated, run through the migration steps, then load the document object model. That’s how a persistence model should work, but Core Data doesn’t work like that at all.

Another option is to leave everything as NSManagedObject, let that be your persistence model. then create a separate set of classes to be your actual data model. But then you’ve got to write code to translate between the persisted Core Data graph and your object model graph. Which is what Core Data is trying to save you from doing.

I don’t have a good answer here but I do know that I wish Core Data’s separation between persistence model and object model was a little wider.

More to come as I think, no I hope I have figured out migration to the point where it actually works. It even works on the current Leopard build.

Leave a Comment

Opportunity missed with Apple's new keyboard

The keyboard itself is wonderful. I like the low profile; the looks on the desk; and it feels good whereas the old Apple keyboards felt like mush.

Interestingly, the numeric keypad has a button, “Clear”, which of course operates Calculator’s Clear button. In fact, the numeric keypad is laid out identically to Calculator’s on-screen layout – except that no keys map to the memory buttons: MC, M+, M-, MR. However, the new keyboard does have keys that would work perfectly for these – the new F16-F19 buttons, placed in exactly the right position above the keypad!

Calculator screenshot

A use for the new F-keys!

I can’t find a way in Keyboard Preferences to map these buttons; it would be pretty sweet if Calculator understood them.

Leave a Comment

Cocoa pitfall #1: awakeFromNib

I’ve run into this exacerbating pitfall more than once.awakeFromNib is a useful method to override. It gets called once all the nib file connections have been made, so you know you are safe to invoke methods on anything created by the nib.You can get bitten when you have multiple nibs. In my case, I had a nib containing a custom view. The view overrides awakeFromNib to perform some initialization. I later created another nib and made the custom view the nib’s owner. When this nib is loaded, awakeFromNib is called again! So all the init code ran again, resulting in the usual unpredictable behavior.awakeFromNib gives you no clue about which nib you’re being awoken from.Took too long this time to work out I’d fallen for this pitfall. This stuff just slows development. Argh!

Leave a Comment

Core Data Blues

Document upgrades are working in TimeFlyer now, thanks to a post from mmalc on the Cocoa mailing list that said, “why aren’t you using configurePersistentStoreCoordinatorForURL?”. Just like the original poster in that thread, I hadn’t been using this – but I should have been.

What is migration? In Core Data, you set up a schema for your persistent store… say what?! I’ve obviously read too much Apple documentation. You tell Core Data what data you want it to store, such as a person’s name, address, and so on. It works great. Then you want to upgrade your application, so maybe now you want to store first and last names separately, and you’ve added some extra data like a person’s photo. All your users’ current document files need upgrading to the new format of data file. This is not trivial and the upgrade process depends on what kind of unique changes you made.

So a) it’s not trivial and b) where in your application’s code do you put all this upgrade logic? Apple has a sample, Core Recipes. Core Recipes is such a bad sample – I think someone wrote it just to show off. It’s ten times more complex than it needs to be, and doesn’t show how a document-based application should be doing migration. In fact, the migration is done by a application separate from the main Recipes program. How about if iPhoto worked like that when it needs to upgrade your library? You think most users would grok having to run an upgrade utility before they run iPhoto 08? As a sample, Core Recipes fails utterly.

Back to configurePersistentStoreCoordinatorForURL, that magic API which is where your version checking/upgrading code should go. Why wasn’t I using it? Well, probably because it receives no mention in Apple’s sample migration application, Core Recipes. Yes, Core Recipes fails again! Actually, it’s not used in any of Apple’s samples; Spotlight can’t find mention of it anywhere, and nor can Google except in Apple’s Reference documentation. Not even a Guide has it, that I can find. Brilliant. No wonder nobody is using it!

Thanks to Marcus Zarra for his article at http://opensource.bleepsoft.com/index.php/Main/DataMigration. I didn’t use his ZDS classes but the ideas got me pointed in the right direction. And thanks to mmalc (who seems to be an awfully helpful chap) for unlocking the final secret.

Comments (1)

Coffee in the UK

Figure Starbucks is a safe bet, right? I’m visiting the UK again and Starbucks has been topped for consistency and taste. You won’t guess by whom.

We ordered a grandé “half-caf” from Starbucks this trip. The barista thought this must mean just a single shot rather than the intended one caffeinated shot, the other shot decaf. Bleuch!

Costa Coffee has been bad too often to be able to mention any specific bad experience, and I avoided them this trip.

The most consistent coffee we’ve had for the past couple of years has come from Marks & Spencer! We’ve tried M&S in Devon, Winchester, and Southampton; it’s cheaper than Starbucks and has always been a 9 or 10/10 coffee. I don’t know what their trick is. Their food is yummy and their kids meals are a good deal too. Well done M&S – highly recommended!

Leave a Comment