Application requirements evolve, which require us to refactor existing features. For the most part, Xcode's built-in refactoring tools work well; however, an area where the refactoring tools can't help is with stringy APIs. Core Data seems to be full of stringy method parameters - in this article I want to look at how we can de-stringify
NSEntityDescription to allow for greater compile protection and super-charge Xcode's refactoring tools.
Changing people to players
If I have a Core Data entity called:
Person and as my application evolves I decide that
Person is no longer an accurate description for that entity, instead
Player would be better. I'd fire up the rename refactoring tool and change the name with Xcode taking care of cascading the name change through the codebase.
However if my
NSEntityDescription declarations looked like this:
[NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:self.managedObjectContext];
The refactoring tool wouldn't change "Person" to "Player". The project would compile, but when this statement is executed the app would crash. I could search for the word "Person" and change it to Player" however, this is very manual and risks the chance that I don't catch them all.
A better approach is to get the refactoring tool to do it for us:
[NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([Person class]) inManagedObjectContext:self.managedObjectContext];
Here we use
NSStringFromClass([Person class]) to create the needed string, but we keep the connection with the actual class. Now the rename refactoring tool can spot that
[Person class] should become
[Player class] and make the necessary change.
By de-stringing the
NSEntityDescription declaration, we no longer need to wait on discovering a crash at runtime to know if we changed all the uses of
Player. Instead, the refactoring tool can do a better job of getting rid of
Person for us. And if any
Person declarations make it past the refactoring tool, the compiler acts the ultimate safety net - as
Person no longer exists, trying to use it will cause the project to fail to compile.
What do you think? Let me know by getting in touch on Twitter - @wibosco