Edit: Interestingly enough, a few days after publishing this post, the team at @rwenderlich released their own objective-c style guide. Their guide does a great job combining elements from other conventions and Apple’s own, though I wish they would touch upon things like class structuring and lazy instantiation more.
This is a follow-up to the previous post on objective-c coding conventions. To illustrate the positive impacts a good coding convention can have, we will be re-factoring a medium sized view controller class from my previous Home-For-iOS project.
The PSHCoverFeedViewController class is a simple view controller responsible for managing the cover flow pages and responding to user actions like reloading of the feed and swiping. It conforms to the protocols UIPageViewControllerDataSource, PSHMenuViewControllerDelegate, PSHCoverFeedPageViewControllerDelegate and PSHMessagingViewControllerDelegate, and relies on a handful of view controllers like the PSHMenuViewController to handle dedicated logic like setting up a draggable actions menu. There is very little UI code so we won’t be doing conversion to auto layout.
With the context set, let’s head on to the re-factoring
Import statements and class extension – original:
Import statements and class extension – refactored:
No magic here. The import statements and interface declarations have been sorted alphabetically and each conforming protocol has its own line to eliminate horizontal scrolling while reading the code.
Class implementation and pragma marks – original:
Although pragma marks were in place in the original to partition the class into sections, there wasn’t as much organization when it came to the non-delegate related methods. Huge chunks of logic were placed under catch-all titles like “init methods” and “Menu related”.
Class implementation and pragma marks – refactored:
The extra pragma marks brought to the class a formal structure and stronger sense of hierarchy. Distinction of public and private sections made it easier at a glance to grasp what the class is about. However, the init method is still rather generic and non-descriptive, so that’s what we will work on next.
Init Methods – original:
Init Methods – refactored:
What stands out immediately is the much simplified viewDidLoad, which now only animates the menu buttons when the view is shown. A lot of the initialization logic were moved to private methods with clear names and the invocation is centralized in initWithNibName. These are shown next:
Notice again how objects initialization logic is absent even in these methods – addSubviewTree does not perform anything other than adding menuViewController’s view to the root view. Contrast this with the old initFeedsPageViewController where creation of objects, view hierarchy set up and other UI logic like animation are all mingled together. Lazy initialization plays a great role in this. By overriding the init methods of the private properties, our core logic is decoupled from the often distracting initialization logic, making it quicker for readers to understand the purpose of the methods. and the properties are always ready and prepared when we need them.
The delegate methods do not need re-factoring, though they have been moved to the bottom of the file.
So there you have it. The functionality of the class is exactly the same before and after the re-factoring, but it is much more readable and hence easier to maintain. I reckon the little amount of extra effort it took to make this class compliant to my new favorite coding convention went a long, long way.