Flex 编码规范

42 篇文章 0 订阅
遵循一定编码规范能够使源码看起来前后一致、组织良好、更加专业。

本部分内容包括:1. 命名;2. 语言使用 3. 文件组织 4. 格式 5. ASDoc

 
1. 命名
缩写:能避免就避免,代码清晰永远比减少打字重要;但是也要记住一些标准化了的通用的缩写,比如acc(accessiblility) , auto(automatic), impl(implementation), info(infomation), num(number), min(minimum), max(maximum), nav(navigation), regexp(regular expression), util(utility)等等。使用缩写时尽量和Flex保持一致;

 
首字母缩写词:要么全部大写要么全部小写。当首字母缩写词当成一个标志符或者标志符的开始部分,且这个标志符必须以小写字母开始的时候才采用全部小写的方式。

 
词语边界:标志符多个单词构成的时候,单词首字母大写,或者词语以下划线隔开,比如LayoutManager, object_proxy;当多个首字母缩写词邻接的时候遵循首字母缩写词规范,但是尽量避免。

 
指定类型的名字:如果你要将某一个类型组合到一个名字中去,那么把在加在最后,比如命名命名一个border图形可以使用:border, borderSkin, borderShape;最好的名字就是类型的小写比如:Button的实例button。

 
包命名:使用小写字母,之间大写字母隔开,比如controls, listClasses;包名称最好是名词或者动名词,不要用动词、介词、形容词、副词之类。当一个包的作用是实现某一功能的时候最好使用动名词,比如bingding, logging, messaging, printing;支持组件FooBar的最好写作fooBarClasses;

 
文件名称:对于重要的API文件,文件名称必须和重要的公开API保持一致,但是include文件不一定要遵循此规则;对于包含文件比如用作Styles的,大写字母开始,各个单词隔开,且在最后加上Styles: BorderStyles.as, ModalTrasparencyStyles.as; 对于资源文件小写字母开始,下划线隔开:icon_align_left.png;

 
命名空间名称:小写字母、下划线隔开:mx_internal, object_proxy

 
接口名称:字母“I”开始、大写字母间隔:IList, IFocusManager, IUID

 
类名称:大写字母开始、大写字母间隔:Button, FocusManager;Event子类(FoobarEvent),Error子类(FooBarError),皮肤类(FooBarBackground, FooBarBorder, FooBarIcon...),utility类(FooBarUtil,不是FooBarUtils,包是复数,类是单数);

 
事件名称:小写字母开始、大写字母间隔:move, creationComplete

 
Style名称:小写字母开始,大写字母间隔:color, fontSize;

 
字符属性枚举值:auto, filesOnly;

 
常量命名:全部大写字母,下划线间隔:OFF, DEFAULT_WIDTH,如果常量是一个字符串,那么常量命名和常量值保持一致: <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作为loop循环的变量:

for (var p:String in o)

{

    ...

}

如果子类的getter/setter覆盖了基类的getter/setter,但是同时又想继续公开基类的getter/setter,那么这个时候应将基类的属性名前加上“$”作为子类属性名,并且子类的属性名应该标志为final,且除了调用基类getter/setter外不应该做其它的事情:

mx_internal final function get $numChildren():int

{

    return super.numChildren;

}

 
存储变量命名:getter/setter属性foo所存储的变量应该是_foo(加上下划线);

 
方法命名:小写字母开始,每个单词大写字母间隔,应该使用动词:measure(), updateDisplayList();无参方法应该实现为getter/setter,而不应该是getFooBar(), setFooBar();当然,如果getFooBar()是一个需要大量计算的慢速度方法的话就应该命名为findFooBar(), calculateFooBar(), determineFooBar()等等,而不是getter;如果子类的某方法覆盖了基类的某方法,但是同时又想继续公开基类的某方法,那么这个时候应将基类的方法名前加上“$”作为子类方法名,并且子类的方法名应该标志为final,且除了调用基类方法外不应该做其它的事情:

mx_internal final function $addChild(child:DisplayObject):DisplayObject

