Hatena::ブログ(Diary)

杉風呂2.0 - A Lifelog -

2012-07-08(日)

[][]もっと上手に JavaScript を書くための 10 の Tips (10 tips to write better JavaScript)

この文章は、 Kinesis framework の公式ブログから "10 tips to write better JavaScript" という記事を翻訳したものです。今回は原文を並記してみます。実験的に GituHub で作業をしていたところsakuro さんからご指摘頂きました。GitHubは素晴らしいですね。

10 tips to write better JavaScript

http://kinesis.io/blog/10-tips-to-write-better-javascript/

1. セミコロンを忘れない(Don’t forget the semi-colons)

JavaScript allows developers the freedom to skip semi-colons in the source code. Most of us, being lazy as we are, tend to follow this.

However, the JavaScript compiler still needs them, so it is the parsers job to insert them whenever there is a parse error due to a missing semi-colon. It tries to execute the statement, and if it fails, it tries again with the semicolons

When you’re writing JavaScript, you should always include semicolons after statements.

JavaScript では、開発者がソースコード中のセミコロンを飛ばす自由がある。ほとんどの人は、私たちがそうであるように、怠け者なので、そうしがちだ。

しかし、JavaScriptコンパイラは依然としてセミコロンを必要としていて、セミコロンがないところでパースエラーがあると必ず、パーサがセミコロンを挿入する。ステートメントを実行しようとして失敗すると、セミコロンから実行を再開しようとする。

JavaScript を書くときは、ステートメントの後ろにかならずセミコロンを含めるべきだ。

2. 言語をよく知る(Know the language)

When we talk about Arrays and Objects in JavaScript, there are two ways to initializing them listed below.

JavaScript で Array とObject の話題といえば、以下のように、2 種類の初期化の方法がある。

var arr = [], obj = {};

var arr = new Array, obj = new Object;

だ。

Note that in modern browsers, the first way is faster and should be used.

モダンなブラウザでは、最初の方が高速なので、こちらを使うべきだ。

3. For ループ 対 For in ループ (For vs For in Loop)

The for in loop looks like

ループで使用する for はこんな感じだ。

for(item in obj) {
 //do something with item
}

This has a drawback. It will not just access the properties of “obj”, it will also include any properties inherited by the object through the prototype chain.

Therefore, most of the times, we have to use a if statement inside the loop along with the method “hasOwnProperty()” on the “obj”.

これには欠点がある。アクセスを許すプロパティが obj のものだけではないということだ。プロトタイプチェーンによって継承したプロパティをすべて含んでいるということでもある。

そのため、大抵は、ループ中の obj に対して hasOwnProperty() メソッドと一緒に if ステートメントを使わなくてはいけない。

4. == の代わりに === を使う(Use === instead of ==)

The identity (===) operator behaves identically to the equality (==) operator except no type conversion takes place. The types must be the same for === to return true.

The == operator will compare for equality after doing any necessary type conversions. The === operator will not do the conversion, so if two values are not the same type === will simply return false. It’s this case where === will be faster, and may return a different result than ==. In all other cases performance will be the same.

'===' 演算子は、等値か判断するのに必要な変換を行ってから比較を行う。'==' 演算子は変換をしない。2 つの値が同じ型でない場合、 '===' は単純に false を返す。'===' が速いのは事実だし、'==' と異なる結果を返すこともあるが、それ以外のすべての場合で、パフォーマンスは同じだ。

"abc" == new String("abc")    // true
"abc" === new String("abc")   // false

5. with の使用を避ける(Avoid using “with”)

JavaScript’s with statement was intended to provide a shorthand for writing recurring accesses to objects. So instead of writing

JavaScript の with ステートメントは、オブジェクトに繰り返しアクセスするための略記法を提供するためのものだ。次のように書く代わりに、

a.s.d.f.g.h.j.k.hello = true;
a.s.d.f.g.h.j.k.world = true;

You can write

このように書ける。

with (a.s.d.f.g.h.j.k) {
    hello = true;
    world = true;
}

How can you be sure if the variable a.s.d.f.g.h.j.k.hello is being set or a global variable named hello is being set.

Fortunately, we have a better way of doing this.

a.s.d.f.g.h.j.k.hello という変数がセットされるか、hello というグローバル変数がセットされるか自信を持って言えるだろうか。

幸運にも、これをやるよいやり方がある。

var obj = a.s.d.f.g.h.j.k;
obj.hello = true;
obj.world = true;

6. メソッド呼び出しを避ける(できるかぎり)(Avoid method calls (as much as you can))

