четверг, 26 августа 2010 г.

Соглашения по написанию кода

Представляю вашему вниманию перевод Flex SDK coding conventions and best practices. Здесь соглашения по написанию кода и лучшие практики.

По известному закону ближе к концу перевода наткнулся на уже готовый перевод на русский, но решил все-таки выложить, т.к.:
- получилось не так уж и плохо;
- хуже от этого не будет :)


Flex SDK coding conventions and best practices






Введение



Этот документ определяет соглашения написания кода компонент открытого фреймворка Flex на языке ActionScript 3. Соблюдение этих соглашений сделает исходный код связанным и последовательным, хорошо организованным и профессиональным.
Некоторые из этих соглашений совершенно произвольны, т.к. не всегда есть единственный лучший способ написать определенный код. Однако, для обеспечения совместимости, весь код Flex SDK будет соответствовать этим соглашениям.

Именование



Выбор хороших названий очень важен для легкого в использовании и понимании кода. Вы всегда должны уделять некоторое время, чтобы подумать, действительно ли вы выбрали хорошее имя для свойства или метода, особенно если это часть открытого API.
Наши стандарты именования главным образом совместимы с ECMAScript и Flash Player 9.

Сокращения



Как правило, их следует избегать. Например, calculateOptimalValue() – лучшее название для метода, чем calcOptVal().
Ясность более важна, чем уменьшение количества нажатий клавиш. И если вы не используете сокращений, то другим разработчикам не нужно будет запоминать какое сокращение слова «qualified» (например) больше нравиться вам – «qual» или «qlfd».
Однако мы стандартизировали некоторые сокращения:
* acc от accessibility (доступность), например ButtonAccImpl
* auto от automatic (автоматический), например autoLayout
* eval от evaluate (оценивать), например EvalBindingResponder
* impl от implementation (реализация), например ButtonAccImpl
* info от information (информация), например GridRowInfo
* num от number of (количество, число), например 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.

Границы слов в названии



Если идентификатор содержит несколько слов, мы используем два способа, чтобы показать границы этих слов: изменение регистра (LayoutManager или measuredWidth) или нижнее подчеркивание (object_proxy).
Иногда непонятно, является ли сочетание слов в названии просто сочетанием или устоявшимся отдельным словом, и мы снова в таких случаях непоследовательны: dropdown, popUp, pulldown.
В случае, когда в названии идут подряд два или более акронима, необходимо придерживаться соглашений для акронимов. Пример (который фактически не используется) – loadCSSURL(). Но по возможности избегайте таких названий.

Названия, использующие названия типов данных



Если вы хотите включить тип данных в название, сделайте это в конце названия. Не используйте старые соглашения ActionScript 1, которые предлагают использование суффиксов типа _mc. Например, границу скина или шейпа стоит назвать borderSkin или borderShape, но не border_mc.
Часто, лучшее название для объекта это просто название соответствующего типа данных в нижнем регистре
var button:Button = new Button();


Имена пакетов



Их следует начинать со строчной буквы и использовать заглавные буквы для обозначения границ слов: controls, listClasses.
Имена пакетов должны быть всегда существительными или герундиями (существительное, образованное от глагола с – ing на конце), но не глаголами, прилагательными или наречиями.
У пакета, в котором реализуется множество подобных друг другу вещей, должно быть название, которое является множественным числом этой вещи: charts, collections, containers, controls, effects, events, formatters, managers, preloaders, resources, skins, states, styles, utils, validators.
Распространено использование герундий для названия пакета, содержимое которого совершает определенное действие: binding, logging, messaging, printing. С другой стороны это могут быть существительные, определяющие концепцию: accessibility, core, graphics, rpc.
Пакет, содержащий классы, обслуживающие компонент FooBar должен называться fooBarClasses.

Имена файлов



Для импортируемых API, имена файлов должны совпадать с именами файлов куда они импортируются. Но это правило не распространяется для включаемых (с помощью директивы include) файлов.
Имена включаемых (include) файлов для метаданных типа [Style(...)] должны начинаться с большой буквы и использовать верхний регистр для выделения границ слов и иметь на конце слово «Style»: BorderStyles.as, ModalTransparencyStyles.as.
Начинайте названия присоединяемых файлов с нижнего регистра и используйте нижнее подчеркивание для разделения слов: icon_align_left.png.

Имена пространств имен



Начинайте названия с нижнего регистра и используйте нижнее подчеркивание для разделения слов: mx_internal, object_proxy.

Имена интерфейсов



