紳士なブログ

紳士すぎてすみません

CoffeeScriptの基礎まとめ その2

今回は文字列を扱います。

s = "hello"

s = "this is a pen.
this is a panda.
this is the end"



ヒアドキュメントを使うと、こうなります。

s = "hello"

s = """this is a pen.
this is a panda.
this is the end"""



変数を展開させるためには以下のようにします。

name = "zakiyama"

alert "hi, #{name}"



数値計算もできます。

alert "hi, #{15/3}"

CoffeeScriptの基礎まとめ その1

家でアプリをつくるときにRails3.2を使っているのですが、そのRails3ではCoffeeScriptファイルが自動で生成されるようになっています。

もともと興味があったこともあって、せっかくの機会なので勉強してみようと思い、少し基礎をまとめてみました。


CoffeeScriptとは


公式サイト

http://www.coffeescript.org

TRY COFFEESCRITのところで、CoffeeScriptとJavaScriptの違いを確かめることができる


コメントアウト

# コメントアウト


###
コメントアウト
###


JavaScriptとの違い

  • varは不要
  • 行末のセミコロン不要
  • 波括弧はインデントで表現
  • 丸括弧は曖昧性がない場合は省略可能

JavaScriptで書くとこうなる

var message = "hello world";
if (message.length > 1) {
  alert(message);
}


これをCoffeeScriptで書くとこうなる

message = "hello world"
if message.length > 1
  alert message

javascriptの勉強 その3 -関数-

引き続き、javascriptの勉強をしていきます。

今回は少し重めの関数の話。
それでは早速。


  • 関数は一連の命令文を内包したjavascriptの基本的な部品である
    • 関数は、コードの再利用、情報の隠蔽、プログラムの構造化のために利用される
    • また、関数はオブジェクトの振る舞いを規定するためにも利用される
  • 一般的にプログラミングを行うということは、一連の要求仕様を関数とデータ構造に分解するための作業である


  • Functionオブジェクト
    • javascriptにおける関数はオブジェクトである
      • オブジェクトは複数の名前と値のペアで構成されており、プロトタイプオブジェクトへの隠れたリンクをもっている
    • FunctionオブジェクトはFunction.prototypeにリンクされている(そしてそれはObject.prototypeへリンクされている)
    • すべての関数は、生成される際にさらにもう2つの隠されたプロパティを持つようになっている
    • それは、その関数の振る舞いを決めるためのコンテキストとコードである
    • 関数オブジェクトもすべて、生成時にprototypeプロパティが同時に生成される
      • その値はオブジェクトであり、そのconstructorプロパティにはその関数自身がセットされている
    • 関数はオブジェクトなので、それ以外の値と同様に扱うことができる
      • 関数を変数やオブジェクト、配列に格納することもできる
      • 関数が他のオブジェクトと異なるのは、それを呼び出すことができるという点である



// addという変数を定義し、2つの値を加算する関数を格納する
var add = function (a, b) {
  return a + b;
}


  • 関数リテラルつづき
    • 関数リテラルは4つのパーツで構成される
      • 1番目はfunctionという予約語
      • 2番目は関数の名前で、これは省略可能
        • 関数に名前をつけることで、再帰的に呼び出すことが可能となる
      • 3番目は括弧で囲まれた関数のパラメータである
        • 通常の変数がundefinedで初期化されるのと異なり、これらの変数はその関数が呼び出された際に、渡された引数で初期化される
      • 4番目は中括弧で囲まれた、命令文の集合体である
        • これらの命令文は関数の本体であり、その関数が呼び出された際に実行される
    • 関数リテラルは、式を記述可能な場所であればどこにでも記述することができる
      • 関数を他の関数の内部で定義することもできる
      • 内包された関数は、もちろんそれ自身のパラメータや変数にアクセスできるが、それだけでなく、その関数を内包している外側の関数のパラメータや変数にアクセスすることもできる
      • 関数リテラルで定義された関数オブジェクトは、外部コンテキストへのリンクも保持していると言える
      • この機能は「クロージャ」と呼ばれ、これを活用することで、かなり高い表現力を得ることができる


  • 関数の呼び出し
    • 関数の呼び出しを行うと、現在実行されている関数の処理は一旦停止され、コントロールとパラメータが新しい関数へと渡される
    • 定義されたパラメータに加えて、すべての関数はあと2つのパラメータを自動的に受け取っている
      • それはthisとargumentsである
      • thisパラメータはオブジェクト指向プログラミングにおいては非常に重要なもので、その値は呼び出しのパターンによって異なる
      • javascriptの呼び出しのパターンは、メソッド呼び出しパターン、関数呼び出しパターン、コンストラクタ呼び出しパターン、apply呼び出しパターンの4つの種類があるが、これらの違いは、thisという追加パラメータがどのように初期化されるか、という点にある


  • メソッド呼び出しパターン
    • 関数がオブジェクトのプロパティとして格納されている場合には、メソッドと呼ばれる
    • メソッドが呼び出された場合、thisにはそのオブジェクトが格納される