Inline code is faster in all modern browsers that calling functions. I know that writing code in this manner can lead to clutter, but this is just one those JavaScript annoyances that we deal with.

インラインコードはすべてのモダンプラウザ関数呼び出しを行うよりも速い。私はこの方法が散らかりの元となると知ってはいるが、これは JavaScript のいらいらを扱う一つの方法でもある。

function explicitCall() {
  function cube(x) { return x * x * x };
  var i = 1000;

  while(i--) { console.info(cube(i)); }

}

function inlineCall() {
  var i = 1000;

  while(i--) { console.info(i * i * i); }

}

7. JSLinst を使う(Use JSLint)

http://www.jslint.com/ is The JavaScript Code Quality Tool.

Use this and check your JavaScript for errors as much as you can. Running your code through this is a great way to improve your code and follow the best practices.

http://www.jslint.com/JavaScript の品質測定ツールだ。

これを使って、 JavaScript のエラーをできるだけチェックしよう。この中に自分のコードを走らせれば、コードを改善し、ベストプラクティスに従う素晴らしい方法になる。

8. ドット記法と数値型(Dot Notation and Numbers)

There is a problem in the JavaScript parsers dot notation when dealing with numbers.

JavaScript のパーサは、数値を扱う際のドット記法に問題がある。

10.toString() //Error

The JavaScript parser expects a number to follow right after the first period. This causes a syntax error.

JavaScript のパーサは、最初のピリオドの右側に数字を期待している。これがシンタックスエラーを引き起こす。

To fix this, there are two ways of going forward

これを正すには、次のように 2 つのやり方がある。

(10).toString();
10..toString();

9. ブロックスコープが存在しない(No block scope)

There is no block scope in JavaScript.

Statements like if and for do not create a scope, and therefore variables can be overwritten.

In the following code, we will see how the value changes if the variable x

JavaScript にはブロックスコープが存在しない。

if や for といったステートメントはスコープを作らない。それため、変数は上書きされる可能性がある。

次のコードで、変数 x の値が変更される様子がわかるだろう。

var x = 1; // x = 1

if(true) {
 x = 2; // x = 2

 for(var i=0; i < 4; i++) {
  x = i; //i = 0,1,2,3
 }

}

So x is changing as the code executes.

変数 x がコードの実行とともに変化していく。

10. グローバル変数キャッシュする(Cache Globals)

It is always better when caching globals in terms of execution time.

実行時間の観点から、グローバル変数キャッシュした方がよい場合が多い。

function notcached() {
 var i = 1000;
 while (i--) window.test = 'test';
}

function cached() {
 var i = 1000;
 var w = window;
 while (i--) w.test = 'test';
}
JavaScriptパターン ―優れたアプリケーションのための作法

JavaScriptパターン ―優れたアプリケーションのための作法

2012-06-05(火)

[][]Rails で十分に活用されていなくてもったいない ActiveRecord::Relation のメソッド TOP 10

2013年12月2日更新: 参照されることが多いので Rails 4 の情報を訳注として追記しました。また、Rails 4 に関する情報は、 WEB+DB PRESS Vol.73 が非常に参考になるので、一読をおすすめします。

この文章は Mitch Crowe 氏のブログより 2012年4月14日の記事を翻訳したものです。


The 10 Most Underused ActiveRecord::Relation Methods

http://blog.mitchcrowe.com/blog/2012/04/14/10-most-underused-activerecord-relation-methods/


昨日は ActiveRecord::Relation のコードに膝まで浸かって、使われているのをこれまで全然見たことがない面白いナゲットを思い出させてくれた。この記事で、十分に活用されていない Relation クラスのメソッドのトップ10をリストにしたので、楽しんでもらいたい。

10位 ブロック付きの first_or_create

first_or_create はとてもなじみ深い。

Book.where(:title => 'Tale of Two Cities').first_or_create

そして、名前通りのことをやってくれる。だが、特定の属性を持つレコードを find するとか、それらの属性を持つレコードを create して、さらに追加で属性を設定したくなることが頻繁にあると思う。これを簡潔にやるには first_or_create にブロックを与えればいい。

Book.where(:title => 'Tale of Two Cities').first_or_create do |book|
  book.author = 'Charles Dickens'
  book.published_year = 1859
end

9位 first_or_initialize

このレコードをまだ保存したくない場合は、 first_or_initialize が使える。

Book.where(:title => 'Tale of Two Cities').first_or_initialize

8位 scoped