Названия следует начинать с буквы «I» и использовать верхний регистр для выделения границ слов: IList, IFocusManager, IUID.

Имена классов



Их следует начинать с заглавной буквы и использовать верхний регистр для выделения границ слов: Button, FocusManager, UIComponent.
Имя подкласса класса Event - FooBarEvent.
Имя подкласса класса Error - FooBarError.
Имена подклассов с функцио
Имя подкласса класса Formatter – FooBarFormatter.
Имя подкласса класса Validator – FooBarValidator.
Имена для классов скинов - FooBarBackground, FooBarBorder, FooBarSkin, FooBarIcon, FooBarIndicator, FooBarSeparator, FooBarCursor и т.д.
Сервисные классы лучше назвать FooBarUtil (но не FooBarUtils, оставьте множественное число для именования пакетов, классы должны именоваться в единственном числе)
Базовые классы принято называть FooBarBase: ComboBase, DateBase, DataGridBase, ListBase.

Имена событий



Название начинается со строчной буквы и используется изменение регистра для обозначения границ слов: "creationComplete".

Имена стилей



То же: color, fontSize.

Строковые значения свойств



То же: "auto", "filesOnly"

Имена констант



Имена констант пишутся в верхнем регистре, и для разделения слов используется нижнее подчеркивание: OFF, DEFAULT_WIDTH.
Значение константы (если ее тип String) должно соответствовать имени этой константы:
public static const FOO_BAR:String = "fooBar";


Имена свойств (переменных и геттеров/сеттеров)



Начинаются со строчной буквы и используется верхний регистр для выделения границ слов: i, width, numChildren.
Используйте «i» для именования итератора цикла и «n» для границы цикла. «j» и «m» используются аналогично, если нужен вложенный цикл:
for (var i:int = 0; i < n; i++)
{
for (var j:int = 0; j < m; j++)
{
...
}
}


Используйте «p» (сокращение от «property» - свойство) для использования в циклах for-in:
for (var p:String in o)
{
...
}


Если в классе переопределяются геттер/сеттер и есть необходимость использовать базовые (непереопределенные) геттер/сеттер, то переопределенные называются также как и базовые, но с добавлением в начале символа «$». Переопределенный геттер/сеттер должен быть объявлен с инструкцией «final» и не делать ничего, кроме вызова супергеттера/сеттера:
mx_internal final function get $numChildren():int
{
return super.numChildren;
}


Имена закрытых переменных



В начале имени добавляется нижнее подчеркивание: _foo.

Имена методов



Начинаются со строчной буквы и для обозначения границ слов используется верхний регистр: measure(), updateDisplayList().
Имена методов всегда должны быть глаголами.
Параметризующие методы нельзя называть getFooBar() и setFooBar(); они должны быть реализованы в виде геттеров/сеттеров. С другой стороны, если метод getFooBar() медленный и требует большого количества вычислений, то его лучше назвать findFooBar(), calculateFooBar(), determineFooBar() и т.д.
Если класс переопределяет метод и есть необходимость продолжать использовать базовый метод, то переопределенные называются также как и базовые, но с добавлением в начале символа «$». Переопределенный метод должен быть объявлен с инструкцией «final» и не делать ничего, кроме вызова базового метода:
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» (не «e», «evt» или «eventObj») для именования аргумента обработчика:
protected function mouseDownHandler(event:Event):void


Имена пакетов ресурсов



Если пакет ресурсов содержит ресурсы для специфического пакета, назовите пакет ресурсов так же как и специфический пакет: controls, {formatters}}, validators.

Имена идентификаторов ресурсов



Должны начинаться со строчной буквы и использовать верхний регистр для обозначения границ слов: pm, dayNamesShort.

Прочие соглашения



Избегайте использования в именах слова «object», т.к. это создает неопределенность.
Используйте слово «item» для именования элемента данных, но не отображаемого объекта.
Слово «renderer» для именования отображаемого объекта, который визуализирует элемент данных.
Не используйте «type» для обозначения типа, для этого используйте «kind»

Использование языка



Эта часть соглашений покажет, как использовать конструкции языка AS3, особенно когда можно получить один и тот же результат разными способами.

Опции компилятора



Компилируйте с включенными опциями -strict и -show-actionscript-warnings. (По умолчанию они включены в flex-config.xml)

API, основанные на свойствах



Старайтесь применять API, которые основываются на свойствах, а не на методах, т.к. это более подходит для декларативного стиля программирования на MXML.