// myObjectを生成する
// これはvalueプロパティとincrementメソッドをもつ
// incrementメソッドはパラメータを1つとり、これは省略可能である
// 引数が数値ではなかった場合、
// 代わりにデフォルト値として1が使われる

var myObject = {
  value: 0,
  increment: function (inc) {
    this.value += typeof inc === 'number' ? inc : 1;
  }
};

myObject.increment();
document.writeIn(myObject.value); // 1

myObject.increment(2);
document.writeIn(myObject.value); // 3


  • メソッド呼び出しパターンのつづき
    • メソッドではthisを使ってオブジェクトにアクセスできるので、オブジェクトから値を取得したり、オブジェクトの内容を修正したりすることができる
    • thisへのオブジェクトのセットは、呼び出しが発生したタイミングで行われる
    • 遅延束縛と呼ばれるこの割り当てのタイミングのおかげで、thisは非常に便利なものとなっている
    • thisを使って自分自身のオブジェクトコンテキストにアクセスしているメソッドは、パブリックメソッドと呼ばれる


  • 関数呼び出しパターン
    • 関数がオブジェクトのプロパティではない場合は、関数として呼び出される
    • このパターンで呼び出された関数では、thisにはグローバルオブジェクトがセットされる。これは言語の設計としては失敗である。
      • これには回避策が存在する。
      • もしメソッド内で別の変数を定義し、その中にthisの値を代入すれば、内部関数ではその変数を通じてthisの値にアクセスできるようになる


var sum = add(3, 4); // sumは7


// myObjectにdoubleメソッドを追加する

myObject.double = function() {
  var that = this; // 値の待避

  var helper = function() {
    that.value = add(that.value, that.value);
  };

  helper(); // helperを関数として呼び出す
};

// doubleをメソッドとして呼び出す

myObject.double();
document.writeIn(myObject.value);


  • コンストラクタ呼び出しパターン
    • javascriptは、プロトタイプ継承を行う言語である
      • これは、オブジェクトが他のオブジェクトから直接継承を行うことを意味する
      • そしてこの言語にはクラスの概念は存在しない
    • もし関数を呼び出す際に、new演算子が前に付けられていた場合、新しいオブジェクトが生成されて、thisにはその新しいオブジェクトがセットされるようになる
    • そしてそのオブジェクトは、呼び出された関数のprototypeプロパティへの隠されたリンクをもっている


// Quoという名のコンストラクタ関数を生成する
// これはstatusプロパティをもつオブジェクトを生成する

var Quo = function (string) {
  this.status = string;
};

// get_statusというパブリックメソッドを
// Quoのすべてのインスタンスで利用可能にする

Quo.prototype.get_status = function () {
  return this.status;
};

// Quoのインスタンスを生成する

var myQuo = new Quo("confused");

