Readdle Coding Standard∗ А.А. Буданцов, Д.А. Процеров
1
Введение
Данный документ содержит рекомендации по оформлению исходного кода на языках Objective-C и, в некоторой степени, C/C++. Соблюдение данных рекомендаций поможет снизить дискомфорт при работе с исходным кодом разных разработчиков работающих в Компании, повысить читаемость и понятность кода, избежать проблем при реиспользовании кода в других проектах.
2
Здравый смысл
Данный документ является дополнением к здравому смыслу. Список перечисленных рекомендаций является открытым и не учитывает все богатство фантазии разработчиков.
3
Общие положения
3.1
Длина строки
При написании кода рекомендуется ограничивать длину строки 120 символами. На заметку: В среде разработки Xcode включить индикацию горизонтального положения курсора (колонки) можно в меню Xcode → Preferences... → Text Editing → Display Options → Show column position Рассмотрите следующие варианты, для того чтобы разбить длинную строку на более короткие: • Если в строке присутствует вызов функции (передача сообщения) с большим количеством аргументов — перенесите какие-то из аргументов(каждый аргумент) на новую строку. Многострочные сообщения Xcode прекрасно выравнивает по двоеточиям: ∗ Редакция
1.0
1
UIAlertView *a = [[UIAlertView alloc] initWithTitle:title message:text delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; • Если в строке присутствует вложенные вызовы функций (результат вызова одной функции, является аргументом для другой) — объявите временную переменную строкой выше и поместите туда значение одной из функций; • Логические и арифметические выражения следует разбивать на строки по знакам операций, оставляя сам знак в конце предыдущей строки.
3.2
Пустые строки
Пустыми строками следует разделять: • Реализации функций и обработчики сообщений; • Хорошим тоном является разделение пустой строкой разных логических блоков внутри функции.
3.3
Пробелы
Пробелом следует разделять • арифметические и логические операции, оператор присваивания — выделяются пробелами с обоих сторон: int buttonOffset = frameOffset +
previousButtonHeight + margin;
• составные части конструкции for — пробел ставиться после точки с запятой: for(i = 0; i < 10; i++) • аргументы функции(С) — пробел ставится после запятой: doSomething(arg1, arg2, arg3) Пробелами не следует разделять • в вызове сообщения — имя сообщения/аргумента и его значение: [object callWithValue:value] • в вызове функции — имя функции и открывающую скобку: doSomething(argument) • переменную и операцию инкримента/декримента
2
3.4
Операторные скобки
Открывающая скобка находится на той же строке, на которой происходит объявление блока: - (id)initWithFileName:(NSString *)fileName { ... if (pathToFile && [pathToFile hasSuffix:@"rtfd.zip"]) { ... for(i = 0; i < 10; i++) { ... struct mystruct { // не совсем операторные скобки ... @interface BlackMail : UIView { Если объявление блока занимает несколько строк, то операторная скобка начинается с новой строки: @interface NewGifController : UIViewController { Закрывающая скобка всегда находиться на строке одна, и не может сопровождаться какими-либо другими символами или конструкциями (кроме комментариев). Таким образом, предыдущие правила определяют способ расстановки операторных скобок при использовании else if: if (a == 1) { // code } else if (b == 1) { // more code } else { // even more code }
3.5
* в указателях и функциях
Символ * в объявлении переменных-указателей, возвращаемом значении функций, аргументов функции — всегда отбивается пробелами от основных типов данных: NSString *RDDocsDirectory(); ... - (void)addColor:(UIColor *)color; ... NSObject *object = nil; ... char *test = (char *)malloc(1024);
3
4
Правила именования
В отношении именования классов, функций, сообщений и пр. мы придерживаемся рекомендаций от Apple: http://developer.apple.com/documentation/ Cocoa/Conceptual/CodingGuidelines/CodingGuidelines.html Документ по ссылке выше рекомендуется для тщательного изучения. Ключевые положения уточняющие этот документ или входящие с ним в противоречие (и имеющие более высокий приоритет) будут изложены в этом разделе позднее.
4.1
Префиксы имен классов и функций
Для классов и функций предназначенных для самого широкого использования, мы используем префикс RD. Авторам кажется удачной идея использовать для отдельных проектов свои собственные префиксы (таких как RD2 для ReaddleDocs2). Вопрос использования/выбора префикса решается для каждого проекта индивидуально.
5 5.1
Прочие рекомендации init и dealloc
Рекомендуется физически располагать реализацию обработчика сообщения dealloc сразу после обработчиков сообщений init-. . . . Всем переменным класса которым в dealloc будет послано release, в initметодах должно быть присвоено nil, или новое значение увеличивающее retainCount (alloc-init, new, retain)
5.2
Свойства и переменные класса
Допускается делать имена переменных и свойств одноименными в том случае, если свойство синтезируется (@synthesize). Если реализация свойства динамическая, однако по смыслу с этим свойством связана переменная — рекомендуется предварять имя этой переменной символом _ Например: @interface TestFile : NSObject { NSString *fullName; long long _size; } // synthesized properties @property(nonatomic, readonly) NSString
*fullName;
// dynamic properties @property(nonatomic, readonly) NSUInteger
size;
@end
4
5.3
NSLocalizedString
Все строки пользовательского интерфейса должны присутствовать в исходном коде внутри макроса NSLocalizedString. NSLocalizedString(строка, описание того, где она используется) Например: email = [UITextField alloc] initWithFrame:...]; email.placeholder = NSLocalizedString(@"e-mail", @"placeholder for email field"); По-умолчанию NSLocalizedString вернет свой первый аргумент. На начальных этапах работы мы просто пользуемся этим фактом, позже NSLocalizedString используется при переводе продукта на другой язык.
5.4
NSAssert
Настоятельно рекомендуется использовать NSAssert — проверяя условия, при которых работа программы окажется бессмысленной или невозможной. NSAssert(условие, ошибка для случая если условие не выполняется) Например: FILE *f = fopen(file, "r"); NSAssert(f != NULL, @"unable to open the File"); ... Существуют так же NSAssert1, NSAssert2, NSAssert3, NSAssert4, NSAssert5 у которые есть дополнительные аргументы, на которые можно ссылатся (форматной строкой, как в NSLog) из описания ошибки. NSAssert прерывает работу программы и должен использоваться только для фатальных ошибок.
5.5
ReaddleLib
К использованию во всех проектах Readdle рекомендуется ReaddleLib (ReaddleLib.h, ReaddleLib.m) содержащие полезные функции и расширения системных классов. Мы будем прилагать максимум усилий для того, чтобы в ReaddleLib находились действительно полезные вещи.
5.6
#pragma mark
Хорошим тоном является разбиение длинных файлов на логические секции при помощи #pragma mark. Для наглядного выделения, мы добавляем по две директивы #pragma mark - выделяя в Xcode заголовок тонкими линиями. #pragma mark #pragma mark Заголовок #pragma mark 5
5.7
Выравнивание в объявлении переменных класса
Как свидетельствует опыт, использование выравнивания в объявлении переменных класса ведет к улучшению читаемости кода. @interface TestClass : NSObject { NSInteger member1; NSInteger member2; RDSomeLongClassName *classMemeber1; } @property (nonatomic) NSInteger member1; @property (nonatomic, readonly) RDSomeLongClassName *classMemeber1;
6