Хочется кодить лучше, правильнее, грамотнее, понятнее, по правилам, ... и чтобы не было стыдно кому-нибудь показать.
Adobe любит нас, и создал для нас небольшой свод правил, который поможет не только лучше понимать Flex SDK, но и нам самим сделать свой код лучше:
Flex SDK coding conventions and best practices
Итак, сегодня мы поговорим об именовании (Naming).
Именование
Наши стандарты именования соответствуют стандартам ECMAScript и Flash Player 9.
Использование сокращений
Вообще, лучше их избегать. Например:
можно: calculateOptimalValue(), нельзя: calcOptVal().
Потому что ясность кода гораздо важнее чем минимизация количества нажимаемых клавиш. Важнее не только для нас самих, но и для тех, кому придется работать с нашим кодом.
Однако, есть общепринятые сокращения:
acc = accessibility (ButtonAccImpl)
auto = automatic (autoLayout)
eval = evaluate (EvalBindingResponder)
impl = implementation (ButtonAccImpl)
info = information (GridRowInfo)
num = number (numChildren)
min = minimum (minWidth)
max = maximum (maxHeight)
nav = navigation (NavBar)
regexp = regular expression (RegExpValidator)
util = utility (StringUtil)
Существуют и другие сокращения. Если мы не догадаемся об их смысле, придется поискать их применение в исходном коде. Или подумать еще разок.
Иногда можно встретить отсутствие логики в применении сокращений. Например, horizontalScrollPolicy и verticalScrollPolicy, но HBox и VBox.
Использование аббревиатур
Аббревиатуры довольно часто используются во Flex: AIR, CSS, HLOC, IME, MX, MXML, RPC, RSL, SWF, UI, UID, URL, WSDL, XML.
Аббревиатуры всегда пишутся либо заглавными, либо строчными буквами:
можно: SWF, swf, нельзя: Swf
Строчные буквы используются только в том случае, когда весь идентификатор именуется аббревиатурой, либо идентификатор начинается с аббревиатуры и он должен начинаться со строчной буквы.
Например:
можно: CSSStyleDeclaration, IUID, uid, IIME, imeMode.
Разделение слов
Когда идентификатор состоит из двух или более слов, используется два метода разделения слов:
- Регистром - каждое отделяемое слово пишется с большой буквы
- Подчеркиванием - слова разделяются символом подчеркивания
В некоторых местах может встретиться нарушение этого правила: комбинация слов становится целым словом: dropdown, popUp, pulldown.
Имена, содержащие тип
Если в имени нужно указать тип, поместите его, не сокращая, в конец имени. Откажитесь от использования суффиксов типа "_mc" по старой традиции ActionScript 1.
Например:
можно: border, borderSkin, or borderShape, нельзя: border_mc
Часто лучшим именем для объекта является имя его типа в отличающемся регистре (не соглашусь, т.к. смысловой нагрузки никакой - годится только для тестов и примеров):var button:Button = new Button();
Имена пакетов
Начинаются со строчной буквы и для разделения слов используется регистр: controls, listClasses.
Имена пакетов должны быть всегда существительными или отглагольными -ing формами (герундий), но не глаголами, прилагательными или наречиями.
Пакет, включающий множество схожих элементов должен именоваться общим названием этих элементов во множественной форме: charts, collections, containers, controls, effects, events ...
Обычно, -ing формами именуются пакеты, реализующие концепции (я бы сказал процессы): binding, logging, messaging, printing ...
С другой стороны, это могут быть существительные, выражающие концепцию: accessibility, core, graphics, rpc ...
Пакет, содержащий классы, которые обеспечивают работу компонента FooBar, должен называться fooBarClasses.
Имена файлов
Имена файлов импортируемых API должны соответствовать определениям public API. Но для include-файлов (файлов фрагментов кода) это правило не применяется.
Имя include-файла начинается с заглавной буквы и разделение слов в имени осуществляется регистром: BorderStyles.as, ModalTransparencyStyles.as
Имена файлов ресурсов пишутся строчными буквами, а слова разделяются символом подчеркивания: icon_align_left.png
Имена пространств имен
Именуются строчными буквами с разделением слов символом подчеркивания: mx_internal, object_proxy.
Имена интерфейсов
Начинаются с заглавной "I", разделение слов в имени осуществляется регистром: IList, IFocusManager, IUID.
Имена классов
Начинаются с заглавной буквы, разделение слов в имени осуществляется регистром: Button, FocusManager, UIComponent.
Подклассы Event именуются FooBarEvent.
Подклассы Error именуются FooBarError.
Подкласс EffectInstance, ассоциированный с эффектом компонента FooBar именуется FooBarInstance.
Подклассы Formatter именуются FooBarFormatter.
Подклассы Validator именуются FooBarValidator.
Классы скинирования компонентов именуются FooBarBackground, FooBarBorder, FooBarSkin, FooBarIcon, FooBarIndicator, FooBarSeparator, FooBarCursor, и т.д.
Классы утилит именуются FooBarUtil (не FooBarUtils - пакет может именоваться во множественном числе, но класс - только в единственном).
Общепринято базовый класс именовать FooBarBase: ComboBase, DateBase, DataGridBase, ListBase.
Имена событий
Начинаются со строчной буквы, разделение слов в имени осуществляется регистром: move, creationComplete.
Имена стилей
Начинаются со строчной буквы, разделение слов в имени осуществляется регистром: color, fontSize.
Значения строковых свойств
Начинаются со строчной буквы, разделение слов в имени осуществляется регистром: "auto", "filesOnly".
Имена констант
Именуются полностью заглавными буквами с разделением символом подчеркивания: OFF, DEFAULT_WIDTH.
Если константа строковая, слова в имени константы должны соответствовать словам в строке ее значения:public static const FOO_BAR:String = "fooBar";
Имена свойств (переменные и установщики)
Начинаются со строчной буквы, разделение слов в имени осуществляется регистром: i, width, numChildren.
Используйте "i" для имени переменной цикла "for", и "n" для имени верхнего предела цикла.Используйте "j" для имени переменной вложенного цикла "for", и "m" для его имени верхнего предела цикла:
for (var i:int = 0; i < n; i++)
{
for (var j:int = 0; j < m; j++)
{
...
}
}
Используйте "p" для имени переменной цикла "for..in":for (var p:String in o)
{
...
}
Бывают ситуации, когда в классе необходимо переопределить установщик, но предполагается, что базовый установщик будет продолжать использования. Для сохранения базового установщика, необходимо создать новый установщик, имя которого должно формироваться путем добавления к имени базового установщика символа "$". Полученный установщик нужно определить как "final". Он не должен ничего делать, кроме вызова базового установщика. Напимер, нам нужно перекрыть установщик numChildren, но при этом сохранить возможность вызывать базовый super.numChildren - для последнего мы создаем следующее:mx_internal final function get $numChildren():int {
return super.numChildren;
}
Переменные для хранения данных установщиков
К имени установщика добавляется символ подчеркивания "_":
для foo имя переменной _foo.
Имена методов
Начинаются со строчной буквы, разделение слов в имени осуществляется регистром: measure(), updateDisplayList().
Имена методов должны быть всегда глаголами.
Лучше не использовать методы без параметров подобно getFooBar() или setFooBar(). Вместо них используйте установщики. Однако, если getFooBar() - медленный метод, требующий больших вычислений, лучше его назвать findFooBar(), calculateFooBar(), determineFooBar(), и т.д., выражая его суть, а не то, что он способен возвращать что-либо.
Аналогично установщикам, если базовый метод перекрывается, но требуется сохраненить доступ к нему, создается метод с именем базового метода, перед которым добавляется символ "$":mx_internal final function $addChild(child:DisplayObject):DisplayObject
{
return super.addChild(child);
}
Обработчики событий
Имя обработчика события формируется путем добавления к имени типа события слова "Handler": mouseDownHandler().
Если обработчик предназначен для событий, отправленных субкомпонентами (т.е. не this), перед именем обработчика, сформированного по вышеописанному правилу, добавляется имя субкомпонента, отделенное символом подчеркивания "_": textInput_focusInHandler().
Имена аргументов
Всегда используйте для установщиков имя аргумента "value":
можно - public function set label(value:String):void
нельзя - public function set label(lab:String):void
нельзя - public function set label(labelValue:String):void
нельзя - public function set label(val:String):void
Всегда используйте для обработчиков событий имя аргумента "event":
можно - protected function mouseDownHandler(event:Event):void
нельзя - protected function mouseDownHandler(evt:Event):void
Имена пакетов ресурсов
Если пакет рессурсов содержит ресурсы для определенного пакета классов, имя пакета рессурсов должно быть таким же: controls, {formatters}}, validators.
Имена идентификаторов ресурсов
Начинаются со строчной буквы, разделение слов в имени осуществляется регистром: pm, dayNamesShort.
Прочая терминология
Избегайте использование слова "object", т.к. оно вносит неопределенность.
Слово "item" - элемент данных и никогда DisplayObject.
Слово "renderer" - это DisplayObject, который отображает элемент данных.
Слово "type" означает тип AS3, используйте вместо него слово "kind".
С именованием разобрались. Теперь попытаемся придерживатся этих правил на практике. У меня есть много своих правил именования, и скорее всего часть из них я оставлю (например именовать private-свойства с префиксом в два подчеркивания, а protected-в одно), но правила, принципиально идущие вразрез с вышеприведенными надо искоренять.
Следующий раздел "Language Usage" разберем в ближайшее время.
11 комментариев:
Отличная работа! Спасибо
Не лучше ли вместо "установщик" использовать "сеттер"?
Я использовал принятый в литературе термин "установщик/получатель" (кроме того, я опустил слово "получатель" - на мой взгляд, "установщик" вполне отражает сущность термина, когда нет конкретики). Мне кажется это правильно :). Да и слово красивое.
В разговорной же речи, я за геттер/сеттер, т.к. это удобнее.
Кстати, Сеттер - это порода собак.
Пригодно для случая с AS, когда вся аппликация доставляется конечному пользователю в пристойном компактном виде. Как считаешь, следует ли придерживаться подобных правил при написании JS?
Как упоминалось выше, эти правила включают большинство правил ECMAScript, а JS также входит в число диалектов ECMAScript: http://en.wikipedia.org/wiki/ECMAScript.
Любой код, AS или JS, оформленный согласно каким-либо правилам, выглядит красиво и профессионально. Чем ближе правила оформления к стандарту, тем больше людей сможет в нем разобраться. Тем легче отлаживать, производить рефакторинг, генерировать документацию и т.д.
Кроме того, как будет видно из следующей главы, следование стандартам позволяет создать более оптимальное приложение.
Обычно обзываю переменные в JS очень коротко, чтобы уменьшить размер исходника. Конечно, удобнее и понятнее писать myVariableName чем mvn, но привычка, блин, со времён медленного интернета :)
Да, тема снижения объема сокращением длинных имен вполне может быть актуальна для JS. А для сильнопосещаемых сервисов даже очень.
Хотя, конечно, сегодня интернет достаточно жирный для того чтобы на экономить на именах, но теоретически, сокращение качаемых объемов всегда приветствуется.
Кстати, столкнулся с похожей ситуацией, когда програмил под SmartFox Server. При формировании данных для обмена с сервером как раз очень важен размер переменных. Там переменные складываются в объекты, которые затем преобразовываются в пакет и отправляются на сервер/клиент.
Для циклически повторяющихся запросов, сокращение имен жестко актуально, т.к. на этом можно сэкономить мегабайты трафика.
"нельзя - protected function mouseDownHandler(evt:Event):void
можно - protected function mouseDownHandler(event:Event):void"
Почему ?
Потому что "Всегда используйте для обработчиков событий имя аргумента event".
Это так же следствие правила "Использование сокращений".
Если смущают слова "можно/нельзя", то хочу отметить, что вообще, почти все правила носят рекомендательный характер. Можно было бы в принципе обойтись словами "лучше/хуже". Но что бы сделать акцент на важности правил, я применил именно эти слова.
Я не совсем точно поставил вопрос. Он должен был звучать так: "Почему `всегда используйте для обработчиков событий имя аргумента event`?" Типичный обработчик событий принимает всегда только один аргумент, и только из иерархии flash.events.Event, поэтому рекомендацию не сокращать имя этого аргумента считаю безосновательным, а на против советовал бы использовать краткую форму handler(e:SomeEvent), как скажем в случае с простыми, не вложенными, итерирующими по индексам циклами for (i;i<10;i++)... А к написанию этого коммента сподвиг тот факт, что я хочу этот пост использовать как "обязательные к исполнению стандарты" внутри коллектива разработчиков.
Ок, идею понял.
На мой взгляд разница между i и e существенна.
Переменная цикла i - простая целочисленная переменная (думаю, что это сокращение index), и разработчики используют ее с древних времен (я впервые ее применил где-то в начале 90х в фортране на лабах по каким-то основам программирования). То есть это в принципе многолетняя традиция. Кроме того, есть еще вложенные циклы с j, k, ...
Аргумент обработчика события event - это объект. Имеет набор свойств, методов и т.п. Мне кажется, что при обращении к ним, большое значение имеет как это выглядит и читается. Например, event.type впринципе так и прочитается тип события (ну по русски то как всегда всё шиворот на выворот :) а по их - всё четко). И сравним прочтение с e.type.
Про сокращения evt я вообще молчу, - где смысл в сокращении всего на 2 буквы?
И дело вообще не просто в обработчике событий, а в общей системе - полнота и читабельность.
Отправить комментарий