Объявления типов



Пишите тип каждой объявленной переменной, аргумента, возвращаемого методом значения и константы. Если переменная не имеет типа, то это нужно указать явно.
Так
var value:*;


Но не так:
var value;


Используйте самый подходящий тип для более полного соответствия. Например int а не Number, и тем более не Object или просто *. Другой пример – обработчик mouseDownHandler должен иметь аргумент event:MouseEvent а не event:Event.
Используйте int для целых чисел, даже если они не могут быть отрицательными. Используйте uint только для цветов RGB, битовых масок и других не числовых переменных.
Используйте * только для значений, которые могут быть не определены (undefined). В остальных случаях используйте Object, чтобы при значении равном null получить сообщение “object doesn't exist”
Если вы присваиваете какой-либо переменной тип Array, добавляйте в комментарии тип элементов, которые содержит этот массив:
var a:Array /* of String */ = [];


но не так
var a:Array = [];


И делайте так
function f(a:Array /* of Number */):Array /* of Object */
{
...
}


но не так
function f(a:Array):Array


Литералы



Undefined

Избегайте использования undefined везде, где это возможно. Он необходим только там, где тип переменной объявлен с *. Однако и * вы должны использовать как можно реже.

int и uint

Не используйте десятичную точку в целом числе:
Нужно так:
2

Но не так:
2.


Используйте нижний регистр для х и верхний для A-Z в шестнадцатеричных чисел
Нужно так:
0xFEDCBA


Но не так:
0Xfedcba


Всегда используйте запись цветов RGB с использованием шестизначного номера.
Нужно так:
private const BLACK:uint = 0x000000;


Но не так:
private const BLACK:uint = 0; 


Number
Если числовое значение может быть дробным, указывайте это с помощью десятичной точки и нуля, который следует за этой точкой:
Так
alphaFrom = 0.0;

alphaTo = 1.0;

Но не так
alphaFrom = 0;

alphaTo = 1;

Однако не нужно это делать для координат точки даже если она может быть дробной.
Нужно так:
var xOffset:Number = 3;


Но не так:
var xOffset:Number = 3.0;


Используйте е, а не Е для обозначения экспотенциальных значений:
Нужно так:
1.0e12


Но не так:
1.0E12


Используйте значение по умолчанию для числовых значений NaN при объявлении числовых переменных, если нет другого значения.

String
Используйте двойные, а не одинарные кавычки для разделения строк, имеющих кавычки как символ строки
Нужно так
"What's up, \"Big Boy\"?"


Но не так:
'What\'s up, "Big Boy"?'


Используйте \u, а не \U для экранирования уникода.

Array

Используйте литерал массива для создания нового вместо конструкции new Array()
Нужно так:
[]


Но не так:
new Array()


И нужно так
[ 1, 2, 3 ]


Но не так
new Array(1, 2, 3)


Используйте конструктор если необходимо создать пустой массив определенной длины, т.е. вместо [ undefined, undefined, undefined ] использовать new Array(3)

Object
Используйте литерал {} вместо new Object().
Нужно так:
{}


Но не так:
new Object()


И нужно так:
o = { a: 1, b: 2, c: 3 };


Но не так:
o = new Object();
o.a = 1;
o.b = 2;
o.c = 3;


Или так:
o = {};
o.a = 1;
o.b = 2;
o.c = 3;


Function

Избегайте использования литералов функций для создания анонимных функций. Необходимо использовать методы классов и функции уровня пакета.
Если нужно использовать литерал функции, объявите тип возвращаемого значения и закончите последнюю строчку тела функции точкой с запятой:
Нужно так:
function(i:int):void { doIt(i - 1); doIt(i + 1); }


Но не так:
function(i:int) { doIt(i - 1); doIt(i + 1) }


RegExp

Используйте литерал вместо конструкции RegExp для создания регулярного выражения из строки:
Нужно так:
var pattern:RegExp = /\d+/g;


Но не так:
var pattern:RegExp = new RegExp("\\d+", "g");


XML и XMLList

Используйте литерал вместо конструктора для создания XML из строки:
Нужно так:
var node:XML = ;


Но не так:
var node:XML = new XML("");


Используйте двойные кавычки для определения значений атрибутов XML:
Нужно так:
var node:XML = ;


Но не так:
var node:XML = ;


Классы

Используйте полную ссылку на класс (с именами пакетов) только если нужно разделить в классе два одинаковых класса, которые принадлежат разным пакетам:
Нужно так:
import mx.controls.Button;
...
var b:Button = new Button();


