Code documentation best practices in Xcode
Maybe it is not so obvious for most of the developers, but the documentation of your application and code is crucial in long term. Whoever has ever worked in code maintenance knows this. The general problem is with the documentation is that everybody hates to do it, especially when this somebody is in either rush because of the deadlines or just too exited because of the new project. My first advise is KEEP CALM and DOCUMENT YOUR CODE.
Everybody, who has already read Robert C. Martin’s Clean Code knows that comments are not really welcomed anymore. The reason is that while the code is changing the original comments can be drifted apart from their original place. Not to mention if during the refactoring process the whole code changes, except the comment.
So inline comments the code can be dangerous, because they cause misunderstanding or misleading. But still, I think we need a better approach to provide documentation. And actually I have just found a really clever solution
(I think). I would focus on Objective-C, and in this language we have a header file (.h) and the implementation file (.m).
My proposal is the following:
– Make the documentation for the class in general in the header file.
– Use forward declarations and add documentation to the property or method declaration, both in the header and the implementation file, by adding @interface.
– Using #pragma mark – in order to make a distinct classification of the methods.
Let see some examples above.
Documentation in the header file
Take a look about this header file (PMONumberStatsModelController.h):
#import//1 /** Modelcontroller serving the statistical data from the draws Public API: @code - (nullable instancetype)initWithNumberCount:(nonnull NSNumber *)numbersInGame arraySizeForStatistics:(NSInteger)arraySize NS_DESIGNATED_INITIALIZER; @endcode */ @interface PMONumberStatsModelController : PMOCalendarOperatedAbstract //2 /** Designated initializer for the class @param numbersInGame The count of numbers in the Lottery game (usually 45 or 90) @param arraySize The count of numbers that you want to retrieve from the statistical lists. @return an instance of PMONumberStatsModelController */ - (nullable instancetype)initWithNumberCount:(nonnull NSNumber *)numbersInGame arraySizeForStatistics:(NSInteger)arraySize NS_DESIGNATED_INITIALIZER; @end
As you can see at 1. I inserted a documentation block by pressing alt+cmd+/, and filled it up with information. I really like the idea to know what public API offered by this class, so I use @code and @endcode to list all of the available
methods. In this way I can just alt+click on the class name, and I immediately know what methods are available. At 2 I created a documentation block fordesignated initializer.
Documentation in the implementation file
The implementation file (PMONumberStatsModelController.m) will be the following:
#import "PMONumberStatsModelController.h" #import "PMONumberStat.h" //1 @interface PMONumberStatsModelController() //2 /** NSMutableDictionary to hold the number statistical information */ @property (strong, nonatomic, nonnull) NSMutableDictionary*numberStats; //3 /** Initialize an empty mutable directory of numberStats */ - (void)createEmptyStorageForNumberOfStatistics; @end @implementation PMONumberStatsModelController #pragma mark - Initializers - (instancetype)initWithNumberCount:(NSNumber *)numbersInGame arraySizeForStatistics:(NSInteger)arraySize { if (numbersInGame) { self = [super init]; return self; } #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wobjc-designated-initializers" - (instancetype)init { @throw [NSException exceptionWithName:@"Not designated initializer" reason:@"Use [[PMONumberStatsModelController alloc] initWithNumberCount:arraySizeForStatistics: ]" userInfo:nil]; return nil; } #pragma clang diagnostic pop //4 #pragma mark - Helpers - (void)createEmptyStorageForNumberOfStatistics { NSMutableDictionary *newNumberStats = [[NSMutableDictionary alloc] init]; for (int i = 1; i < 46; i++ ) { PMONumberStat *numberStat = [[PMONumberStat alloc] initWithNumber:[NSNumber numberWithInt:i] drawDates:nil]; [newNumberStats setObject:numberStat forKey:numberStat.number]; } _numberStats = newNumberStats; } @end
As you can see at 1, I added an interface section into the implementation file. The syntax a bit different from what is used in the header file. In this section you can do a declaration of all of the properties and methods that you will implement in the implementation section. This is called forward declaration, when you are declaring the method and its signature before the actual implementation. Keep in mind, those properties and methods will be private, which means only accessible from the class, and not from outside.
In the interface section you can add comments in the usual way, the helper pop-up will help you (right after a new compilation).
Using pragma mark
With the help of the #pragma mark you can nicely divide your code into sections. Take a look at 4 on the code above, this #pragma mark - Helpers
will be displayed in the Jump Bar as the following:
Feel to free to leave a comment if you think that you can add more to the topic!