Asial Blog

Recruit! Asialで一緒に働きませんか?

【Flex】Flexのコーディング規約のお話

カテゴリ :
フロントエンド(HTML5)
タグ :
Tech
Flex
コーディング規約
AS3
Flash
こんにちは、橋本です。

今日はFlexのコーディング規約についてお話しようと思います。

「え、Flexにコーディング規約なんてあったの!?」

とお思いの方も多いかと思いますが、実は公式のコーディング規約が存在します。

Flex SDK coding conventions and best practices

日本語訳はこちら


今日はこの中で個人的に気になったところを拾って見ていきたいと思います。


略語
  1. 原則は、略語を使用しないということになっていますが、一部標準化されている略語があります。
  2. acc: accessibility(アクセシビリティ)。使用例: ButtonAccImpl
  3. auto: automatic(自動)。使用例: autoLayout
  4. eval: evaluate(評価)。使用例: EvalBindingResponder
  5. impl: implementation(実装)。使用例: ButtonAccImpl
  6. info: information(情報)。使用例: GridRowInfo
  7. num: number(数値)。使用例: numChildren
  8. min: minimum(最小)。使用例: minWidth
  9. max: maximum(最大)。使用例: maxHeight
  10. nav: navigation(ナビゲーション)。使用例: NavBar
  11. regexp: regular expression(正規表現)。使用例: RegExpValidator
  12. util: utility(ユーティリティ)。使用例: StringUtil

個人的には、obj(object)、arr(array)、str(string)なんかも標準に入れても良い気がするのですが。

プロパティ名(変数およびgetter/setter)
  1. 小文字で綴りを開始し、以後の連語をキャメルケース方式で記述します。例: i、width、numChildren。
  2. ループのインデックスにはi、上限値にはnをそれぞれ使用します。 内部ループのインデックスにはj、上限値にはmをそれぞれ使用します。
  3. for (var i:int = 0; i < n; i++)
  4. {
  5.     for (var j:int = 0; j < m; j++)
  6.     {
  7.         ...
  8.     }
  9. }
  10. for-inループの変数には、p(プロパティの頭文字)を使用します。
  11. for (var p:String in o)
  12. {
  13.     ...
  14. }

for文に関しては、特に異論はないのですが、for-in文の規約には個人的に納得出来ないというか、微妙な気がします。

pってわかりにくいですよね?

for-in文の中でさらにfor-in文を使うときにはどうするんでしょうか?pをプロパティの頭文字と言うのであれば、qだとおかしいですよね?だとすると、p2?

微妙ですね。。。


ストレージ変数名
  1. getter/setterのfooのストレージ変数には、_fooという名前を付けます。

これも、好き嫌いがあると思います。個人的には、内部プロパティについては、全て_hogehogeといった感じで、アンダーバーからスタートする変数名に統一するのが、意外と分かりやすくていいんじゃないかな、と。

イベントハンドラ名
  1. イベントハンドラには、イベントの種類を示す語句に「Handler」を結合した名前を付けます。例: mouseDownHandler()。
  2. 仮にハンドラが、サブコンポーネント(this}}以外のものなど)によってディスパッチされるイベント用のものである場合は、ハンドラ名の前にサブコンポーネント名を付け、これらをアンダースコアで結合します。例: textInput_focusInHandler()。

イベントハンドラについては、onを接頭詞として付ける派(onMouseDown、など)の方もいらっしゃるかと思いますが、FlashBuilder4から追加された、イベントハンドラを自動で作成してくれる機能では、上記の規約に従ってメソッドが作成されるので、こちらに移行した方がいろいろと楽かもしれません。

引数名
  1. 各setterの引数には、valueを使用します。
  2. public function set label(value:String):void
  3. 各イベントハンドラの引数には、(e、evt、eventObjではなく)eventを使用します。
  4. protected function mouseDownHandler(event:Event):void

個人的には、setterの引数には、setする引数名を使いたくなるんですが。。

  1. private var _hoge:String;
  2.       
  3. public function set hoge(hoge:String):void
  4. {
  5.    _hoge = hoge;
  6. }

どっちがわかりやすいんでしょうか。

型宣言
  1. すべての定数、変数、関数引数、関数の戻り値に対して、型宣言を記述します。
  2. Arrayデータ型を宣言する場合は、/* of ElementType */の体裁のコメントをArray直後に記述し、配列要素の型を示すようにします。 将来バージョンの言語では、型付けされた配列が含まれる見込みです。

これは、めんどくさいんですが、慣れるとコードが読みやすくていいかもしれません。
こんな感じです。

  1. var arr:Array /* of String */ = [];

また、この規約はFlash10以降使えるようになった、Vectorクラスの記述に似せたものなのかもしれません。
Vectorクラスは配列みたいなものなのですが、中に格納するデータの型を指定する必要があります。

  1. private var vector:Vector.<String>;