document.writeIn(myQuo.get_status()); // confused


  • コンストラクタ呼び出しパターンつづき
    • new演算子をつけて呼び出すことを前提とした関数は、コンストラクタと呼ばれる
      • コンストラクタは、大文字で始まる名前の変数に格納されるのが慣例である


  • apply呼び出しパターン
    • javascriptは関数型オブジェクト指向言語であり、関数はメソッドをもつことがきる
    • applyメソッドを使うことで、引数を格納した配列を使って関数を呼び出すことができる
    • さらに、applyメソッドを使うことでthisにセットされている値を自由に設定することが可能になる
      • applyメソッドには2つのパラメータを指定することができ、1つ目はthisにセットしたい値、2つ目はパラメータの配列である


// 2つの数値からなる配列を作り、それらを足し合わせる

var array = [3, 4]
var sum = add.apply(null, array); // sumは7

// statusというメンバをもつオブジェクトを生成する

var statusObject = {
  status: 'A-OK'
};

// statusObjectはQuo.prototypeを継承していない
// しかし、statusObjectがget_statusメソッドを持っていないにも
// かかわらず、statusObjectのget_statusメソッドを呼び出すことが可能になる

var status = Quo.prototype.get_status.apply(statusObject);

// statusは'A-OK'


  • 変数型の拡張
    • javascriptでは、標準で用意されている変数型を拡張することができる
    • 以前、Object.prototypeを使うと、すべてのオブジェクトで利用できるメソッドを追加できることを紹介したが、関数や、配列、文字列、数値、正規表現、真偽値においても、同様のことが言える
    • 標準で用意されている変数型を拡張することで、言語の表現力を飛躍的に高めることができる
      • javascriptのプロトタイプ型のインターフェイスがもつ動的な性質のおかげで、メソッドを追加すると、その変数型の値すべてが即座にそのメソッドを利用できるようになる
      • たとえば、Function.prototypeを拡張することで、すべての関数で利用できるメソッドを追加することができる


Function.prototype.method = function (name, func){
  this.prototype[name] = func;
  return this;
};


ひとまず今回はここまでにします。
長々とお付き合いいただきありがとうございます。

javascriptの勉強 その2 -オブジェクト-

引き続きjavascriptの勉強を進めていきます。

今回はオブジェクトの話です。


オブジェクト

  • javascriptには、単純な変数型として、数値、文字列、真偽値(trueとfalse)、null、undefinedがある
  • そして、それ以外の値はすべてオブジェクト


  • 数値、文字列、真偽値はメソッドを呼び出すことができる、という意味ではオブジェクトに似ている
  • しかし、これらの値はイミュータブル、すなわち一度セットしたら値を変更できない
  • 一方、javascriptにおけるオブジェクトはキーによって整理されたミュータブル、つまり変更可能なデータの集合体
    • javascriptでは、配列も、関数も、正規表現もすべてオブジェクト
    • 当たり前だが、オブジェクトもオブジェクト


  • オブジェクトは複数のプロパティをもつコンテナで、名前と値で構成されている
    • プロパティ名は任意の文字列が利用でき、空文字も利用可能
    • プロパティの値には、undefinedを除くすべてのjavascriptの値をセットできる


  • javascriptにおけるオブジェクトはクラスの概念をもたない
  • プロパティ名やプロパティの値に関して、何の制約ももたない
    • オブジェクトはデータの集約や整理に非常に役立つ
    • オブジェクトの中にオブジェクトを含むこともできるので、ツリー構造、グラフ構造を表すことも容易


  • javascript には、他のオブジェクトのプロパティを継承することを可能にする、プロトタイプ連鎖の機能が用意されている
    • これをうまく利用することで、オブジェクトの初期化のコストとメモリの消費量を抑えることができる


  • オブジェクトリテラル
    • オブジェクトリテラルを利用すると、新しいオブジェクトの生成を非常に簡潔に記述することができる
      • オブジェクトリテラルは2つの中括弧で囲まれ、その中に名前と値のペアが列挙されたもの
      • オブジェクトリテラルは、式が記述可能であれば、どこにでも記述することができる


var empty_object = {};

