Skip to content

Instantly share code, notes, and snippets.

@nonsensery
Created February 15, 2014 19:35
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nonsensery/9024131 to your computer and use it in GitHub Desktop.
Save nonsensery/9024131 to your computer and use it in GitHub Desktop.
Splitting model objects into several entities

Some thoughts on this blog post by Brent Simmons

From the original:

A VSNote has more than a dozen properties. But the timeline needs only a few of those, and there would be performance and memory-use gains by using a smaller object. … In Core Data I could create two entities: VSTimelineNote and VSExtendedNote. VSTimelineNote would have a to-one relationship to VSExtendedNote. … [But that] means the data isn’t stored using the most natural representation. The data model would be based on the needs of the UI, which is not a good idea.

Putting aside Core Data for a moment, at issue is that each VSNote contains 8 or 10 attributes that are not needed to display the master list of notes; they are only needed to display the detail view for a note. Ideally, when displaying the list, we could load just the attributes used in the list into memory, and then load the rest when displaying the detail view. But realistically, a few bytes for a timestamp here, and a few bytes for something else there are not going to make or break most apps. It usually boils down to a few really "heavy" attributes, like the full text of the note in this case.

Thinking about it in these terms, it becomes a pretty straight-forward optimization problem: loading the full text of the notes when displaying the timeline uses too much memory. And given that, the solution is pretty obvious: don't load the full text of a note until you want to view the note.

Now, how do you do that? When working with SQL directly, you just change your query to select fewer attributes (usually changing from select * from ... to select col1, col2, col3 from .... But that's the SQL way of doing it. The Core Data way (or "ORM way" to be more general), is to move that attribute to a separate entity, connected by a to-one relationship (as you've suggested).

The difference here is why you're moving the full text to a separate entity. It's not about the needs of the UI or what is natural or unnatural. You're moving it to a separate entity because there's a performance problem when it's lumped into the main entity. It's the data model's job to store the data in the way that matches the needs of the application. That is it's nature.

And finally…

It also means that some accessors would be weird — to get the creation date, for instance, I’d have to type something like note.extendedNote.creationDate.

Not necessarily. (I'll use note.extendedNote.fullText instead, since that's the attribute I've focussed on.) The fact that the full text now lives in a separate entity is an implementation detail. There's no reason that the API for your VSNote class needs to change. Just adjust (or add) the accessors for the full text to call through to the extended note, something like:

- (NSString *)fullText
{
  return self.extendedNote.fullText;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment