Opinionated Core Data: Hold On To Your Butts
I presented earlier this week at VanCocoa on using Core Data to build out the model layer of iOS Apps. The presentation is based on my experience building the iOS App for Goaly.co.
The talk goes over 4 key points:
The slidedeck is available on SpeakerDeck
All non-trivial abstractions, to some degree, are leaky.
– Joel Spolsky
The Law of Leaky Abstractions states that all non-trivial abstractions, to some degree, are leaky. Core Data is very far from a non-trival abstraction. Here are the main objects that Core Data classes abstract:
|NSManagedObjectContext||SQL statements, query engine|
|NSManagedObject||Row in a table|
Active Record and Datamapper
The two main design patterns that are used to abstract away a database are Active Record and Datamapper. Core Data does not cleanly fit under either of these patterns. However, it is instructive to understand how other frameworks abstract away the database layer.
The database that is usually abstracted away by the Core Data stack is SQLite. SQLite is a SQL database engine that is designed to be embedded in Apps.
Therefore, what Core Data is really abstracting away is the SQL When working with Core Data, I always turn on SQL debugging to make sure I see the SQL statements that run during an App’s lifetime.
Xcode generates terrible boilerplate when a project with Core Data support is created. It dumps the stack creation into seperate parts in the AppDelegate. This is a terrible idea.
The whole Core Data stack should be created at once as it doesn’t make sense to use each part seperately. The NSManagedObjectContext is the only class that should be exposed to the rest of the App. The NSPersistentStoreCoordinator and NSManagedObjectModel should be buried in one implementation file and never exposed.
And whatever you do, Don’t Use Fucking Singletons. Singletons are a terrible idea as they make it difficult to test the model layer of an App and they make signin/signout difficult to implement.
The model layer of an App can be completely tested by creating the NSManagedObjectContext in the setUp function of a test case. And the domain logic of the App should be pushed down into NSManagedObjectModel subclasses.
Classes and ViewControllers
The last half of the presentation decribes hot to structure and implement NSManagedObject and NSFetchRequest subclasses. It also details how UIViewController and UIView classes should interact with the model layer.
Apps can be built such that JSON that is received from the network layer and data that is pushed to the view layer are tested. All that is required is a sensible approach to structuring code in a project.