{

    return super.addChild(child);

}

 
事件处理器命名:在后面加上Handler:mouseDownHandler();如果事件处理器是用来处理组件的某一个子组件的事件的话,那么就应该把子组件的名称加到最前面,并且用下划线隔开:textinput_focusInHandler() (textinput的focusin事件的handler);

 
参数命名:setter值使用value:public function set label(value:String):void; 事件参数使用event:protected function mouseDownHandler(event:Event):void;

 
资源包名称:为某一包服务的资源包名称应该和包的名称保持一致;

 
资源键名称:小写字母,每个单词大写字母隔开;

 
杂七杂八:避免使用“object”,因为它不明确;“item”是数据项,不是显示对象;renderer是显示数据项的显示对象;“type”是AS3类型,否则使用“kind”;

 
2. 语言使用
这个部分讨论AS3的语言构造,尤其当某一事情有多种表示方法的时候;

 
编译选项:编译的时候要使用-strict –show-actionscript-warnings(flex-config.xml默认);

 
基于属性的API:应该偏向基于属性的API而不是基于方法的API,因为这对于声明示的MXML来说更加有利;

 
类型声明:尽量为每个变量、参数、返回值等编写注释;参数类型尽量准确,比如循环变量应该是int,而不是Number,更不是Object;鼠标事件处理器的参数应该是MouseEvent而不是Event;如果值可以是undefined的话那么使用“*”,这种情况下可以使用Object代替,null表示undefined;如果声明变量为Array,则应该使用“/*   */”马上注明数组的成员类型:var a:Array /* of String */ = [];

function f(a:Array /* of Number */):Array /* of Object */

{

    ...

}

 
保留字:
undefined尽量避免使用;

int和uint:整数后面不要加小数点,十六进制用0x开始,后面的字母大写;

RGB色通常用六个十六进制数字表示;

索引值-1表示“没有索引项”;

Number:通常表示可以带小数,所以即使变量是整数也应该加上一个小数点和一个零,比如alphaFrom = 0.0; alphaTo = 1.0;但是屏幕坐标值不要这样做;

指数计数的时候使用e,比如1.0e12,不要用大写E;

String:使用双引号界定字符,即使字符中间包含引号:字符what’up, “Big Boy”?表示为"What's up, /"Big Boy/"?", 而不是’what/’s up “Big Boy”?’;

Array:使用“[]”, 而不是new Array(),比如[1, 2, 3]而不是new Array(1, 2, 3);这里在一个数组变量的时候容易出问题,比如一个包含一个值3的数组,如果用new Array(3),那么表示的是建立了一个三个元素的数组[undefined, undefined, undefined], 而不是[3];

Object:使用{}, 而不是new Object();比如{}, {a: 1, b: 2, c: 3};

Function:避免使用匿名函数,用类方法或者包方法代替;如果一定要用,那么声明返回值,并且函数体内最后一个语句用分号结尾:function(i:int):void { doIt(i - 1); doIt(i + 1); }

RegExp:不要使用正则表达式构造函数创建正则表达式,使用var pattern:RegExp = //d+/g; 而不是var pattern:RegExp = new RegExp("//d+", "g");

XML和XMLList:直接使用保留字声明,不要使用构造函数。使用var node:XML = <name first="Jane" last="Doe"/>;而不是var node:XML = new XML("<name first=/"Jane/" last=/"Doe/"/>"); XML属性值要使用双引号括起来,不要使用单引号。

Class:只有当需要在区分两个导入类的时候才使用类的全名,

正确做法(Yes:):

import mx.controls.Button;

...

var b:Button = new Button();

错误做法(No:):

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();

 
表达式相关:对于通用的操作符(+, -, *, /, &&, ||, <, <=, >, >=, ==, !=)不要使用不必要的圆括号;其它的优先级不容易记住的可以借助圆括号。

 
强制类型转换:不要将Boolean变量和true或false比较;显式的将int,uint, Number, String转换为Boolean值,使用if(n !=0 ) 而不是if (n), 使用if (s != null && s != “”)而不是if (s),对于对象引用来说可以隐式转换为Boolean值,使用 if (child) 而不是if (child != null),使用if (!child) 而不是if (child != null);使用强制类型转换而不是as操作符,仅仅当强制转换可能失败并且你希望失败的时候值为null而不是抛出异常。使用IUIComponent(child).document而不是(child as UIComponnet).document;

 
比较:以更容易理解的方式书写比较表达式: if (n == 3) // "if n is 3"(Yes), if (3 == n) // "if 3 is n"(No);

 
++ 和 –操作:前缀形式和后缀形式效果一样的时候使用后缀形式,只有当你想在变量在操作之前使用的时候才使用前缀形式;

 
三元操作符:可以使用三元操作符代替简单的if/else 逻辑,尤其是对null进行判断的时候;