var stooge = {
  "first-name": "Jerome",
  "last-name": "Howard"
};


  • オブジェクトリテラルつづき
    • プロパティ名には、空文字を含む任意の文字列が利用できる
    • プロパティ名の前後につけるクォート("")は、文字列が予約後ではなく、javascriptの名前に則っていれば、省略することができる
      • たとえば、"first-name"の場合はクォートが必要だが、first_nameの場合には省略が可能
    • プロパティの区切りにはカンマを利用する
    • プロパティの値には任意の式を記述できるし、他のオブジェクトリテラルを含むことも可能(すなわち、オブジェクトはネストすることができる)


var flight = {
  airline: "Oceanic",
  number: 815,
  departure: {
    IATA: "SYD",
    time: "2004-09-22 14:55",
    city: "Sydney"
  },
  arrival: {
    IATA: "LAX",
    time: "2004-09-23 10:42",
    city: "Los Angeles"
  }
};


  • 値の取得
    • 文字列式を[]で囲んで指定することで、オブジェクトから値を取り出すことができる
    • []の代わりに.を利用することもできる(ただし、文字列式が文字列リテラルで、予約語ではないjavascriptの名前のルールに則っている場合に限る)
      • .を使った表現の方がおすすめ(コンパクトで読みやすいから)


stooge["first-name"]  // "Jerome"
flight.departure.IATA // "SYD"



存在しないメンバを取得しようとした場合にはundefinedが返される

stooge["middle-name"] // undefined
flight.status         // undefined
stooge["FIRST-NAME"]  // undefined



'||'演算子を使ってデフォルト値を設定することが出来る

var middle = stooge["middle-name"] || "(none)";
var status = flight.status || "unknown";



undefinedに対して、さらにそのプロパティを取得しようとしてしまうと、TypeError例外が投げられてしまう。

&&演算子を利用することでそうした事態を避ける事ができる

flight.equipment                           // undefined
flight.equipment.model                     // "TypeError"が投げられる
flight.equipment && flight.equioment.model // undefined


  • 値の更新
    • オブジェクトの値は、設定の場合と同様の方法で更新することができる


stooge['first-name'] = 'Jerome'


  • プロトタイプ
    • すべてのオブジェクトは、プロトタイプオブジェクトとリンクしていて、そこからプロパティを継承している
      • オブジェクトリテラルによってつくられたオブジェクトはすべて、javascript標準のObject.prototypeオブジェクトとリンクしている
    • オブジェクトを新たに生成する際には、プロトタイプとするオブジェクトを選択することができる
      • Object関数にcreateメソッドを追加してみよう
      • createメソッドは既存のオブジェクトをプロトタイプとして、新しいオブジェクトを生成する機能をもつ関数


if (typeof Object.create !== 'function'){
  Object.create = function (o) {
    var F = function () {};
    F.prototype = o;
    return new F();
  }
}


  • プロトタイプつづき
    • プロトタイプとのリンクはオブジェクトの修正の際には何も影響を及ぼさない。つまり、オブジェクトの内容を書き換えた際に、プロトタイプの内容が変更されることはない。
    • プロトタイプとのリンクは、オブジェクトから値を取得する際にのみ利用される
      • オブジェクトから指定したプロパティの値を取得する際に、もしそのオブジェクト自身に指定された名前のプロパティがなかった場合、javascriptはプロトタイプオブジェクトからプロパティの値を取得しようとする
      • そしてもしそこにもプロパティが存在しなかったら、さらにそのオブジェクトのプロトタイプにさかのぼっていき、最終的にObject.prototypeに行き着くまで検索が行われる
      • もし該当するプロパティがプロトタイプチェーン上に存在していなかった場合には、undefinedという値が得られることになる
      • この仕組みは「委譲」と呼ばれている
    • プロトタイプの結びつきは、動的なものである
      • プロトタイプオブジェクトに新しいプロトタイプを追加した場合、そのプロパティはその瞬間から、そのオブジェクトをプロトタイプとするオブジェクトすべてにおいてもアクセス可能になる