あるクラスの持つすべてのレコードを表した ActiveRecord::Relation がほしいことがある。そんなときは scoped メソッドを使えば簡単に生成できる。(訳注: Rails 4 では、 scoped が非推奨になり、 all が Array から ActiveRecord::Relation のオブジェクトを返すようになりました。Rails 4 では scoped から all に変更してください。)

def search(query)
  if query.blank?
    scoped
  else
    q = "%#{query}%"
    where("title like ? or author like ?", q, q)
  end
end

7位 none ( Rails 4 のみ)

同じように、オブジェクトを含まない ActiveRecord::Relation がほしいことがある。空の Array を返すことが、大抵それほどよくないのは、 API の利用者が Relation オブジェクトを期待しているからだ。代わりに none を使えばいい。

def filter(filter_name)
  case filter_name
  when :all
    scoped
  when :published
    where(:published => true)
  when :unpublished
    where(:published => false)
  else
    none
  end
end

注意:最先端を行く人は今すぐ none を使いたくなっていることだと思う。これは、 Rails 3 ではなく、 Rails 4 で利用できる。だが、Rails 4 を待つまでの間も簡単に書くことができる。 この Stack Overflow のスレッドをチェックしてほしい。

6位 find_each

数千レコードをイレテートさせたくなっ場合、each を使いたくはないだろう。

each は1 つのクエリを実行して、全レコードを取得し、それらすべてをメモリ上にインスタンス化してしまう。メモリを十分に確保しているならいい。確保してなければ、これは Rails アプリをフリーズさせる素敵な方法になる。find_each は、そうではなく、レコードをバッチ処理で find して(デフォルトは1000件)、一度に yield する。その結果、同時に全レコード分のメモリを確保する必要がなくなる。

find_each は yield されるレコードの順序を指定できないので注意だ。指定してもただ単に無視される。

Book.where(:published => true).find_each do |book|
  puts "Do something with #{book.title} here!"
end

5位 to_sql と explain

ActiveRecord は素晴らしいが、思った通りのクエリをいつも生成してくれるとは限らない。コンソールに飛んで、組み立てた Relation で この 2 つの命令を実行してみよう。賢いクエリにマップされているか確認して、そうなってなかったら愛情込めて作ったインデックスを使うようにしよう。

Library.joins(:book).to_sql
# => SQL query for you database.
Libray.joins(:book).explain
# => Database explain for the query.

4位 find_by(Rails 4 のみ)

Rails で書いたコードは次のような行で散らかったものになりやすい。

Book.where(:title => 'Three Day Road', :author => 'Joseph Boyden').first

代わりに、 find_by というショートカットメソッドが使える。

Book.find_by(:title => 'Three Day Road', :author => 'Joseph Boyden')

これは上と同じものが実行される。

注意:最先端を行く人は今すぐ find_by を使いたくなっていることだと思う。これは Rails 3 ではなく、 Rails 4 で利用できる。

3位 scoping

scope メソッドを特定の Relation として使える。Rails のドキュメントにある次の例を検討してみよう。

Comment.where(:post_id => 1).scoping do
  Comment.first # SELECT * FROM comments WHERE post_id = 1
end

これはまったくもって使いやすい。

2位 pluck

特定のレコードのカラムで配列にしたいことがないだろうか?私はこういうにを本当にたくさん見てきた。

published_book_titles = Book.published.select(:title).map(&:title)

さらに悪い場合だとこうだ。

published_book_titles = Book.published.map(&:title)

代わりに pluck を使おう。

published_book_titles = Book.published.pluck(:title)

(訳注: Rails 3 では、pluck の引数に指定できるシンボルは 1 つでしたが、 Rails 4 ではシンボルの配列を指定することで、属性を複数指定することができます。select で複数の属性を指定した場合と違い、2次元配列を返します。3 系でも比較的最近のバージョンで使えるはずです。)

1位 merge

僕はこの宝石なしには生きられない。しかし奇妙なことに、これはソース中にドキュメントされていないし、今まで見たガイドでも言及がない。これを使うと、結合( JOIN )ができて、結合されたモデルに対して名前付きスコープでフィルタできる。(訳注: 私見ですが、4.0.0 では merge が意図と違う動作をしないかよく確認した方がよいと思います。*1 いくつか修正が入っている4.0.1 以降でも試してみてください。)

class Account < ActiveRecord::Base
  # ...

  # Returns all the accounts that have unread messages.
  def self.with_unread_messages
    joins(:messages).merge( Message.unread )
  end
end

2012-05-16(水)

[][][]なぜ私たちは NodeJS から Ruby on Rails に移行したのか

以下の文章は Targeter App Blog の記事を翻訳したものです。原文は 2012年5月12日 に書かれました。


Why we moved from NodeJS to RoR

