今週は “先を行くこと” (”Living on the Edge”) がお休みですが、Rails のコミュニティーは相変わらずなので、情報をお待ちの皆様を暇にさせることはありません。
ライアン・ディーグル (”Ryan Daigle”) が、開発版のいくつかの変更をフォローしており、それらについての素晴らしい解説をいくつか投稿してくれました。
- ActiveSupport::Memoizable を利用した手軽なメモ化 (”Memoization”)
- ネストされたモデルの一括割り当て
- メタクラス・アクセサー (通称: 固有クラス “eigenclass”)
それらよりも特筆すべきなのは、国際化サポート (I18n: “Internationalization”) が Rails のコアに導入されたことかもしれません。スヴェン・フュッフス (”Sven Fuchs”) が、国際化の技術的な詳細と API および、Rails と国際化の歴史について説明しています。国際化サポートは、Rails 2.2 の公開に合わせて完全に安定化させられる予定です。国際化に興味のある方は、Google グループでアイディアやフィードバック、パッチ等を提供してみてはいかがでしょうか。
Filed under: Ruby, ソフトウェア開発, 翻訳, 読み物 | 1 Comment
Outpost で Basecamp が iPhone 対応に
先週末は、ソフトバンクから発売されたアップルの携帯電話というかスマートフォン iPhone (”アイ・フォーン”) が、メディアをにぎわせていました。
そんな iPhone に、Ruby on Rails が生まれたきっかけとなったプロジェクト管理ツール Basecamp を利用する為のアプリケーション、Outpost が8月に提供される様です。
Filed under: iPhone, ウェブ, ソフトウェア, ツール | 0 Comments
ここのところ開発版 Rails ではさほど大きな変更や機能追加が無かったので、かなり短くなっています。この記事で触れられていない小規模な変更などについては Rails commit logs の方を参照してください。ActionPack のリファクタリングやマルチスレッド化、ActiveModel などもありますが、まだまだ開発途中で、それほど具体的でないので省略します。
要望や批判がありましたら、いつもの様にコメント欄にお願いします。
script/server が Thin に対応
script/server が Thin が使用可能かチェックし、可能であれば使用する様になりました。開発環境で Thin を使用している場合でも、運用環境で Thin を使用している場合でも便利な機能でしょう。Thin を使用する場合は、environment.rb に config.gem ‘thin’ を追加する必要があります。
この機能のパッチは fluxin の人達が提供してくれました。
String#humanize が語形変化 (”Inflection”) でカスタマイズ可能に
中核拡張 (”Core Extension”) の String#humanize が、テーブル項目の様なアンダーバー付き文字列を読みやすくするのに使われる様になりました。例えば以下の様になります。
"actor_salary".humanize => "Actor salary" "anime_id".humanize => "Anime"
レガシーな項目名を設定していたり、出演者の報酬 (”Actor salary”) という項目に “act_sal_money” といった様な「非人間的」な名前を使っている場合は、“Act Sal Money” が返されてしまい、あまりうまく機能しません。
この語形変化は、単数形、複数形、例外、不可算などと同じように、語形変化法則を指定することでカスタマイズできます。
Inflector.inflections do |inflect| inflect.human /_cnt%/, '\1_count' inflect.human 'act_as_money', 'Actor salary' end
正規表現を使って “click_cnt” を “Click count” できる点は気に留めておきたいところです。
このパッチを提供してくれた ダン・マンジェス (”Dan Manges”) と パスカル・エラート (”Pascal Ehlert”) に感謝。
ハッシュを使って複数テーブルにまたがる条件を設定可能に
ネイクさん (”Pratik Naik”) が、結合 (”JOIN”) されたテーブルにハッシュでそれぞれ条件を設定できる、小規模ながら便利な ActiveRecord の機能を提供してくれました。説明より以下の例を見た方がわかりやすいでしょう。
Anime.all(
:joins => :character,
:conditions => {
:active => true,
:characters => { :gender => 'female' }
}
}
この ActiveRecord クエリーは、アクティブに設定され、キャラクターが女性 (”female”) のすべてのアニメを返します。
あとがき
今回は以上です。小規模な修正や変更でも、もっと紹介して欲しいものがあれば、是非教えてください。
きょうのはま
湿度にやられています。
Filed under: Ruby, ソフトウェア開発, 翻訳, 読み物, 開発版 Rails "edge" | 0 Comments
だめプログラマー症候群 (1): だめなプログラマー
プログラムが理解できない
プログラムを理解するということは、プログラムに必要な機能を把握でき、実際のプログラムがどの様に実行されるのかを頭の中でイメージできるということです。
症状
- おまじないとしか言えない命令があったり、必要な機能とは無関係の命令がある。
- 念のためといって、save() 関数などを2, 3回呼び出す。
- バグがある関数を直す際、その関数の出力を操作して直す。
- いちいち別の型にキャストして変数の操作を行う。例えば、小数を文字列にして、文字列分割で整数部を取り出し、整数にキャストしたりする。
- 再利用性を考えずに、既存のプログラムを無駄にサブルーチン化する。
処置
この様なプログラマーは、開発環境のデバッガーを利用して一行ずつステップインし、プログラムを理解する訓練が必要です。例えば Visual Studio なら、プログラムの初めの方にブレークポイントを設定させ、F11 を使って一つ一つ丁寧にステップインさせ、プログラムが一体何を行っているのか理解できる様になるまで、変数の内容の変化を理解させると良いでしょう。万が一ステップインといった機能の無い環境でプログラミングをしている場合は、すぐに他の環境で訓練させるべきでしょう。
プログラミングパラダイムを理解できない
プログラミングパラダイムとはプログラムの見方を与えるものです。例えば、オブジェクト指向は近代のプログラミングパラダイムの代表的な例です。他には関数型や手続き型、宣言型や命令型といったパラダイムがあります。アセンブラや GOTO を使用する言語と、それらのパラダイムが大きく違うことは明確ですが、個々のパラダイムもそれぞれ大きく違います。また、普及している近代的なプログラミング言語の多くがオブジェクト指向を取り入れていますが、オブジェクト指向でも個々の言語で、リスト内包表記 (”List Comprehensions”) や、総称型 (”Generics”)、ダックタイピング (”Duck-typing”) といった独自の拡張がなされています。
症状
- 禁じ手を使ってパラダイムから抜け出し、残りのプログラムを命令型や手続き型のプログラミングを行う。
- オブジェクト指向において、非スタティックな関数をインスタンス化していないクラス自身から呼び出そうしてコンパイルエラーを起こすが、なぜエラーになるのかわからない。クラスとインスタンスの概念を理解していない。
- オブジェクト指向において、あるクラスのオブジェクトを操作する為のメソッドを “xxxxxManager” といったクラスを定義してしまい、肝心のオブジェクトには何も定義しない。
- リレーショナルデータベースに、データベースネイティブな値で保存せずに、不用意にシリアル化したオブジェクトを保存する。
- 関数型プログラミングにおいて、同じアルゴリズムの関数を引数の違いの為に何個も実装してしまう。
- 決定的関数 (”Deterministic Functions”) の結果を自前でキャッシュする。
- 純粋な関数型プログラミングにおいて、入出力やモナドの実装になると、他のプログラムからコピペをする。
- 宣言型プログラミングにおいて、複数の値をデータバインドで設定せずに、一つ一つ命令を使って設定する。
処置
教育を受けていないことが原因でこの様な症状が出ている場合は、適切な教育を受けさせるか、実際のプログラミングを通じて学ばせると良いでしょう。実際のプログラミングを通じて新しいパラダイムを身につけさせるには、プロジェクトに参加させるなどして、とにかく本人をそのパラダイムに集中させる他ありません。また、パラダイムの特徴を理解できるまでは、簡単な言葉で順を追って理解できる様にすると良いでしょう。
オブジェクト指向の例
- オブジェクト指向は、レコードとメソッドの集まりである。
- メソッドは、独自のグローバル変数を持つ細分化されたプログラム中の関数にすぎない。
- それらのグローバル変数はフィールドと呼ばれ、必要であれば外部から隠すことができる。
- プライベート宣言とパブリック宣言の目的は、外部からプログラムの実装を隠し、実装を意識しないで外部から利用できる様にするインターフェースを提供することである。これをカプセル化と呼ぶ。
- カプセル化の結果、ビジネスロジックがプログラムの実装に影響されなくなる。
最後のカプセル化の結果は、ほとんどのオブジェクト指向言語で共通しています。オブジェクト指向の主たる目的は、プログラマーがある機能を利用する際に、その機能の実装を意識しないで済む様にすることだからです。
関数型プログラミングの例
- 関数型プログラミングは、複数の決定的関数を組み合わせである。
- もし関数が決定的な場合、結果が必要になるまで実行される必要は無く、必要な回数だけ実行すれば良い。これらは、消極的評価 (”Lazy Evaluation”) と、部分評価 (”Partial Evaluation”) と呼ばれる。
- 消極的評価と部分評価を利用するためには、渡されたひとつの引数をどの様に変更するか、どう他の関数に渡すべきなのかを関数で定義しなければならない。これをカリー化 (”Currying”) と呼ぶ。
- 関数がカリー化された場合、コンパイラーは制約解決 (”Constraint Solver”) を通じて最適なプログラム実行方法を選ぶことができる。
- 制約解決に通すことで、どう引数を渡してもらうかではなく、どんな引数が欲しいかを記述することに集中できる。
調べことができない・慢性的にプラットフォームを知らない
近代的なプログラミング言語やフレームワークは、非常に幅が広くかつ深い命令と機能が提供されており、先進的なフレームワークである Java や、.NET、Cocoa では、才能のあるプログラマーでも学ぶのに最低でも一年はかかります。才能のあるプログラマーは、事前に必要な命令を探してからプログラミングを始め、特に優れたプログラマーは、目標を達成するために必要なプロセスを細分化し、既存のフレームワークやデザインパターン、さらにモデルやプログラミング言語を選び、実際にプログラミングを始めます。
症状
そのプラットフォームで長くプログラミングをしているにも関わらずこれらの症状が現れた場合、プラットフォームの習得が遅すぎることを意味しています。
- イベントやハンドラー、正規表現など、フレームワークで提供されている機能を再実装する。
- フレームワークで提供されているクラスを再実装する。タイマー、コレクション、ソートや検索アルゴリズムなど。
- 掲示板で教えて君をする。
- 簡単に済ませられる機能をやたらと遠回りなプログラムで実装する。小数を文字列に変換してまるめた後に、再度小数に戻したりなど。
- 同じ機能でもより良い新しい実装方法があるのにも関わらず、既存の古い方法で実装する。例えば、ラムダを使わず名前付きデリゲート関数を未だに書いているなど。
- 自分の知っているレベルでの「心地の良い」プログラミングに執着し、複雑な問題を単純な機能を使って非常に長いプログラムで解決する。
処置
空き時間が無ければこの様なプラットフォームの知識はなかなか身に付かないし、現場ではとにかく実装することを急ぐのでなおさら身につきません。根本的な解決にはなりませんが、手元に便利なプラットフォームのリファレンスを置かせ、できる限り短時間で全体を把握できるようにすべきです。本でもいいですし、2画面にして片方に PDF や、ウェブサイトを開くのでもいいでしょう。リファレンスに目を通す癖を付けさせる為に、まずは既存のプログラムを 10:1 以上に縮めさると効果的です。
ポインターを理解できない
ポインターを理解していないプログラマーは、複雑なデータ構造や効率的な API の設計ができず、限られた種類のプログラムしか書けないでしょう。マネージド言語では、ポインター演算を無くし、一方で自動開放などを追加した参照という機能が替わりに提供されていますが、これもポインターの概念が理解できなければ、値渡しや参照渡しの違いが理解できず、酷いデータ構造やバグを生み出してしまいます。
症状
- 連結リストの実装ができない。連結リストで項目を追加、削除してもデータが失われない様に実装できない。
- 連結リストなどの動的なデータ構造を使わず、不定量の大きな配列を割り当て、配列の長さを別の変数でカウントする。
- ポインター演算によって起きているバグを見つけられない、修正できない。
- ポインターの参照している値が関数外から変更される可能性を意識しない。
- ポインターを複製した後に、参照が解放された元のポインターから値を変更しようとする。
- ポインター自身をシリアル化して保存しようとする。
- ポインターの配列をポインター自身の比較でソートする。
山岡さんはホテルのどこかの部屋に泊まっています。どの部屋かはわかりません。しかし、友達の林さんの部屋はわかるので、そこまでいって山岡さんがどの部屋に泊まっているのか聞きました。すると、林さんは、どこに山岡さんがいるのかわからない様でしたが、山岡さんの別の友達である北島さんの部屋を教えてくれました。そこで北島さんの部屋に行き、山岡さんの部屋を教えてもらい、結果、山岡さんの部屋に行き、山岡さん自身に会うことができました。
ポインターは様々な比喩を用いて説明することができ、データ構造は様々な類推を用いて説明することができます。上の例は連結リストの例で、プログラマーでなくとも思いつくデータ構造です。この様なポインターの説明は、理解できないものではありません。それでもなぜポインターを理解できない人がいるのかというと、コンピューターのメモリー内で一体何が起きているのかを理解する際に、よく似ている変数の概念と絡まってしまい混乱するからです。ポインターの概念が正確に理解できイメージできる様になるまでは、プログラムの内容をわかりやすい他の話にたとえるのがいいでしょう。
再帰関数の処理を把握できない
再帰関数の概念は簡単に理解できますが、処理結果がイメージできなかったり、複雑な計算を単純な再帰関数で実装できるのに気がつかないことがあります。再帰の条件式を書く際にそうなってしまうと、非常にやっかいです。
症状
- 再帰関数で簡単に処理できるにも関わらず、非常に複雑な反復処理を行う。
- 再帰条件を、処理開始時と処理終了時に確認させる。
- 再帰条件を確認しない関数を書く。
- 末尾再帰 (”Tail recursion”) を使うべきところで、グローバル変数や持ち越される変数に再帰処理をまとめる。
- 再帰関数の引数に何を渡して良いのかわからない。引数を操作しない再帰関数に何を渡して良いのかわからない。
まずは一つの条件と、同じ渡された引数を操作しない一つの再帰関数を書かせましょう。何かふに落ちていない様子でも、そこでやめさせ、実際に実行させましょう。スタックオーバーフローが起きるはずですから、プログラムに戻らせ、渡された引数を操作して再帰関数に渡す様に変更させましょう。それでも、スタックオーバーフローや、永遠と出力が続く様であれば、再帰条件を書き換えるなど、適切な結果が出力されるまであれこれ実験させましょう。二つ以上の条件を持つ再帰関数は、完全に理解できるまでは書かせるべきではありません。
目的は、再帰関数を扱うだけの自信を持たせることにあります。再帰処理内で、今どこにいるのかが正確にわからなくてもいいのです。自信が付き、実際に現場で実装する時が来たら、まずは単体テストを書かせ、同じような試行錯誤を繰り返させればいいのです。
きょうのはま
耳が痛いです。
Filed under: ソフトウェア開発, 翻訳, 読み物 | 0 Comments
6月25日付け: 開発版 Rails の変更点 “先を行くこと” (”Living on the Edge”) その2: パフォーマンス改善 — Ruby on Rails 公式ブログより
最初の “先を行くこと” では API の変更について扱いましたが、前回も述べたとおり今回はパフォーマンス改善について扱おうと思います。
では、早速。
高速になった ERB テンプレート
ジェーミー・キャンパー (”Jeremy Kemper”) が ERB の処理を、特にヘルパーメソッド concat と capture を効率化してくれました。また「特別な」ERB である _erbout は、インスタンス変数に置き換えられ、以下の様な結果が生まれました。
- バインディングがあちこちにコピーされなくなった結果、(メモリー)パフォーマンスの改善
- 一般的に重い処理が多い eval メソッドの使用回数の減少
- 文字列バッファーをスワップできるので、_erbout を切り出す必要が無くなった
- output_beffer で文字列バッファーを読み書きでき、必要に応じてオーバーライド可能になった
関連する変更セットは 993697a obdb7d3 4d4c8e2 です。
部分テンプレートと JavaScript ヘルパーの高速化
キャンパーさんによって、部分テンプレートと JavaScript ヘルパーの初期化にリファクタリングが施され、処理速度と処理効率が最適化されました。これらは、キャンパーさんが最近コミットした最適化のほんの一部でしかありません。詳細は Rails へのコミットをご覧ください。他の高品質なオープンソースプロジェクトからも学べる様に、これらのコミットからも学ぶことがたくさんあります。
RecordIdentifier メソッドの高速化
RecordIdentifier が「メモ化機能」(”Memo-ization”) の単純な利用により、語形変化 (”Inflection”) が少なくなる等して高速化されました。RecordIdentifier は、ActiveRecord モデルの ID を気にせず一意に認識する為に使われることが多い他、キャッシュキーや、部分テンプレート等でも使われています。
キャンパーさんによる関連する変更セットは c1a9820 566d717 です。
キャッシュの消極的読み込み (”Lazy-loading”)
お知らせ: この変更は、後ほどの変更 6573f6a で元に戻されました。
ActiveSupport::Cache モジュールに含まれるいくつかのキャッシュストアが、消極的読み込みを行う様になりました。実際に使い始めた時にのみ、“require” メソッドで読み込まれることを意味します。
きょうのはま
先日受けた英検一級の一次試験に通過していました。受験時に語彙問題だけずいぶん難しいと思ったのですが、案の定、語彙問題の得点が一番悪かったです。
Filed under: Ruby, ソフトウェア開発, ドキュメント, 翻訳, 開発版 Rails "edge" | 0 Comments