Но не так:
import mx.controls.Button;
...
var b:Button = new mx.controls.Button();


Но в этой ситуации нужно использовать полную ссылку:
import mx.controls.Button;
import my.controls.Button;
...
var b:Button = new mx.controls.Button();


Выражения



Круглые скобки

Не используйте круглые скобки со следующими операторами +, -, *, /, &&, ||, <, <=, >, >=, ==, and !=.
Нужно так:
var e:Number = a * b / (c + d);


Но не так
var e:Number = (a * b) / (c + d);


И нужно так:
var e:Boolean = a && b || c == d;


Но не так:
var e:Boolean = ((a && b) || (c == d));


Правила ассоциативности для других операторов сложнее запомнить, поэтому для них применение круглых скобок оправданно.

Приведение типов

Не приводите булево значение в true или false – оно уже является или тем или тем.
Нужно так:
if (flag)


Но не так:
if (flag == true)


И нужно так:
var flag:Boolean = a && b;


Но не так:
var flag:Boolean = (a && b) != false;


Старайтесь приводить явно значения типов Number, String, XML, XMLList, Array, Object, or * к булеву типу, т.к. эти типы имеют множество значений и трудно запомнить, какое из них приводиться к false, а какое к true в AS3.
Нужно так:
if (s != null && s != "")


Но не так:
if (s)


Подклассам класса Object (например UIComponent) можно позволить приводиться к булеву типу самостоятельно, т.к. понятно что к false они будут приведены только если равны null. (Замечание: Object и его подклассы не могут получать значение undefined)
Нужно так:
if (child)


Но не так:
if (child != null)


И нужно так:
if (!child)


Но не так:
if (child == null)


int и uint, если их значения равны нулю, будут приведены в false а любые другие значения в true. Так, если вы хотите использовать неявное приведение типов, то все ОК.
Лучше использовать приведение, чем оператор as. Используйте оператор as когда приведение может привести к ошибке и вы хотите выражение привести к null, а не получить ошибку.
Нужно так:
IUIComponent(child).document


Но не так:
(child as IUIComponent).document


Сравнения

Следует писать в порядке, в котором они имеют смысл:
Нужно так:
if (n == 3) // "if n is 3"


Но не так:
if (3 == n) // "if 3 is n"


Операторы ++ и --

В случае, когда постфиксные и префиксные операторы эквивалентны используйте постфиксные. Используйте префиксные операторы только тогда, когда вы должны использовать значение прежде чем оно будет изменено.
Нужно так:
for (var i:int = 0; i < n; i++)


Но не так:
for (var i:int = 0; i < n; ++i)


Тернарный оператор

Используйте тернарные операторы вместо инструкций if/else, особенно для «нулевых» проверок:
Нужно так:
return item ? item.label : null;


Но не так:
if (!item)
return null;
return item.label;


Но не используйте тернарные операторы вместо комплексной логики if/else:
Нужно так:
if (a < b)
return -1;
else if (a > b)
return 1;
return 0;


Но не так:
return a < b ? -1 : (a > b ? 1 : 0);


Оператор new

Используйте круглые скобки после ссылки на класс, даже если конструктор класса не принимает никаких аргументов:
Нужно так:
var b:Button = new Button();


Но не так:
var b:Button = new Button;


Директивы



Заканчивайте каждую директиву точкой с запятой.
Нужно так:
a = 1;
b = 2;
c = 3;


Но не так:
a = 1
b = 2
c = 3


Директива include

Используйте include, но не # include. Заканчивайте каждую директиву include точкой с запятой:
Нужно так:
include "../core/ComponentVersion.as";


Но не так:
#include "../core/ComponentVersion.as"


Используйте относительные, а не абсолютные пути.

Директива import
Импортируйте определенные классы, интерфейсы и функции уровня пакета. Не используйте * при импорте:
Нужно так:
import mx.controls.Button;
import flash.utils.getTimer;


Но не так:
import mx.core.*;


Директива use namespace

Избегайте ее использования. Используйте :: для ссылки на неоткрытое пространство имен.
Нужно так
import mx.core.mx_internal;
// Позже в каком-нибудь методе...
mx_internal::doSomething();


Но не так:
import mx.core.mx_internal;
use namespace mx_internal;
// Позже в каком-нибудь методе...
doSomething();


Директива if

Если выражение конструкции if/else содержит единственную директиву, то не нужно ее заключать в фигурные скобки.
Нужно так:
if (flag)
doThing1();