stooge.prefession = 'actor';
another_stooge.profession // 'actor'


  • プロパティの削除
    • delete演算子を使うとオブジェクトからプロパティを削除することができる
      • この演算子は、指定したプロパティがオブジェクト上に存在した場合に、それを削除する機能をもつ
      • このオペレータは、プロトタイプチェーン上のオブジェクトに作用することはない
      • そのため、オブジェクトからプロパティを削除すると、プロトタイプチェーン上に存在していた同じ名前のプロパティが見えるようになる


another_stooge.nickname // 'Moe'

// another_stoogeからnicknameプロパティが削除され、
// プロトタイプ上のnicknameプロパティが見えるようになる

delete another_stooge.nickname;

another_stooge.nickname // 'Curly'


  • グローバル領域の利用を減らす

javascriptの勉強 その1 -文法-

たまに少しかじったりはちょくちょくしてたけど、
じっくり勉強したことはなかったのでそろそろ時間をとってjavascriptを勉強してみる。


題材はO'REILLYの『Javascript : The Good Parts』。
O'REILLY大好きです。


javascriptの良い部分つまみ食いなので、少し違うところで勉強してから読んだほうがいいという所感。


目次

1章 良いパーツ
2章 文法
3章 オブジェクト
4章 関数
5章 継承
6章 配列
7章 正規表現
8章 メソッド
9章 スタイル
10章 美しい機能たち


文法

  • 名前
    • 予約語の多くは、javascriptの中では使われない
      • undefined, NaN, Infinityなどは本来予約語になるべきなのになっていない
    • 予約語は変数やパラメータの名前として利用することができない
    • オブジェクトのプロパティとしても、オブジェクトリテラルとしても、ドットの後に書くようにしても使うことができない


  • 数値
    • javascriptには数値型が1つしかない
    • 他の言語と異なって、独立した整数型をもたない
      • たとえば、1と1.0はまったく同じ値
    • 数字を単に「数字」として認識すればいいので、数値型のせいで発生するエラーを気にする必要がない
    • 数値はメソッドをもつ
    • Mathオブジェクトが用意されている
      • たとえば、Math.floorメソッドは数値を整数に変換する


  • 文字列
    • 文字列リテラルは、シングルクォート、もしくはダブルクォートで囲むことで表現でき、その中には0コ以上の文字を含むことができる
    • 文字列はlengthプロパティをもつ
      • たとえば、"seven".lengthの値は5
    • 文字列はイミュータブル、すなわち一度生成されたらその内容を変更できない
    • +演算子を使って文字列に他の文字列を連結することはできる
    • 文字列ではメソッドが利用できる


  • 命令文
    • var文が関数内で使われたときは、その関数のプライベート関数を定義するものとなる
    • switch, while, for, do文は、ラベルをオプションとして命令文の前に付けることができる
    • そしてbreak文でそのラベルを指定することができる
    • ブロックは一連の命令文のことで、中括弧で囲まれている
      • ただし、javascriptのブロックは、他の言語と異なり、新しいスコープを生成しない
      • そのため、変数はブロックの中でなく、関数の先頭で定義するべし
    • for文は2種類の書き方をし、複雑なループを実行することができる
    • 1つ目は初期化部分、条件式、増加部分という3つの省略可能な節を利用して制御を行う、昔から知られている書き方
      • まず、初期化。ループ変数の初期化を行う。
      • 次に、条件式が評価される。ループ変数がループを終了する条件を満たしたかどうかを調べる。
        • 条件式が省略された場合、評価結果は常にtruly
        • 評価式がfalsyと評価された場合、ループが終了
      • もしループが終了されなければブロック部分が実行され、そして増加部分が実行されてから、条件式の評価の部分からループがくり返される。
    • もう1つの書き方はfor inと呼ばれ、指定したオブジェクトのプロパティ名を列挙するものである
      • この書き方では、それぞれのくり返しの際にオブジェクトのプロパティ名が1つずつ指定した変数に格納されていく
      • その際には、object.hasOwnProperty(変数名)メソッドを利用して、そのプロパティ名が本当にそのオブジェクトのメンバか、それともプロトタイプチェーン上にあるものなのか、ということをチェックする必要がある場合が多い