http://blog.targeterapp.com/post/22984987832/why-we-moved-from-nodejs-to-ror

免責事項:この記事は NodeJS や Ruby on Rails について騒ぎ立てるものではありません。ただ私たちの決定とその理由について振り返るものです。両フレームワークはそれぞれが作られた目的において素晴らしいものであり、そのことは、私たちのスタックの一部がいまだ NodeJS で動いている理由でもあります。

私は NodeJS のすごいファンで、これは非常にエキサイティングな技術だと信じていて、これらの人気が出る様を目にするだろうと思う。私はとても賞賛しているが、それにもかかわらず、私たちは Targeter App を NodeJS から Ruby on Rails に移行した。

私たちが当初 NodeJS でアプリを書いた理由というのはいたって単純だ。アプリをすぐ出すのに使えるライブラリがあったということと(Startup Weekend で使える時間は 54 時間だった)、Ruby に比べると、 JavaScript の方がコーディングする機会が多かったということだ。私たちのスタックは MongoDB を含んでいて、JS 環境で生かされることに意味があった。しかし、アプリが成長してくると、NodeJS がこのアプリには間違った選択だと気づいた。以下に主だった理由を挙げる。

NodeJS は数多くの短いリクエスト(short lived requests)を実行するアプリに適している。伝統的な CRUD アプリでも上手く動作はするが、理想的なツールというわけではない。PHP、Ruby、Pythonにもフレームワークがあり、そういった用途のアプリには十分磨き抜かれ、成熟している。NodeJSがすべて非同期(async everything)であるということは CRUD アプリでは効果がない。人気のフレームワークは、とても良いキャッシュや、アプリに必要なものをすべて備えていて、同期処理であっても十分に上手く動作する。

NodeJS はとても若いフレームワークで、パッケージ周りは未成熟だ。このことで多くの優れたパッケージを生み出してきた素晴らしいコントリビュータを攻撃するつもりはまったくない。しかし、ほとんどのパッケージはまだ成長段階だし、NodeJSの急速な開発は、新しいバージョンになる度にたくさんの変更があるということを意味する。つまり、最先端の技術を使うには、最新バージョンに出来るだけ早く更新しなければならない。これはスタートアップには多くの問題となる。

さらなる理由として、テスティングがある。NodeJS のテスティングフレームワークは良いが、Django や RoR といったプラットフォームで利用できるものには敵わない。1日に数十のコミットがあってそれらすべてを1、2日中に使えるようにしなきゃならないときに重要になってくるのが、何も壊れていないと保証することで、それができなければ、苦労して獲得したアーリー・アドプターを失うことになる。ささいなバグを直すのに丸一日を費やしたい人はいない。

最後に、私たちは、すべてをキャッシュすることが必要で、それをできるだけ早く終わらせる必要があった。アプリが成長して秒間数千ヒットになったが、洪水のようなリクエストを経験することはなかった。チャットアプリじゃないんだ! 最大でもメインアプリは 1000 RPS で、それぐらいは、RoR と Nginx を使えば容易に対応できる。

さて、ここまで読んでいる人は、私たちがどこで NodeJS を使っているか死ぬほど訊きたいのだと思う。説明しよう。私たちのアプリは 2 つの部分で構成されている。1つはユーザが見るユーザインターフェースで、もう一つはレポートを管理する部分だ。後者は NodeJS を使うのに完璧なシナリオだ。たくさんの短いリクエストがある。この部分は、多くのものをプッシュしているときでもレスポンスをできるだけ速く終わらせる。リクエストがオープンになっている間はブラウザがそれの終了待ちになり、ユーザ・エクスペリエンスを損なってしまうので、これは重要なことだ。NodeJSがすべて非同期だということが私たちを救ってくれた。データは DB に書き込まれたり、ガシガシ処理されたりする一方で、リクエストは終了し、ブラウザはより重要なことを続行できる。

私たちが従事しているプロジェクトは Targeter App で、私たちのアプリの更新を twitter や ニューズレターにサインアップすると受けとることができる。

PS: ここに NodeJS をどこで使うべきか、また、上司を説得して使わせる方法についての優れたガイドがある。

http://nodeguide.com/convincing_the_boss.html

yuku_tyuku_t 2012/05/17 19:30 piece of cake = 楽勝
みたいな意味なので、RoRとNginxの構成で問題ない、とかがいいんじゃないでしょうか。
> RoRとNginxでいただくケーキみたいなものだ

suginoysuginoy 2012/05/17 22:13 修正しました。たしかに慣用句でしたね。ご指摘ありがとうございます。