Но не так:
if (flag)
{
doThing1();
}


И нужно так:
if (flag)
doThing1();
else
doThing2();


Но не так:
if (flag)
{
doThing1();
}
else
{
doThing2();
}


Но если выражение содержит больше одной директивы, то заключаем его в блоки:
Нужно так:
if (flag)
{
doThing1();
}
else
{
doThing2();
doThing3();
}


Но не так:
if (flag)
doThing1();
else
{
doThing2();
doThing3();
}


Делая многочисленные проверки на ошибки, используйте последовательно оператор if, который сразу будет возвращать false, как только найдется ошибка. Не делайте вложенных проверок, которые будут выполняться целиком для возвращения результата.
Нужно так:
if (!condition1)
return false;
...
if (!condition2)
return false;
...
if (!condition2)
return false;
...
return true;


Но не так:
if (condition1)
{
...
if (condition2)
{
...
if (condition3)
{
...
return true;
}
}
}
return false;


Директива for

Заключайте тело цикла в фигурные скобки, даже если оно содержит только одну директиву:
Нужно так:
for (var i:int = 0; i < 3; i++)
{
doSomething(i);
}


Но не так:
for (var i:int = 0; i < 3; i++)
doSomething(i);


Храните предел цикла в локальной переменной, чтобы она не переопределялась (если это не нужно) в каждой итерации.
Нужно так:
var n:int = a.length;
for (var i:int = 0; i < n; i++)
{
...
}


Но не так:
for (var i:int = 0; i < a.length; i++)
{
...
}


Объявляйте итератор цикла внутри круглых скобок директивы for, если он не используется многократно в других местах.
Нужно так:
for (var i:int = 0; i < 3; i++)


Но не так:
var i:int;
for (i = 0; i < 3; i++)
{
...
}


Директива while

Тело while необходимо заключать в фигурные скобки, даже если оно содержит единственную директиву:
Нужно так:
while (i < n)
{
doSomething(i);
}


Но не так:
while (i < n)
doSomething(i);


Директива do

Тело do необходимо заключать в фигурные скобки, даже если оно содержит единственную директиву:
Нужно так:
do
{
doSomething(i);
}
while (i < n);


Но не так:
do
doSomething(i);
while (i < n);


Директива switch

Все выражения конструкции switch должны быть заключены в фигурные скобки. Поместите break или return в блок, но не после него. Если необходим return, не помещайте break после return. Обрабатывайте выражение default так же, как и выражения case.
Нужно так:
switch (n)
{
case 0:
{
foo();
break;
}

case 1:
{
bar();
return;
}

case 2:
{
baz();
return;
}

default:
{
blech();
break;
}
}


Но не так:
switch (n)
{
case 0:
foo();
break;

case 1:
{
bar();
}
break;

case 2:
baz();
return;
break;

default:
blech();
}


Директива return

Не заключайте возвращаемое значение в скобки:
Нужно так:
return n + 1;


Но не так:
return (n + 1);


return в середине метода – это нормально.

Объявления переменных



Не делайте объявления нескольких переменных в одной строке:
Нужно так:
var a:int = 1;
var b:int = 2;


Но не так:
var a:int = 1, b:int = 2;



Ключевое слово override

Помещать его нужно перед модификатором доступа:
Нужно так:
override protected method measure():void


Но не так:
protected override method measure():void



Модификаторы доступа

Модификаторы доступа должны всегда указываться явно (там, где это допустимо). Не используйте internal, если вы его не используете явно в других случаях.
Перед тем как сделать API public или protected, хорошо подумайте, действительно оно должно быть именно таким. public и protected API должны быть задокументированы.

Ключевое слово static

Используйте его после модификатора доступа
Нужно так:
public static const MOVE:String = «move»;


Но не так:
static public const MOVE:String = «move»;


Ключевое слово final

Используйте его после модификатора доступа
Нужно так:
public final class BoxDirection


Но не так:
final public class BoxDirection


Объявляйте «перечисляемые классы» с ключевым словом final.
«Базовые» свойства и методы (которые начинаются с $) также должны быть объявлены с ключевым словом final.

Константы

Все константы должны быть объявлены с ключевым словом static. Нет повода использовать несколько констант, которые будут хранить одно и тоже значение.
Нужно так:
public static const ALL:String = "all";


Но не так:
public const ALL:String = "all";


Переменные

Если объявляемая переменная при инициализации должна иметь значение отличное от значения по умолчанию, то это значение нужно присваивать при объявлении, а не в конструкторе:
Нужно так:
private var counter:int = 1;