for (myvar in obj) {
  if (obj.hasOwnProperty(myvar)){
    ...
  }
}


  • 命令文のつづき
    • try文はブロック部分を実行してその中で投げられたすべての例外をキャッチする
      • catch節では、例外オブジェクトを受け取るために、新しい変数を定義する
    • throw文は例外を発生させる
      • そしてthrow文がtryブロック内に存在した場合は、catch節に処理が移る
      • そうでなければ、その関数の実行は強制的に終了し、呼び出し元でtryが使われている場所のcatch節に処理が移動する
      • throw文における式では通常、nameとmessageの2つのプロパティを含むオブジェクトリテラルを生成させる
        • そうしておくことで、その例外をキャッチした際に何をすべきかを決定するための情報を得ることができる



  • 関数
    • 関数リテラルは、関数オブジェクトを定義する
      • 関数リテラルでは、再帰的に呼び出しを行う際に利用するために、名前をつけることもできる
      • パラメータを列挙して記述できる
      • これらのパラメータは、その関数が呼び出された際に引数として渡されてきた値によって初期化される


お読みいただきありがとうございます。
まだまだ続きますよ。

ruby script/runnerのお話

以前ruby script/runner関連で意味不明なエラーが出たのでちょっと調べてみました。
今の自分にはわからないことが多かったので、雑多にまとめてみようと思います。


RailsアプリでActiveRecordを使ったバッチ処理 その2」

http://higelog.brassworks.jp/?p=12

  • ruby on railsではscript/runnerを使えばWebアプリ内からではなくてもメソッドを実行することができる
  • script/runnerはRails環境を読み込んだうえでワンライナーを実行するためのスクリプト
  • このコマンドをcronなどで定期的に実行するようにする



「script/console と script/runner の環境の指定方法の違い」

http://d.hatena.ne.jp/takihiro/20080507/1210163583

script/console と script/runner で環境の指定の仕方が違うとのこと。

% ruby script/runner -e production
% ruby script/console production


使い方のヘルプはそれぞれこんな感じ。

% ruby script/runner -h
Usage: script/runner [options] ('Some.ruby(code)' or a filename)

    -e, --environment=name           ...


% ruby script/console --help
Usage: console [environment] [options]


環境を設定するコードも全然違うみたい。

  • rails-2.3.14/lib/commands/runner.rb
require 'optparse'

options = { :environment => (ENV['RAILS_ENV'] || "development").dup }
code_or_file = nil

ARGV.clone.options do |opts|
  opts.on("-e", "--environment=name", String,
          "Specifies the environment for the runner to operate under (test/development/production).",
          "Default: development") { |v| options[:environment] = v }
end

ENV["RAILS_ENV"] = options[:environment]
RAILS_ENV.replace(options[:environment]) if defined?(RAILS_ENV)


  • rails-2.3.14/lib/commands/console.rb
ENV['RAILS_ENV'] = case ARGV.first  # (1)
  when "p": "production"
  when "d": "development"
  when "t": "test"
  else
    ARGV.first || ENV['RAILS_ENV'] || 'development'
end


Rails task: script/runner or rake? - Stack Overflow

http://stackoverflow.com/questions/591503/rails-task-script-runner-or-rake

scrpt/runner some_useful_thing と rake some:other_useful_thingどちらが好まれるかという話。


script/runner がRailsを呼び出すのに対し、 rakeは :environment を指定したりして呼び出すことを明確にしない限りRailsを呼び出さない。
Railsを呼び出すのはコストがかかるので、避けられるに越したことはないという話になります。

とは言ってもほとんど同じとのこと。どちらも使うことはあるし、むしろ script/runner を使う人もいるようです。


script/runner OR script/rails runnerがクソ重い。どうしてくれんのよ?

http://d.hatena.ne.jp/babie/20100506/1273157249