リテラル
  1. String:
  2. 文字列の区切りとしては、たとえその文字列にクオーテーションマークが文字として含まれている場合でも、アポストロフィ(1重引用符)ではなくクオーテーションマーク(2重引用符)を使用します。
  3. "What's up, \"Big Boy\"?";
  4. Array:
  5. new Array()ではなく、配列リテラルを使用する。
  6. var arr:Array = [];
  7. Object:
  8. new Object()ではなく、Objectリテラルを使用する。
  9. var obj:Object= {};

ArrayとObjectは基本かと思いますが、Stringが気持ち悪いですね。わざわざエスケープするくらいなら、シングルクォート使う方がわかりやすいと思うんですけどね。。

ifステートメント
  1. if/elseステートメントの分岐後条件に単一のステートメントのみが含まれる場合は、これらをブロックにすることを避けます。
  2. 1.
  3. if (flag)
  4.     doThing1();
  5. 2.  
  6. if (flag)
  7.     doThing1();
  8. else
  9.     doThing2():

1番はまぁいいのですが、2番はブロックにしたいですよね。なんとなく気持ち悪い。。。

forステートメント
  1. たとえステートメントが1つしかない場合でも、{{for}}ループの命令部分はブロックで記述します。
  2. for (var i:int = 0; i < 3; i++)
  3. {
  4.    doSomething(i);
  5. }

なんで、ifと逆なんだ…。

switchステートメント
  1. 各case句の内容、およびdefault句の内容はブロックで記述します。breakステートメントおよびreturnステートメントは、ブロックの後ではなくブロック内に記述します。 returnがある場合は、returnをbreakの後に配置しないようにします。 default句はcase句同様に扱うようにし、breakやreturnを記述してswitchの最後まで処理が達するのを防ぐようにします。
  2. switch (n)
  3. {
  4.     case 0:
  5.     {
  6.         foo();
  7.         break;
  8.     }
  9.     case 1:
  10.     {
  11.         bar();
  12.         return;
  13.     }
  14.     case 2:
  15.     {
  16.         baz();
  17.         return;
  18.     }
  19.     default:
  20.     {
  21.         blech();
  22.         break;
  23.     }
  24. }

これは慣れると、非常に見やすいです。

PHPを書いてるときにも、switch文の書き方に違和感を感じていたので、この書き方は目から鱗でした。
ちなみに、PHPでもこの書き方、できます。

ローカル変数
  1. ローカル変数は、その変数が初めて使用される時点、または使用される直前に宣言するようにします。 すべての宣言を関数の最初の部分に記述することは避けます。
  2. 正しい記述例
  3. private function f(i:int, j:int):int
  4. {
  5.     var a:int = g(i - 1) + g(i + 1);
  6.     var b:int = g(a - 1) + g(a + 1);
  7.     var c:int  = g(b - 1) + g(b + 1);
  8.     return (a * b * c) / (a + b + c);
  9. }
  10. 誤った記述例
  11. private function f(i:int, j:int):int
  12. {
  13.     var a:int;
  14.     var b:int;
  15.     var c:int;
  16.     a = g(i - 1) + g(i + 1);
  17.     b = g(a - 1) + g(a + 1);
  18.     c = g(b - 1) + g(b + 1);
  19.     return (a * b * c) / (a + b + c);
  20. }

AS3はブロック内のみが有効範囲のローカル変数に対応しておらず、変数名の重複でコンパイルエラーが出るときが多々あるので、個人的には、最初にまとめて宣言しちゃいたいです。

まぁ、変数名にもっと気を使ってコード書けって話になるのかもしれませんが。

記述書式
  1. コードは1行あたり半角文字80字で折り返します。 これにより以下のメリットを享受できます。
  2. デベロッパーが小さな画面を使用している場合でも、長い行を読む際に水平にスクロールする必要がありません。
  3. 比較ユーティリティを使用する際、ファイルの2つのバージョンを並べて表示できます。
  4. プロジェクタを使用してグループにプレゼンする際、スクロールではなくフォントサイズを大きくすることで対応できます。
  5. 途切れや無駄な改行なく、ソースコードを印刷できます。

一行あたり80文字は少なくないですか。
下手したら、メソッドの宣言だけで80文字こえちゃいますよ?
メリットは確かにあるのかもしれませんが、普段コードを書く分には80文字だと少し物足りないですよね。


インデント
  1. 半角スペース4文字のインデントを使用します。

PHPを書くときは、半角2文字派だったんですが、慣れると4文字の方が見やすいです。

その他にもいろいろとあるのですが、個人的に気になったのはこの辺でしょうか。
コーディングスタイルは人それぞれだと思いますので、そんなに気にすることもないのかもしれませんが、
時間があれば一度目を通してみると、いろいろと発見があって面白いかもしれません。