даже если вы пишите код сами ✤ и думаете, что исходники никто и никогда не увидит ✤ или это проект на 15 минут ✤ Представляйте граммар-наци с тесаком у себя за спиной
Tests/ – отдельный каталог для тестов ✤ xib’ы традиционно валяются в корне проекта ✤ *.png; *.jpg; etc. – выносить в Resources/ если их больше пяти штук ✤ В общем случае – выносить в отдельные каталоги логические группы файлов, когда их нагромождение в корне затрудняет поиск
Classes/ ✤ Support/ – код поддержки (дополнительные категории, общие делегаты) ✤ Controllers/, UI Controllers/ – контроллеры хранилища, сети, интерфейса. Удобно далее группировать по UITabBar’у ✤ Model/ – любые ORM-like классы, в том числе производные от NSManagedObject ✤ Other Sources/ – удачное место для всех «внешних» фреймворков (DDXML, Three20, ...)
✤ FooAppDelegate: FooAppDelegate.h ✤ Общий хедер – связанные классы и протоколы: ✤ FooController, FooControllerDelegate: FooController.h ✤ в том числе – связанные структуры данных (enum, struct) ✤ Отдельный хедер – категория: ✤ NSString (SmsLength): NSString+SmsLength.h (или NSStringAdditions.h) ✤ Нет хедера – Unit-тест: ✤ FooControllerTest: FooControllerTest.m
форматирования ✤ Это очень важно! ✤ Его любыми способами навязывает тимлид ✤ в том числе – хуки на VCS, финансовые штрафы ✤ если я ставлю { ... } в стиле “linux kernel”, то все мои девелоперы тоже ставят { ... } аналогично ✤ brew install uncrustify + UniversalIndentGUI
огромных плюса ✤ быстро работающие log, diff, blame ✤ Дешевые бранчи позволяют перестроить подход к написанию кода и систематизировать коммиты (см. bit.ly/git-branching) ✤ git-svn позволяет прозрачно и удобно работать в корпоративной «svn- среде»
Или хотя бы ясные ✤ insertObject: atIndex: – коротко и понятно ✤ insert: at: – что мы встявляем? Что означает второй аргумент? ✤ removeObjectAtIndex:, removeObject: – удачные названия ✤ remove: – что мы удаляем? ✤ Не придумывайте лишних аббревиатур ✤ destinationSelection:, setBackgroundColor: – хорошо ✤ destSel:, setBkgdColor: – плохо ✤ Для списка общеупотребляемых аббревиатур смотрите Coding Guidelines ✤ Соблюдайте ясность интерпретации названия ✤ sendPort – отправляет порт или возвращает порт отправки? ✤ displayName – показывает имя или возвращает значение заголовка?
в Cocoa/Cocoa Touch ✤ Особенно это важно для полиморфизма ✤ - (int)tag существует в ряде разных классов Cocoa (не связанных прямым наследованием) ✤ Не ссылайтесь на себя ✤ Имена не должны ссылатся на сам объект: ✤ NSString vs NSStringObject ✤ Исключение из правила – константы-маски и константы уведомлений: ✤ NSUnderlineByWordMask ✤ NSTableViewColumnDidMoveNotification
имен ✤ Используйте префиксы в именах классов, протоколов, функций, констант и структур ✤ Используйте префиксы в названиях методов категорий, расширяющих стандартные классы ✤ Не используйте префиксы для других методов, имен полей
которое описывает задачи класса ✤ Название класса должно начинаться с большой буквы ✤ Название протокола обычно обозначает общее поведение методов протокола, Apple рекомендует использовать герундий: ✤ NSLocking vs. NSLock
слова init, copy, new обозначают специальное поведение метода (retain count +1) ✤ Методы, которые описывают действие, выполняемое над объектом, удобно называть с глагола: ✤ - (void)invokeWithTarget:(id)target; ✤ - (void)selectTabViewItem:(NSTabViewItem *)tabViewItem;
должно быть понятно, как его использовать: ✤ - (void)sendAction:(SEL)aSelector to:(id)anObject forAllCells: (BOOL)flag; ✤ - (void)sendAction:(SEL)aSelector :(id)anObject :(BOOL)flag; ✤ Слово перед аргументом должно описывать аргумент: ✤ - (id)viewWithTag:(int)aTag; ✤ - (id)taggedView:(int)aTag;
метода ✤ - (int)runModalForDirectory:(NSString *)path andFile:(NSString *) name andTypes:(NSArray *)fileTypes; ✤ Кроме того случая, если «and» используется для объединения двух разных действий: ✤ - (BOOL)openFile:(NSString *)fullPath withApplication:(NSString *)appName andDeactivate:(BOOL)flag;
✤ Свойства это: ✤ Ограничение доступа (readonly) ✤ Режим управления памятью (assign, retain, copy) ✤ Прозрачная реализация собственных методов доступа (getter, setter)
✤ Используйте автоматически сгенерированные поля (@synthesize) ✤ В таком случае, блок { ... } в описании класса вообще можно опустить ✤ Для явного доступа к ivar (например в своем setter) используйте постфикс “_” (он некрасиво смотрится, что уменьшит желание его использовать): ✤ @property (nonatomic, copy) NSString *title; ✤ @synthesize title = title_; ✤ Никогда не используйте ivar_ нигде, кроме как в getter/setter
общий хедер! ✤ Используйте или отдельный файл MyClass+Private.h, или просто анонимную категорию в начале MyClass.m: @interface MyClass () @property (nonatomic, readwrite, retain) *privateObjects; - (void)privateOperation; @end
рядом с new/init/copy/retain, чтобы не забыть потом сделать release ✤ Создавайте в своих классах воспомогательные конструкторы с автоматической делегацией объекта в ближайший пул: ✤ + (id)controllerWithSomeObject:(SomeObject *)object;