« aARDvark | Main | Sandvox Designs-a-Plenty »

July 8, 2005

Diagrams that break

model.png

One of the things I've been working on since WWDC is streamlining Sandvox's Core Data model. (Yes, that's part of it there, on the left. It'll likely be public when we publish the plugin spec, so I don't think I'm giving away too much.)

Even though, many months ago, I came up with some really kick-ass model merging code that grabbed partial models from a bunch of different plugins and hooked up all the attributes, relationships, fetch specs, and parent/child relationships in just the right way, it turned out to be absolutely the wrong approach since, as soon as one thing varies in the model – oh, say, the presence or absence of a plugin – you've effectively broken your file format, requiring a lot of gnashing of teeth and grindage of CPU while you migrate from whatever your model used to be to whatever your model is now.

Thunderstruck to learn that I'd have to toss all (twelve lines of) my brilliant code, I decided to just suck it up and simplify, simplify, simplify. (Always, always, always a good thing to do anyway.)

So here's the good news: writing a plugin for Sandvox now requires virtually zero knowledge of Core Data: we just do it all for you behind the scenes using one simple, easy-to-maintain (and upgrade) model. You just create a delegate that implements and customizes what you need to. Just like it should be. Thank you Cocoa.

And here's the better news, at least for me: the modeling tool in Xcode, and Core Data itself, actually made this streamlining really, really easy. How? Visual development of (compiled) models, with copy/paste, and datastores that validate against the model at Save. In other words, Diagrams that break.

model_bad.png

As I mentioned somewhat off-handedly, as soon as you start seeing Core Data as fundamental to how you use Cocoa, you stop worrying about a whole class of problems. Not only can you whip up a pretty powerful object model by clicking and dragging (and, well, thinking), the system actually tells you if you get it wrong.

Actually, it does this in two ways: first it compiles your model on the front-end, into a .mom. If you've done something really stupid, your model won't compile. You have to fix it in the modeler before you even get to the code. And then on the back-end, when you go to save a document, Core Data actually verifies that the data you want to store matches the requirements you set out in the model. Say hello, one would hope, to referential integrity. That's not to say you can't put bad data in, but at least you're not leaving good data out. And that, I think, is a real step forward for fast, fast, fast Cocoa development.


On a related note: Apple just updated the developer documentation. Be sure you've got the latest. Xcode Preferences > Documentation > Check Now.

Posted by ttalbot at July 8, 2005 7:57 PM

Comments

How do you handle the case in your main app when you update the data model? Do you have some kind of merging / migration code?

Posted by: GJohn at July 10, 2005 9:32 AM

Yes, basically just some straightforward migration code. Have a look at the DataMigrator class in the Migration example that comes with Core Recipes. It basically walks you through the necessary steps.

Always version your models and put the corresponding model version in your document's metadata. That way you can check what model version it uses before firing up a persistence stack. If the model used by the document isn't the latest and greatest, you can give the user the opportunity to upgrade the document (by essentially writing out a new document with a copy of the old data, but in the form expected by the new model).

One thing I definitely did keep from my old code was the notion that the app would be quite precise about which model(s) it loaded and made available through its persistent document class. I don't let the app just load up and merge every model it finds in the main bundle. I'll also probably move old(er) models to a subdirectory in the app wrapper.

Of course, all of this is somewhat theoretical as the app has yet to be stress tested in the wild with different model/document versions floating around. We recently did a model review where we really tried to plan for future data needs of the app without having to make changes to the model. In reality I want to put our users through "document upgrades" as infrequently as possible, if ever, so we've done some things to design expandability into the document without having to change the model. I'll try to talk about those in future posts.

Posted by: Terrence Talbot at July 10, 2005 12:25 PM

It's nice to find someone blogging about doing a real app with Core Data. I'm looking forward to hearing what you have to say about designing expandability into the model, since I was told to be pretty careful about performance when doing that - for instance, not to expect good performance from making a to-many relationship to key-value pairs...

Posted by: Michael McCracken at July 18, 2005 3:07 PM