return item ? item.label : null (Yes)

if (! Item) 

return null;

return item.label; (No)

但是不要使用嵌套的三元操作符;

 
new:即使构造的类不带参数也要使用圆括号:var b:Button = new Button(); (yes) var b:Button = new Button;(No);

 
声明:每一个声明语句都使用分号结尾。

 
include:使用include 而不是已废弃的#include,和前面一样,每个声明语句以分号结束;使用相对路径而不是绝对路径;

 
import:导入明确的类,避免使用通配符“*”;

 
use namespace :避免使用,非公开名字空间引用使用“::”:

Yes:

import mx.core.mx_internal;

 
// Later, in some method...

mx_internal::doSomething();  

No:

import mx.core.mx_internal;

use namespace mx_internal;

 
// Later, in some method...

doSomething();

 
if:当if/else 分支只有一句声明的时候,不要用{}括起来;

Yes:

if (flag)

doThing1();

――――――――――――――――――――――――――――――――――――

if (flag)

    doThing1();

else

doThing2():

―――――――――――――――――――――――――――――――――――――

No:

if (flag)

{

    doThing1();

}

―――――――――――――――――――――――――――――――――――――

if (flag)

{

    doThing1();

}

else

{

    doThing2();

}

但是如果有一个分支有多行语句,那么都用{}括起来:

Yes:

if (flag)

{

    doThing1();

}

else

{

    doThing2();

    doThing3();

}

―――――――――――――――――――――――――――――――――――――――

No:

if (flag)

    doThing1();

else

{

    doThing2();

    doThing3();

}

 
对于多个错误检查,使用串行的表达方式,检测错误立即返回,正确值最后返回。不要用嵌套的形式,这样会使整个逻辑看起来很凌乱。

Yes:

if (!condition1)

    return false;

...

if (!condition2)

    return false;

...

if (!condition2)

    return false;

...

return true;

 
No:

if (condition1)

{

    ...

    if (condition2)

    {

        ...

        if (condition3)

        {

            ...

            return true;

        }

    }

}

return false;

 
for:循环体使用{}括起来,即使只有一行的情况下也是如此。循环上界需要计算的情况下将它存入本地变量,防止多次重复计算。

Yes:

var n:int = a.length;

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

{

    ...

}

No:

for (var i:int = 0; i < a.length; i++)

{

    ...

}

循环变量的声明放入圆括号内,除非这个变量需要多次重复使用。

Yes:

for (var i:int = 0; i < 3; i++)

No:

var i:int;

for (i = 0; i < 3; i++)

{

   ...

}

 
while:循环体使用{}括起来,即使只有一行的情况下也是如此。

 
do:循环体使用{}括起来,即使只有一行的情况下也是如此。

 
Switch:每一个case语句都用{}括起来,在{}块里面最后加上return 或者 break语句。如果你想返回值,那么使用return。return后面不必加break。default部分和case部分一样:

Yes:

switch (n)

{

    case 0:

    {

        foo();

        break;

    }

 
    case 1:

    {

        bar();

        return;

    }

 
    case 2:

    {

        baz();

        return;

    }

 
    default:

    {

        blech();

        break;

    }

}

No:

switch (n)

{

    case 0:

        foo();

        break;

 
    case 1:

    {

        bar();

    }

    break;

 
    case 2:

        baz();

        return;

        break;

 
    default:

        blech();

}

 
return:返回值不加不必要的圆括号。在函数的中间返回也是可以的。

 
声明:一行不声明多个变量。

Yes:

var a:int = 1;

var b:int = 2;

No:

