Flex编码规范
遵循一定编码规范能够使源码看起来前后一致、组织良好、更加专业。本部分内容包括:1. 命名;2. 语言使用 3. 文件组织 4. 格式 5. ASDoc1. 命名缩写:能避免就避免,代码清晰永远比减少打字重要;但是也要记住一些标准化了的通用的缩写,比如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, creationCompleteStyle名称:小写字母开始,大写字母间隔: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();elsedoThing2():―――――――――――――――――――――――――――――――――――――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):voidNo:function f(n : Number) : voidfunction f(n: Number): void操作符和赋值:在赋值操作符、中缀操作符的前后各加一个空格,不要在前缀或者后缀操作符前后加任何空格;语句行:每个语句一行,块内保持对齐;函数声明:如果参数需要换行,那么第二行参数和第一行左括号右侧对齐,如果一行放置适当的数目的参数,如果实在无法安排,那么一行放置一个参数。如果第一行一个都没法放,那么将第一个参数放置到第二行,并相对函数声明进行缩进:public function foo(parameter1:Number, parameter2:String, parameter3:Boolean):voidpublic function foo(parameter1:Number, parameter2:String, parameter3:Boolean):voidpublic 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. ASDocget和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():FooNo:/** * Comments for someProp */[Bindable("somePropChanged")]public function get someProp():Foo本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/arshoon/archive/2008/05/21/2467161.aspx
?