Но не так:
private var counter:int;
...
public function MyClass()
{
super();
...
counter = 1;
}


Локальные переменные

Используйте локальные переменные сразу в их объявлении. Не надо их сначала объявлять, а ниже использовать:
Нужно так:
private function f(i:int, j:int):int
{
var a:int = g(i - 1) + g(i + 1);
var b:int = g(a - 1) + g(a + 1);
var c:int = g(b - 1) + g(b + 1);

return (a * b * c) / (a + b + c);
}


Но не так:
private function f(i:int, j:int):int
{
var a:int;
var b:int;
var c:int;

a = g(i - 1) + g(i + 1);
b = g(a - 1) + g(a + 1);
c = g(b - 1) + g(b + 1);

return (a * b * c) / (a + b + c);
}


Объявляйте каждую локальную переменную только один раз в теле функции.
Нужно так:
var a:int;
if (flag)
{
a = 1;
...
}
else
{
a = 2;
...
}


Но не так:
if (flag)
{
var a:int = 1;
...
}
else
{
var a:int = 2;
...
}


И нужно так:
var i:int;
for (i = 0; i < n; i++)
{
...
}

for (i = 0; i < n; i++)
{
...
}


Но не так:
for (var i:int = 0; i < n; i++)
{
...
}

for (var i:int = 0; i < n; i++)
{
...
}


Классы

Если класс расширяет Object, то выражение «extends Object» можно опустить.
Конструктор не должен принимать параметров только тогда, когда единственное назначение класса – вызов инициализирующего метода, например loadResources().

Конструкторы

Если класс содержит только свойства, напишите конструктор, в котором вызовите super(), даже если он пустой.
Если конструктор принимает аргументы, которые будут затем присвоены его свойствам, то эти аргументы нужно назвать так же как и эти свойства:
Нужно так:
public function MyClass(foo:int, bar:int)
{
this.foo = foo;
this.bar = bar;
}


Но не так:
public function MyClass(fooVal:int, barVal:int)
{
foo = fooVal;
bar = barVal;
}


Не присваивайте свойствам класса значения в его конструкторе, сделайте это при их объявлении. С другой стороны, если они должны быть сброшены для каждого экземпляра класса, то это должно быть сделано в конструкторе.

Interfaces

TBD

Namespaces

TBD

Implementing properties

TBD

Metadata

TBD

Пакеты

Хотя бы один открытый член в пакете должен быть (обычно это класс, иногда пространство имен или функция)

Организация файла



В этом разделе определяется порядок, в котором должен быть организован файл фреймворка Flex.

Объявление об авторском праве



Это включение делается в самом верху *.as файла фреймворка. Формат следующий:
////////////////////////////////////////////////////////////////////////////////
//
// ADOBE SYSTEMS INCORPORATED
// Copyright 2008 Adobe Systems Incorporated
// All Rights Reserved.
//
// NOTICE: Adobe permits you to use, modify, and distribute this file
// in accordance with the terms of the license agreement accompanying it.
//
////////////////////////////////////////////////////////////////////////////////


Заметим, что его размер не более 80 символов по ширине.

Директива package



TBD

Директива import



TBD

Директива use namespace



TBD

Метаданные класса