var a:int = 1, b:int = 2;

 
override:放在第一个。override protected method measure():void(Yes) protected override method measure():void(No);

 
存取标志:在用户没有显式声明的情况下存储标志是internal,避免使用默认声明,在必要的地方显式声明。在需要对API进行public或protected声明之前需仔细考虑,因为经过这种类型声明的函数需要建立文档,并且在正式废弃此API之前项目都必须支持此类API。

 
static:置于存取标志之后。比如public static const MOVE:String =  "move";

 
final:置于存取标志之后。将所有enum类声明为final基本属性和方法(那些$开始的)声明为final。

 
常量:所有常量都必须声明为static,常量的值是一样的,所以声明为实例化常量没有意义。

 
变量:如果变量需要初始化一个非默认值,那么在声明的时候就赋值,不要放在类的构造函数里面去。

 
本地变量:在使用的时候声明,而不是放在函数开始的部分。

Yes:
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);

}

No:
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);

}

 
本地变量的作用域是整个函数而不是一个块,一个变量在一个函数范围内只需要声明一次。

Yes:
var i:int;

for (i = 0; i < n; i++)

{

    ...

}

 
for (i = 0; i < n; i++)

{

    ...

}

No:
for (var i:int = 0; i < n; i++)

{

    ...

}

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

{

    ...

}

 
类:如果类是Object的子类,那么不必要写extends Object;

 
构造函数:如果类有实例,那么就要编写构造函数,并且在构造函数里显式调用super()。如果构造函数需要对实例属性初始化,那么构造函数的参数名应该和需要初始化的属性名保持一致。

Yes:

public function MyClass(foo:int, bar:int)

{

    this.foo = foo;

    this.bar = bar;

}

No:

public function MyClass(fooVal:int, barVal:int)

{

    foo = fooVal;

    bar = barVal;

}

不要在构造函数里对类实例变量属性进行初始化,应该在声明的部分这样做。如果需要改变父类的属性值,那么这部分工作应该放到构造函数里面。

 
接口、命名空间、元数据、属性实现:待定;

 
3. 文件组织
在每个as文件的开始部分包含版权信息。2008的开源版权信息如下:
///
//
//  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、import 、use namespace声明:待定;
 
类元数据:按照“块”的形式组织元数据,顺序为:Events, Styles, Effects, Excluded API以及其它元数据。在每个“块”的前面加上一个小的“块”头部,注意,这个头部是40字符宽,且在块名称和//之间有两个空格。在每个块内对元数据按照字母顺序排序,其它的元数据按照元数据标志进行字母排序。
//--------------------------------------
//  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")]
 
类声明:待定;
 
Version.as的包含声明:每个类都应该以相对路径的形式包含core/Version.as,这个文件包含static const VERSION:STRING的声明:
include “../core/Version.as”;
 
实现,类初始化:待定;
 
类常量:AS3不允许Array和Object类型的常量,但是可以用static var的形式声明(不要用static const),之所以放到这个部分说明是因为在概念上讲它们仍然是常量。
 
类资源、类变量:待定;

 
类属性:在这里声明static类型的getter和setter,按照属性字母排序,每个属性前用属性名分隔,将getter放置在setter之前;

 
构造函数、变量:待定;

 
重写属性(override properties):在这里声明非静态getter和setter,字母排序,属性名隔开,getter在setter之前;

 
属性:把非静态setter和setter放在这里,字母排序,属性名分隔,getter在setter之前。

 
重写方法:将重写的非静态方法放在这里。

 
方法:非静态函数。

 
重写事件处理器:将重写的事件处理器放到这里。

 
事件处理器:新的事件处理器。

 
包外辅助类:待定;

 
4. 格式:
这个部分讨论Flex框架类的应该以何种格式书写。

行宽:80字符。优点:小屏幕开发者不必水平滚动;比较工具可以并排放置两个文件窗口;字体投影无需滚动;源码无需经过剪裁或者断行就可以打印;

 
缩进:4空格;配置你的编辑器插入空格而不是Tab,这样允许其它的程序使用不同的缩进策略而不至于影响显式外观,比如NotPad就是8空格缩进;

块分隔符:

大“块”分隔符:

    //--------------------------------------------------------------------------

    //

    //  Overridden methods

    //

    //--------------------------------------------------------------------------

