Core Data is Invasive. You Can Hide It, Or You Can Embrace It

Found this nice post about using Swift protocols to expose read-only properties of Core Data managed objects so you don't couple your whole app to Core Data. Using Swift protocols in Core Data NSManagedObjects is a great way to limit the visibility of properties and methods. In my 1st book on Mac app development I talked about this, too, and this is a lot easier to handle than a custom layer of structs that you have to map to NSManagedObject and back again. Core Data is designed to be invasive and convenient. It's not designed to be used as a simple object-relational mapper.

Continue reading …

Extending Types with a Conversion Factory: Where Should You Put It?

In a post about the Swift reflection API, I found the conversion code from a Bookmark struct to a Core Data object interesting. Let's call the latter ManagedBookmark.

What puzzles me: which object should be responsible for the adaptation from one to the other?

  1. Bookmark converts itself to a NSManagedObject using a NSManagedObjectContext you also have to pass in. (That's what Benedikt did in his post.)
  2. ManagedBookmark provides an initializer or other factory taking in a Bookmark and, as always with managed objects, a NSManagedObjectContext.

Option 2 is pretty clear. Using Bookmarks public interface, the managed object will set its attributes. This requires a NSManagedObject subclass wheras option 1 can work with a dictionary of values.

My main worry is that in option 1 Bookmark, a value type of the application, has to have knowledge about Core Data. Usually we'd fare better if we separate Core Data from our own model.

With extensions in Swift (and categories in Objective-C) we have the power to add new behavior to existing types in other locations. Does this help?

Extending a type in a different file hides that detail at first sight – but the extension, when it's not private, is available in the rest of the code base, too. It just appears as if you put the code in the type definition itself.

Now if Bookmark is included in a "Bookmarking" module you import, an extension can add behavior without mixing Core Data visibly into the model layer. The Bookmarking module will not get altered when you extend one of its types in the client code.

I like organizing Swift code in modules because the boundaries are very strict. You cannot cheat yourself into mixing responsibilities and blurring boundaries that easily.

Ideas to Solve Background Fetching and Saving Race Conditions with Core Data

I ran into problems with my Core Data Unit of Work/Transaction implementation the other day. I was not exercising good NSManagedObjectContext hygiene and end up with conflicts from time to time. Race conditions. Hate 'em. The problem is that the parent–child setup of Core Data managed object contexts seems to work just fine for so-called "scratch pad" contexts: create a new child context, perform changes on in, then discard, or save to pass changes to the parent context.

Continue reading …

Transactions and Rolling Back Changes in Core Data with UnitOfWork

The Unit of Work pattern is a code equivalent to database transactions: when it completes, changes are persisted; when something fails, changes are rolled back. That's handy to perform a set of changes and have them saved. Sooner or later during app development using Core Data, you may ask: when should I save? When is the best point in time?

Continue reading …

Revisiting the Core Data + Domain Model Architecture

It happens that just yesterday I read about architecture smells in code. Among the examples was "subclasses don't redefine methods". In my post about Core Data and expressive domains earlier this week, I did just that: create a Egg subclass of CoreDataEgg to inherit CoreDataEgg's behavior. That's not what abstraction to superclasses is meant to do.

Continue reading …

How to Create Flexible Components with Two Levels of Service Objects

Again I was reminded about the value of service objects to encapsulate sequences in two places: the Domain, where business rules are kept, and in client code, where database management and transactions play a role. This distinction helps create clean code and deliver flexible components. I am building a feature for the Word Counter in a separate "library" project until everything runs smoothly. Then I'll integrate the code into the main application. Since I consider this to be some kind of library, I thought I wouldn't need many service objects, but I was wrong.

Continue reading …

Test doubles for Core Data managed objects might not work as expected

You don't have to learn anything new if you work with Core Data in Swift. It's a pain to use NSManagedObject directly, so you better work with custom subclasses all the time. Unboxing optional NSNumbers is just too cumbersome. There are caveats you should be aware of, though: Swift's static typing makes it a bit harder to write test doubles for managed objects.

Continue reading …

Core Data Violates DDD Principles by Default

I'm working on a way to make the Word Counter watch files and folders on a user's disk. This will enable to measure project progress. Until now, I always used .plist files to store records with the end in mind that I'm going to switch to a better alternative in the future. Since I'm adding all-new data tracking, I thought I might as well try different solutions now.

Continue reading …