Extend not a library more than you are able.


When shipping apps, especially those that deal with CoreData or otherwise keep track of data, you often need to normalize that data or somehow make a correction if things become inconsistent. This often comes at app update time, and it’s usually a block of code you want to run once and only once. For each app I build I end up writing some custom logic to handle it. Today I decided to wrap that logic into a library called MTMigration, available on GitHub. The API looks something like this:

[MTMigration migrateToVersion:@"1.1" block:^{
    [obj doSomeDataStuff];
}];

However, the point of this post is to explain that the API I decided upon varies a bit from my original attempts. It looked like this:

[MTMigration migrateToVersion:@"1.1" 
                      options:MTMigrationOptionOnFreshInstall | MTMigrationOptionOnUpdate
                        block:^{
                            [obj doSomeDataStuff];
                        }];

and this:

[MTMigration migrateToVersion:@"1.1" 
              ifMigratingFrom:@"1.0"
                        block:^{
                            [obj doSomeDataStuff];
                        }];

Though I’d already identified a real-world problem that needed solving, namely allowing a block of code to run once on an update, I began imagining all the different scenarios MTMigration might also cover. “You might want to only run the block if you’re updating, or if you’re on a fresh install!” I pontificated, “Or maybe you only want to run it if you are upgrading from a specific version!” said I.

I quickly realized that I was no longer solving a problem I actually had. As I began thinking about the implementation details, it became clear I had no real use-case to test my bright ideas on, and it began to get messy. So I scrapped it.

This principle extends to all aspects of building a library. None of the APIs I had debated about are “bad” or “wrong” in any way, I’m just not in a position to implement it. I have no real-world use for them, so I’d likely do it wrong. I really hope someone comes along that is having those exact problems, as they’ll make a killer extension to MTMigration, with the experience to back it up.

I’d encourage all developers to keep this in mind next time you’re writing a library. Are you trying to solve problems you actually have, or at least have had before? If not, consider dropping the feature. Add it when you do have the problem, or if it’s open source, let someone else take a crack at it that’s actually experiencing the problem. If no one is actually experiencing the problem, well, there’s your answer.