Skip to content
uupaa edited this page Oct 13, 2014 · 30 revisions

このエントリでは、JavaScript コードのヘッダとボディを分離する理由について述べます。

コードはどんな時に読まれるか

貴方のコードはどんな時に読まれるでしょう?

  • 80% の時間は、どんな API があってどんな引数で何を返すのかを知るために使われます。必要になる度に何度もチラ見されます。
  • 残り 20% の時間は、デバッグのために読まれます。

貴方のコードを読む殆どの人は、API に興味があり、瞬時に知りたいと考えています。

コードを読む人はどんな人か

また、貴方のコードを読む人はどんな人でしょう?

  • デバッグのために読む人。イライラしており時間に余裕も無いため、無関係な部分は読み飛ばしたいと考えています。どこを見ればよいのか瞬時に知りたいと考えています。
  • 興味本位でコードを読む人。とりあえず上から下まで軽く読み流します。
  • 評価のためにコードを読む人。早ければ2秒、長くても1〜2分程度の時間で、コードの質と、コーディングセンスの良し/悪しも同時に判断されます。

読み手の行動や潜在的な要求をイメージできるかどうか

コードを読む人は「API を素早く確認したい」のです。

このような読み手の要求を想像できない人は、API を集中的に記載したヘッダ部分を作らず、実装(ボディ)にAPIの定義を混ぜ込んだチャーハンのようなごちゃごちゃとしたコードを書きます。

このようなコードは、時間当たりの情報量が低い(=読み手の事を考慮しておらず低品質なもの)と誤解されても文句は言えません。

コードの読み手が、転職先の会社の(多忙を極める)面接官だった場合は、どうなるでしょうか?

どうすればよいか

最も良い方法は、コードの先頭部分(ヘッダ部分,最初の1〜2画面内)に API の一覧を記載することです。
コードのヘッダを一瞥すれば、そのコードに実装されている 60〜80% の情報を得られる状態にします。

これまで説明してきた考え方は、特別な新しいアイデアではなく、 C/C++ では既にヘッダファイル(.h)として実現されているものです。

悪い例

// 見通しが悪く、読み手の時間を奪うダメな実装例
(function(window, undefined) {
var MyClass = function() {
};

MyClass.prototype.method1 = function(arg1) {
    ...
};
...
MyClass.prototype.method29 = function(arg1, arg2, arg3) {
    ...
};
MyClass.prototype.method30 = function(arg1, arg2) {
    ...
};

window.MyClass = MyClass;
})(window);

良い例

(function(global) {

// --- class / interfaces ----------------------------------
function MyClass() {
}

MyClass.prototype = {
    constructor:  MyClass,          // new MyClass():MyClass
    method1:      MyClass_method1,  // MyClass#method1(arg1:Any):this
      :
    method29:     MyClass_method29, // MyClass#method29(arg1:Any, arg2:Boolean, arg3:String):this
    method30:     MyClass_method39  // MyClass#method30(arg1:Any, arg2:Number):this
}; 
// --- implements ------------------------------------------
function MyClass_method1(arg1) {
    ...
}
...
function MyClass_method29(arg1, arg2, arg3) {
    ...
}
function MyClass_method30(arg1, arg2) {
    ...
}
// --- exports ---------------------------------------------
global["MyClass"] = MyClass;

})((this || 0).self || global);

Clone this wiki locally