Railsでのバッチ処理(script/runner)は環境を全部ロードするのでスタートアップがとても重いとのこと。
daemon_generatorなどを使う手もある。

他にもたくさん方法はあるみたいです。

http://higelog.brassworks.jp/?p=15


でもちょっと大げさ、というときのための手軽な方法があるようです。

actionに処理内容を書いて、ローカルのスクリプトからHTTPアクセスして叩く、という方法。
手動やcron/crontabで処理しようと思っていたなら使える方法です。

  • app/controllers/hoge_controller.rb
class HogeController < ActionController::Base
  def batch
    # IP制限しないと怖いですよ……
    raise NotFoundError.new unless request.remote_ip == "127.0.0.1"

    # 処理内容を書く
    ...

    render :text => "ok", :status => 200
  end
end

IPアドレスを制限するのがポイントとのこと。


じゃあバッチスクリプトはどう書くかというと、

  • script/batch.rb
#!/usr/bin/env ruby

require "net/http"
Net::HTTP.version_1_2

if __FILE__ == $0
  Net::HTTP.start('127.0.0.1', 80) do |http|
    response = http.get("/hoge/batch")
    unless response == Net::HTTPSuccess
      # log にエラーを吐くとか……適当に。
    end
  end
end

こんな感じで、cron/crontabに設定しておけばよいようです。
NotFoundErrorのところ、ちゃんと定義しておく必要がある(名前は任意)みたい。


  • app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  ...

  class NotFoundError < StandardError; end
  rescue_from NotFoundError, :with => :record_not_found

  def record_not_found
    render :file => File.join(RAILS_ROOT, 'public', '404.html'), :status => 404
  end
end

すでにロードされているので激速とのこと。今度試してみる。



railsのmodelメソッドを簡単にdaemon化する方法」

http://doruby.kbmj.com/red/20100707/rails___model___daemon__


Railsで普段開発する際には、ruby script/console や ruby script/runnerは重宝する。

これらのコマンドは、Webアプリを作成するために作ったmodelのメソッドを、簡単にbatchやコマンドラインのインタラクティブアプリに変更することができ、cron化やデバッグにとても重宝される。


最後までお読みいただきありがとうございます。

『良いコードを書く技術』のまとめ その1

そろそろリファクタリングとか良いコードを書くことをもっと意識してもいいなと思ったので、『良いコードを書く技術』を読んでみた。

いくつか参考になることがあったので、重要なところをまとめてみたいと思います。

f:id:mathemathiko:20120609170450j:plain

Amazonで詳細を見る


目次

第1章 良いコードとは何か
第2章 良いコードを書くための5つの習慣
第3章 名前付け
第4章 スコープ
第5章 コードの役割
第6章 コードの集約
第7章 コードのパフォーマンス
第8章 ユニットテスト
第9章 抽象化
第10章 メタプログラミング
第11章 フレームワークを作ろう


良いコードの定義


本書では、次の4つを満たすものを良いコードと定義している。

  • 保守性が高い
  • すばやく効率的に動作する
  • 正確に動作する
  • 無駄な部分がない


良いコードを書くための習慣


長い期間プログラマをやっているからといって必ず良いコードが書けるようになるわけではない。
良いコードを書くための習慣を日々実践して、時間をかけて積み上げていくことが重要。


  • その1 コードを読んで読んで読みまくる
    • オープンソースソフトウェアや周りの達人プログラマの人が書いたコードをじっくり読んだことがないのであれば、かなり危うい状況
      • 音楽や絵画など芸術の世界で、自分だけの発想で作品を完成させる人はいない
      • 先人たちの作品を見て、影響を受けたり良いところを盗んで咀嚼していくなかでオリジナルの作品を生み出していく


  • その2 とにかくコードを書く
    • いったい何を書けばいいんだろうという人は、コードの写経をするとよい
    • 写経することで、もとのコードが書かれた手順や、行間に潜む意図を伺い知ることができる