Организуйте метаданные в секции, в следующем порядке: Events, Styles, Effects, Excluded APIs и т.д. Для каждой секции используйте заголовок. Заметим, что заголовок должен быть не более 40 символов в ширину и иметь два пробела между // и названием секции.
Расположите метаданные в алфавитном порядке по name = «…» в каждой секции. В секции Other metadata они могут быть расположены по тэгу:
//--------------------------------------
// Events
//--------------------------------------
/
**
* ASDoc comment.
*/
[Event

/**
* ASDoc comment.
*/
[Event

//--------------------------------------
// Styles
//--------------------------------------

/**
* ASDoc comment.
*/
[Style

/**
* ASDoc comment.
*/
[Style]

//--------------------------------------
// Effects
//--------------------------------------

/**
* ASDoc comment.
*/
[Effect

/**
* ASDoc comment.
*/
[Effect]

//--------------------------------------
// Excluded APIs
//--------------------------------------

[Exclude(name=”horizontalAlign”, kind=”style”)]
[Exclude(name=”verticalAlign”, kind=”style”)]

//--------------------------------------
// Other metadata
//--------------------------------------

[DefaultBindingProperty(source=”text”, destination=”text”)]
[IconFile(“Text.png”)]


Объявление класса



TBD

Директива include для Version.as



Каждый класс должен включать core/Version.as используя для этого относительный путь. Этот файл содержит объявление для static const VERSION:String.
include "../core/Version.as";

Реализация интерфейса



TBD

Инициализация класса



TBD

Константы класса



Используйте static const для их объявления.
AS3 не позволяет иметь константе в качестве значения экземпляры классов Array и Object. Объявляйте такие константы с помощью static var, а не static const, но помещайте их в этой же секции констант, т.к. концептуально они являются константами

Ресурсы класса



TBD

Переменные класса



TBD

Статические переменные



Объявляйте статические геттеры/сеттеры здесь. Расположите их в алфавитном порядке. Используйте небольшой разделитель для каждого имени переменной. Геттер следует поместить перед сеттером

Статические методы



Здесь помещаются статические функции класса.

Конструктор



TBD

Переменные



TBD

Переопределенные свойства



Помещайте переопределенные не статические геттеры/сеттеры здесь. Располагайте их в алфавитном порядке. Используйте небольшой разделитель для каждого имени свойства. Располагайте геттер перед сеттером.

Свойства



Помещайте новые не статические геттеры/сеттеры здесь. Располагайте их в алфавитном порядке. Используйте небольшой разделитель для каждого имени свойства. Располагайте геттер перед сеттером.

Переопределенные методы.



Здесь помещаются не статические переопределенные методы.

Методы



Здесь помещаются не статические методы.

Переопределенные обработчики событий



Здесь помещаются переопределенные обработчики событий.

Обработчики событий



Новые обработчики событий помещаются здесь.

Out-of-package helper classes



TBD

Форматирование



Этот раздел о том, как должен быть отформатирован класс фреймворка Flex.

Ширина строки



Разбивайте код на строчки длиной не более 80 символов. Это нужно делать по следующим причинам:
- разработчики с небольшими мониторами не должны пользоваться горизонтальной прокруткой кода;
- сравнивающие утилиты должны иметь возможность отображать два класса бок о бок целиком.
- размер шрифта может быть увеличен отдельными участниками группы, для этого не нужно будет пользоваться горизонтальной прокруткой.
- Исходный код может быть распечатан без обрезки и переноса.

Отступ



Используйте 4-пробельный отступ. Настройте свой текстовый редактор для вставки пробелов, а не табуляции. Это позволит другим программам, например Notepad отображать код корректно, не уродуя его.

Разделители секций



Большие секции внутри класса должны быть разделены следующим образом:
//--------------------------------------------------------------------------
//
// Overridden methods
//
//--------------------------------------------------------------------------


Он располагается от колонки 4 до колонки 80 . Текст выровнен по колонке 8.
Небольшие секции, например между свойствами разделены следующим образом:
//----------------------------------
// visible
//----------------------------------


Он располагается от колонки 4 до колонки 40 . Текст выровнен по колонке 8.
Перед и после разделителя оставьте пустую строку.

Разделители в объявлениях переменных



Используйте пустую строку для разделения объявлений переменных, констант и методов:
/**
* @private
* Holds something.
*/
var a:Number;

/**
* @private
*/
var b:Number



Метаданные



TBD
Нужно так:
Inspectable[a="1", b="2"]


Но не так:
Inspectable[a=1 b=2]


Индексирование массива



Не ставьте пробелы между индексом и квадратной скобкой
Нужно так:
a[0]


Но не так:
a[ 0 ]



Запятые



После запятой ставьте один пробел.

Литералы массива



Ставьте один пробел после левой квадратной скобки и один пробел перед правой квадратной скобкой, и один пробел после каждой запятой:
Нужно так:
[ 1, 2, 3 ]


Но не так:
[1, 2, 3]
[1,2,3]


Пустые массивы отдельный случай:
Нужно так:
[]


Но не так:
[ ]


Форматируйте длинные инициализаторы массива следующим образом:
static var numberNames:Array /* of String */ =
[
"zero",
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine"
];


Литералы объектов



Здесь все по аналогии с литералами массивов:
Нужно так:
{ a: 1, b: 2, c: 3 }


Но не так:
{a: 1, b: 2, c: 3}
{a:1, b:2, c:3}
{a:1,b:2,c:3}


Пустые объекты отдельный случай:
Нужно так:
{}


Но не так:
{ }


Длинные инициализаторы форматируются так:
private static var TextStyleMap:Object =
{
color: true,
fontFamily: true,
fontSize: true,
fontStyle: true,
fontWeight: true,
leading: true,
marginLeft: true,
marginRight: true,
textAlign: true,
textDecoration: true,
textIndent: true
};



Литералы функций



TBD

var f:Function;
f = function():void
{
doSomething();
};



Объявление типов



Не ставьте пробелы для разделения переменной, двоеточия и типа данных:
Нужно так:
var n:Number;


Но не так:
var n : Number;
var n: Number;


И нужно так:
function f(n:Number):void


Но не так:
function f(n : Number) : void
function f(n: Number): void



Операторы и присваивание



Ставьте по одному пробелу до и после оператора присваивания:
Нужно так:
a = 1;


Но не так:
a=1;


так:
a + b * c


Но не так:
a+b*c


так:
a == b


Но не так:
a==b


так:
!o


Но не так:
! o


Так:
i++


Но не так:
i ++


Директивы



Начинайте каждую директиву с новой строки, чтобы можно было установить контрольную точку для каждой директивы:
Нужно так:
a = 1;
b = 2;
c = 3;


Но не так:
a = 1; b = 2; c = 3;


Выравнивайте блоки директив так:
function f():void
{
var n:int = numChildren;
for (var i:int = 0; i < n; i++)
{
if ()
{
x = horizontalGap * i;
y = verticalGap * i;
}
}
}


Но не так:
function f():void {
var n:int = numChildren;
for (var i:int = 0; i < n; i++) {
if () {
x = horizontalGap * i;
y = verticalGap * i;
}
}
}



Объявление констант и переменных



TBD

Объявление функций



TBD

Нужно так:
f(a, b)


Но не так:
f(a,b)
f( a, b )


Если параметры разделяются на несколько строк, то перенесенные параметры выравниваются по левой круглой скобке. Несколько параметров могут располагаться в одной строке, если они для этого подходят. Иначе каждый параметр располагается в отдельной строке. Если даже один параметр не входит в строку, в которой объявляется метод, то он переноситься на следующую строку и выравнивается по имени метода:
public function foo(parameter1:Number, parameter2:String,
parameter3:Boolean):void

public function foo(parameter1:Number,
parameter2:String,
parameter3:Boolean):void

public function aVeryLongFunctionName(
parameter1:Number, parameter2:String,
parameter3:Boolean):void


Вызов функции



TBD

Нужно так:
f(a, b)


Но не так:
f(a,b)
f( a, b )



Директива if



Нужно так:
if (a < b)


Но не так:
if(a < b)
if( a < b )
if ( a < b )



Директива for



Нужно так:
for (var i:int = 0; i < n; i++)


Но не так:
for(var i:int = 0; i < n; i++)
for( var i:int = 0; i < n; i++ )
for ( var i:int = 0; i < n; i++ )


Если условный блок нужно перенести, то его части выравниваются по левой круглой скобке:
for (var aLongLoopVariableName:int = aLongInitialExpression;
aLongLoopVariableName < aLongUpperLimit;
aLongLoopVariableName++)



Директива switch



Нужно так:
switch (n)


Но не так:
switch(n)
switch( n )
switch ( n )


Нужно так:
switch (n)
{
case 1:
{
a = foo();
break;
}

case 2:
{ a = bar();
break;
}

default:
{
a = blech();
break;
}
}


Но не так:
switch(n)
switch( n )
switch ( n )



ASDoc



Комментирование свойств



Документировать нужно только первый метод из пары геттер/сеттер:
/**
* @private
* возвращаемая переменная геттера
*/
private var _someProp:Foo;

/**
* Здесь располагаются все комментарии – сначала для геттер, затем для сеттера
*/
public function get someProp():Foo
{
...
}

/**
* @private
*/
public function set someProp(value:Foo):void
{
...
}


Кроме того, комментарии ASDoc применяются и к тэгам метаданных так же, как и к любым другим конструкциям в пределах класса, поэтому стоит позаботиться, чтобы комментарии относились к надлежащему адресату. Если вы комментируете someProp то:
Нужно так:
[Bindable("somePropChanged")]

/**
* Комментарии для someProp
*/
public function get someProp():Foo


Но не так:
/**
* Комментарии для someProp
*/
[Bindable("somePropChanged")]

public function get someProp():Foo

2 комментария:

  1. Браво, браво! То, что доктор прописал.

    ОтветитьУдалить
  2. Потрясающий перевод! Огромное спасибо за проделанную работу!

    ОтветитьУдалить