从4列到80列,文本从8列开始;

小“块”分隔符:类里面使用,比如属性之间。形如:

    //----------------------------------

    //  visible

    //----------------------------------

从4列到70列,字符8列开始;

分隔部分前后放置一个空行;

 
声明分隔:常量、变量、函数声明由一个空行隔开;

/**

 *  @private

 *  Holds something.

 */

var a:Number;

 
/**

 *  @private

 */

var b:Number

 
元数据:Inspectable[a="1", b="2"](Yes), Inspectable[a=1 b=2](No)。

 
数组索引:中括号前后都不要加空格,a[0] (yes), a[ 0 ] (no);

 
逗号:逗号后面加入一个空格,使用参数、数组、对象等;

 
数组赋值:左括号后面和右括号前面加入一个空格,[ 1, 2, 3 ] (yes), [1, 2, 3], [1,2,3](no);

多行复杂数组初始化的时候括号对齐;

static var numberNames:Array /* of String */ =

[

"zero",

    "one",

    "two",

    "three",

    "four",

    "five",

    "six",

    "seven",

    "eight",

    "nine"

];

 
对象赋值:在左花括号后面和右花括号前面加上一个空格, 属性和值之间用的逗号后面加上一个空格;{ a: 1, b: 2, c: 3 }(yes) {a: 1, b: 2, c: 3}, {a:1, b:2, c:3}(no);空对象是个例:{} ;需要多行表示的对象保持属性和括号的对齐:

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

};

 
类型声明:不要在变量、参数,或者函数类型的冒号前后加任何空格:

Yes: 

var n:Number;

No:

var n : Number;

 
var n: Number;

Yes: 

function f(n:Number):void

No:

function f(n : Number) : void

 
function f(n: Number): void

 
操作符和赋值:在赋值操作符、中缀操作符的前后各加一个空格,不要在前缀或者后缀操作符前后加任何空格;

 
语句行:每个语句一行,块内保持对齐;

 
函数声明:如果参数需要换行,那么第二行参数和第一行左括号右侧对齐,如果一行放置适当的数目的参数,如果实在无法安排,那么一行放置一个参数。如果第一行一个都没法放,那么将第一个参数放置到第二行,并相对函数声明进行缩进:

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

 
函数调用:f(a, b) (yes)  f(a,b), f( a, b ) (no);

 
if表达式:在if后加入一个空格,但是不要在左括号的右侧和右括号的左侧加入任何空格。

yes:

if (a < b)

 
no:

if(a < b)

 
if( a < b )

 
if ( a < b )

 
for表达式:在for后面加入一个空格,但是不要在左括号的右侧和右括号的左侧加入任何空格。

Yes:

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

No:

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表达式需要换行,那么和左括号右侧保持对齐:

for (var aLongLoopVariableName:int = aLongInitialExpression;

    aLongLoopVariableName < aLongUpperLimit;

aLongLoopVariableName++)

 
switch语句:在switch后面加入一个空格,但是不要在左括号的右侧和右括号的左侧加入任何空格。

Yes: switch (n) 

No:

switch(n)

 
switch( n )

 
switch ( n )

 
5. ASDoc
get和set成对出现,只对第一个 get/set函数归档,一般的归档格式如下:

/**

 *  @private

 *  The backing variable for the property.

 */

private var _someProp:Foo;

 
/**

 *  Place all comments for the property with the getter which is defined first. 

 *  Comments should cover both get and set behavior as appropriate.

 */

public function get someProp():Foo

{

  ...

}

 

/**

 *  @private

 */

public function set someProp(value:Foo):void

{

  ...

}

ASDoc注释适用于类内的结构同时也适用于元数据标签,所以注意你的注释应该适合特定的目标。如果你标志一个属性为绑定,那么你的属性注解应该在get函数之前,而不是绑定标签的前面。

Yes:

[Bindable("somePropChanged")]

 
/**

 *  Comments for someProp

 */

public function get someProp():Foo

 
No:

/**

 * Comments for someProp

 */

[Bindable("somePropChanged")]

 
public function get someProp():Foo


http://blog.csdn.net/arshoon/article/details/2467161

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值