手の裏付けのない言葉はあまりに安い。人を動かしたかったら、まず自分の手を動かせ。手が塞がっていたら、手を動かした経験を語れ。口で語るな手で語れ。
ーー小飼弾「スーツの道も、舗装するのはギーク(404 Blog Not Found)2007」


  • その3 道具を磨く
    • コードを書くうえで必要な道具や環境を最高の状態に保つ
    • 作業効率を上げていくことで、無駄のないプログラミングを行う


  • その4 良い知識を得る
    • 書籍を選ぶときは良書を選ぶべし
    • 各言語において原典とも言える良書と、それを読みやすくするためのHOW TO本を組み合わせるとよいのでは


  • その5 アウトプットと人からのFBでさらなる成長を
    • コードレビューを受ける
      • GitHubで自分のコードを公開する、公開されている他人のコードを読むことはおすすめ
    • ブログを書く
    • 勉強会に参加する


名前付け

  • 良い名前は重要
    • 良い名前を使うことで読みやすく理解しやすいコードになり、保守性も向上する
    • 逆に悪い名前はバグを生み出しやすく、保守が難しくなる
    • 名前付けは良いコードの第一歩であり、基本中の基本
      • オープンソフトウェアのコードを見たりして、命名の幅を広げるのも有効
      • 名前付けがうまくできないときは設計を見なおしたほうがよいことが多い


  • 良い名前の条件
    • 説明的で意味・意図を表している
      • 良い変数名、メソッド名、クラス名は、名前がその中身を正しく表している
      • 逆に長すぎるとコードの可読性が落ちる
    • 省略のコツ
      • 先頭の数文字を残す(Separators→Seps)
      • ingの削除(Grouping→Group)
      • 単語の削除(formattedConsumptionTax→formattedTax)
      • 語頭以外の母音を削除(image→img)
      • 強い音を残す(server→svr)
      • 一般的な略語の利用(database→db)
    • 一貫性がある
      • 対称性を保つ
      • 単語の組み合わせ方を一貫させる
    • コーディング標準に従う


  • 変数名
    • 変数名は宣言、代入、参照といった箇所でコード中に何度も登場するため、良い変数名を付けることができればコードの可読性は飛躍的に高まる
    • 基本は説明的な名前を付ける
      • 変数には値やオブジェクトが格納されている。変数名を見るだけで何がどのような役割として格納されているかが明確にわかるものが良い名前
    • 変数はスコープによって求められる良い名前の性質が異なる
      • スコープが長いとさまざまな箇所から参照され影響範囲が広いため、注意が必要


  • メソッド名
    • 良いメソッド名は、名前から機能が想像できる
    • メソッドは処理を行うので、メソッド名は動詞または動詞+目的語になっていることが多い
    • インスタンスメソッドは「Report.new」のようにオブジェクト名と組み合わせて呼び出されるので、組み合わされたときに重複なく意味が通り名前にする
    • クラスメソッドとクラス名も同様
    • よく使用されるメソッドは簡潔で短い名前が良いと言われる


  • クラス名
    • 変数名やメソッド名と比べてクラス名は単位が大きいため、適切で良い名前を付けることが重要
      • 良いクラス名は、名前だけで何を行うクラスかがわかる
    • クラス名がうまく思い浮かばないときは、自分が作ろうとしているクラスの役割が整理できていない
      • 1つのクラスに複数の責務を押しこんでいたり、役割があいまいだったりしている可能性がある
    • クラスの名前付け=設計である
    • 筆者「自分が知らない表現・概念は、自分の中から生まれない」
    • より上位の表現をものにするには、いろいろなコードや書籍を読んだり、実際にコードを書いて試すことが重要
    • クラス名に対する成長の過程


  • まとめ
    • 最初から良い名前付けをできる人はいない
    • どういう名前が良いのかを慎重に検討し、適切な名前を決定するプロセスを繰り返していく
    • 自分が知らないまったく新しい概念の名前が、突然ひらめくことはない
    • コードリーディングやコードレビュー、誰かに相談するなどして、名前の引き出しを少しずつ増やしていくことでネーミングセンスを鍛える


やたら長くなりそうなので、一旦ここで区切りますー