How to move away from Parse

With the uncool announcement from Parse that they are closing in a year people already think where to migrate. I’ll personally migrate to CloudKit because i don’t want to manage my own server and because i develop only for Apple. But one more important thing to think right now is if your app is ready for migration, does the architecture allow this? Do you have any architecture at all? Whatever datastore you chose, if your app is designed with clean code in mind should be a matter of hours/days to do the change. (except if you have a really huge amount of data, in that case i’m sure you have a dedicated team that will take care of it, so only they are screwed)

The code is Swift but the important thing here is only the idea

Do you have something like this in your code?

Then you’re screwed too, none of your classes should ever ever know about the real model, being PFObject or NSManagedObject, you should work with a different model that is a copy in a plain NSObject, struct, tuple… and interfaces. I’m in the same boat with one of my projects that is not even released, but i’m so close that i’ll just continue like this. Luckily my second project was done right. The way it works is like this:

AppDelegate instantiates the DataManager in a variable outside the class, in Swift this will be accessible from anywhere.

var sharedData: DataManagerProtocol!
class AppDelegate: NSObject, NSApplicationDelegate {
  override init() {
    sharedData = DataManager()

Here is a brief implementation of them:

So your app now does not depend on the PFObject (PTask in my case), but on a Task which is a struct, which is harmless and you can use it for unit tests as well. Only DataManager knows about the PFObjects. How easy would now be to make the app to use CoreData instead Parse? Very easy, you instantiate the sharedData with

sharedData = CoreDataDataManager()

And you make sure CoreDataDataManager implements DataManagerProtocol

One tricky thing to do is to save data. You need to pass a Task to the DataManager but internally you need to query for it’s corresponding PTask, if exists you update it, if does not exist you create a new one.

If you want to see more code from this example you can check my opensource app on Github