vim で実践! コードリファクタリング

このエントリーをはてなブックマークに追加
どうも、技術部でプログラマをしている鈴木です。シャノンに来てからは主に Shanon Marketing Platform の国際化対応をやっています。

わたくし、いわゆるひとつの vi 使いでして、世の vi 使いの類にもれず、世の中のすべてのアプリケーションの UI が vi ライクになればいいと常日頃思っているクチなのですが、(この記事も、vi で書いてからコピペであります。WYSIWYG なんてクソくらえ! でありますw)今日は恥ずかしながら、そんなわたくしが普段どんな感じで vi を使っているかをお見せしたいと思います。
そして、どうやら今回の記事の一人称は「わたくし」らしいです。

そもそも vi とはいかなるエディタであるか。なぜ vi でリファクタなのか。



ファイル:Vimlogo.svg


vi は現在も現役でメインエディタとして使われているエディタのうちで最古参のもののひとつですが、その特異な UI のために、世間では最も敷居の高い、プログラマ向け、あるいは玄人向けのシロモノとみなされているエディタです。もちろん、さすがのわたくしも実際に使っているのは、(あの何にもできない)純粋な vi ではなくて、その巨大な拡張であるところの vim なのでありますが。
それはさておき、vi (vim) のエディタとしての主な性質ですが、これもいろいろなところよく言われておりますが(主にクローズドな vi 使いたちのコミュニティにて、なのですが)、私見も含めて再度書きだしてみることにしましょう。若干、めんどくさーい印象になってしまうのは、ご勘弁のほどを。どうしても、vi について語ろうとするとイデオロギー臭がしてしまうのです。

vi はそのコンセプトからして純粋で先鋭的な「エディタ」である。それはテキストを書く (write) のではなく、編集する (edit) 。

標準的なエディタは、通常ユーザの目の前にある巨大なキーボードのスペースを、ただ次の空白に個々の文字を追加するためだけにしか解放していません。けれども、実際のテキストファイルの編集作業において、新しく文字を打つ、という操作は全体の操作の何%を占めているでしょうか?実際には操作の少なくとも数割は、時間的にも操作量的にも、書き換える場所を探したり、体裁を整えるための微調整であったりするのではないでしょうか?
標準的なエディタが提供しているインターフェースは、この作業全体のうちで大きなウェイトを占めている、1. 移動すること、2. 検索すること、3. 置換すること、4. 微調整すること、等々の操作に対して、ひじょうに貧しく、また周辺的なインターフェースしか提供していません。それはまるで、お前はただどんどん書きつぐだけであり、それだけしていればよく、お前がはじめから完璧に書いてさえいれば、削ることやつけ足すこと、あとから記述を探すことなどは、しなくてもいいはずのことなのだ、と言わんばかりです。
ですが、自然言語による一般的な文章ならばまだしも、プログラミングにおいては、新しい記述(==プログラム)を一から書き下ろすことはまずありません。普通は、すでにあるコードに、新しいものを書き足したり、構成を変えたり、削除したりするわけです。極端なハナシ、ある作業中に新しい単語をひとつも書き加えることなしに、すべて検索と置換、コピペで、作業が済んでしまうこともあるでしょう。そして、それは作業の精度といった観点からはむしろ望ましい作業法でさえあるのです。なぜなら、新しく書いたものには必ずといっていいほど typo がありますからね。あるいは、まったく新しい機能、新しいアプリケーションを新規に書き起こすときでさえ、自分または他人の書いたモックアップや既存のアプリケーションのコードをベースにするのが普通ですし、今回お話しするリファクタリングにおいては、むしろこの削ることこそが重要でさえあったりするわけです。
そうしたわけで、とりわけプログラミングにおいては、標準的なエディタを使用していると、キーボードのホームポジションに手が置かれていることはまれで、多くの場合は、右下あたりにあるカーソルキーや、F キー、Ctrl や Shift を叩いていることのほうが多くなってしまいがちです。それどころか、キーボードよりもマウスを握っている時間のほうが長いかも知れません!
けれども、vi は違います。vi でテキストを編集しているかぎり、マウスは触りません(もし vi を使っている最中にマウスに触ったら、それは何かに敗北している瞬間です!)。また、よく比較される emacs のように Ctrl キーの位置がきわめて重要になるということもありません。ほとんどの操作(「すべて」ではありません。UI の設計、それはバランスの問題です)は、ホームポジション上で完結します。新しい行をつけ加えるのも、テキストの上のほうに戻って何を書いたか確認するのも、文字を削除することさえ、Delete キーや BackSpace キーにちょっと指が出張することなしに、ホームポジションで触れる範囲内で操作可能なのです。
こうしたことがなぜ可能であるかといえば、vi のインターフェースはテキストを書くことではなく、テキストを編集するために設計されているためなのです。カーソルを移動する操作(有名なホームポジション時の右手を使う hjkl でありますが)ことは、新しい文を追加する(i や a それから o など)操作と、まったく同列の、同じだけ重要な操作だとみなされています。検索(/)や、コピー(y)、削除 (d や x)、置換 (c) などの操作についても同様です。テキストを新しく打ち込む必要があるのは、その必要のある操作をしたときだけなのです。
と、ちょっと長くなってしまいましたが、わたくしにとって vi というのは、そのプログラムというよりも、このインターフェースであり、そのコンセプトなのでありますし、多くの人にとっても、vi をそのプログラム実体(/usr/bin/vi にあり、それは /usr/bin/vim へのシンボリックリンクであることでしょう)以外をさしている場合は、そのインターフェースを指していることが多いと思います。

「テキスト編集ツール」である vi を使って、リファクタすること。


テキストを編集することに特化したツールである vi は、その本来的な性質としてリファクタリング作業に向いたツールです。特別な拡張機能を使わなくても、いくつか標準の操作を用いるだけで、さくさくと、またミスのリスク(つまり、デグレですが)なく、リファクタリング作業をすることができます。まあ、もちろんゼロではないわけですが、それはリーズナブルな、コントロール可能なものであることでしょう。
ところで、リファクタリング作業の実際とは、いったいどのようなものでしょうか? わたくしが普段行なっている作業は、だいたい以下のようなものです。
  • 冗長な変数、冗長な処理を除去する。
  • コメントを追加する。
  • warning を除去する。
  • インデントやコーディングスタイルなど、体裁を整えて読みやすくする。
  • そのフレームワークの標準的なコーディングスタイルに合わせる。
  • 二箇所以上に記述された同じ処理をメソッド化してひとつにまとめる。
  • 使いやすいようにメソッドのインターフェースを整理して、より汎用的なものにする。
  • 複数のクラスから、特定の要素を抽出して、別のクラスにまとめる。
  • 定数や変数をメソッド呼び出しに置換する。
  • コアな処理を高速化する。
これらの作業のうち、実際に新しいコードを打ち込む必要があるのは、どれくらいでしょうか? ヘタをすると、コメントを補う、という部分だけだったりします。vi なら、その他の大部分の作業をホームポジションからのキーボード操作で行うことができるわけです。
ようするに vi を使ってコードを書くと、どうしてもきれいなコードを書かざるをえないように仕向けられる、ということがあるわけです。なぜなら、vi を使っているとそっちのほうが作業量が少なく、またスマートなのです。


実際に vi でリファクタリングをしてみよう。

さて、実際にそれでは普段、わたくしがやっているリファクタリング向けの vi の操作を列挙してみましょう。

ちなみに、特別な vi プラグインは使っていません。すべて、標準の vim でサポートされている機能です。できれば最新の vim (7.x) がよいですが、たぶん 4.x 以上ならだいたいの操作はできると思います。(そのときからわたくしのやっている作業は大して変わらないのであります)
また、ここであげる例と同じくらいのレベルまでの vim のテクニックについては、以下がよくまとまっています。
超基本操作と、このくらいまで覚えて手になじませれば、実作業で困ることはほとんどないはずです。

単語補完を使う。



insert モード中で、"jQuery" という単語を、補完を使って入力しています。なんだか、補完しないでタイプしたほうが速そうだというのは、言ってはいけません。補完は typo のリスクが小さくなるので、総合的にみれば速いのであります。
最初の if 文のほうは、j まで打ったところで、Ctrl+N で候補リストを表示しています。補完候補は、Ctrl+N と Ctrl+P でくるくる選択します。(候補がリスト表示されるのは、たしか 7.x から)決定する場合は Enter や、次の入力を始めれば確定します。二度目の alert のメッセージのほうは、一度目の候補が多かったので、jQ まで打ってから Ctrl+N しています。
ちなみに、補完候補は、そのとき開いているファイル中に存在する全単語です。tags ファイルが読み込んでいれば、そこからも取り込まれるので、ctags などを使って用意しておくとよいでしょう。取り込む tags ファイルは :set tags で指定できますよ。

使っているキー操作は以下になります。
カーソル移動h/j/k/l
挿入i
補完Ctrl+N/Ctrl+P (insert mode)
insert モードを抜けるCtrl+[ (insert mode)

上の行と同じ入力をする。



コードを書いていると、前後の行とほぼ同じ行を書くことがよくありますが、この場合に、いちいちタイプしていくのは、面倒なものです。(typo のリスクもありますし)
この入力を省力化する方法の標準的なものは、前後の行をコピペして、差異のある箇所だけ書きなおす、というものだと思います。(eclipse などの IDE なら、全部補完してくれるから、普通に書いたほうが速いという意見もありそうですが)
vi では、行のコピペの他に、便利な入力補完機能が用意されています。insert モード中で、Ctrl+Y/Ctrl+E を押しつづけます。
ちなみに、insert モード中の一文字削除は Ctrl+H です。

使っているキー操作は以下になります。
カーソル移動h/j/k/l
下に一行追加o
上/下の行をなぞるCtrl+Y/Ctrl+E (insert mode)
一文字削除Ctrl+H (insert mode)
insert モードを抜けるCtrl+[ (insert mode)

前後の行を入れ替えて見栄えをよくする。コードブロックを整理する。



リファクタリングの第一歩は、何はともあれ動きを変えずにコードの見栄えだけを整えて、読みやすいコードに整頓するところからです。
というわけで、雑然と並んでいるわたくしの vimrc の set 文を、値をセットしているものと、フラグのものとをより分けることにしましょう。つまり、= がついている行とそうでない行とを並べ替えるわけです。
Shift+V で行選択をして d でカット。挿入する前の行で p でペーストします。これを繰り返して = の付いた行を徐々に下の方に持っていきます。集めた = つきの行を実際にどこに配置するかは、最後に決めればいいので、まずはとりあえず集めることに専念しているようです。
ちなみに、カットではなくコピーの場合は y、カーソル行の前に挿入する場合は p ではなくて、Shift+P を使います。

使っているキー操作は以下になります。
カーソル移動h/j/k/l
行選択Shift+V
切り取りd
貼りつけp

複数行の同じ列に同じ単語を挿入する。



vimrc のオプションを = で値をセットするものとフラグとにより分けたので、フラグの設定を一括で設定してみましょう。Ctrl+V で列選択をして、Shift+I。すべてのフラグに no (設定を off にするキーワード) をセットします。
変えてみると、すでに no が付いていたものがあるのが syntax coloring が外れるせいでわかります。これらを再度集めて、nono を no に戻してあげましょう。Ctrl+V で選択して、d でカットです。

使っているキー操作は以下になります。
カーソル移動h/j/k/l
次/前の単語に移動Shift+W/Shift+B
列選択Ctrl+V
列選択の前に挿入Shift+I
列選択部をカットd
行選択Shift+V
行切り取りd
行貼りつけp

複数行の処理をまとめてコメントアウトする。昔の処理をコメントアウトしてとっておく。



ここまで、上の二つの例、行の入れ替えと列編集をやってみると、単純にみえるこの設定部にもいろいろデリケートな性質があることがわかってきました。vimrc は git などで管理しているわけでもないので、うかつな変更はあとでイタイ目を見るかも知れんという気がしてきたので、にわかにバックアップが欲しくなりました。
そういうときは、まあ、ファイル全体をバックアップしておけばよいのですが、そこまででもない気もします。それから、ファイル単位のバックアップは、部分的にもとの状態に戻したい場合に、何かと面倒だったりします。
かくして、ちょっとコメントアウトしてとっておく、という方式がよく採用されることにんあるわけですが、vim なら、そうした作業もサクサクできます(もっとも他のエディタもたぶんそうでしょうけどね)。個人的には、vim の無制限の undo という性質をうまく利用する方法をよく使います。これなら、編集開始時の状態だけではなくて、ある程度確定した状態のコードを取り分けておくこともできるので、とても便利です。
例では、とりあえず undo で、編集開始時の状態にまで戻して (u)、取っておく部分を、コピー領域(バッファ)に保存(Shift+V と y)、redo (Ctrl+R) で、最新の作業状態にまで戻ってきてから、適当なところにペーストして、コメントアウトします。
これも、行選択や列選択と undo/redo を組み合わせただけです。特別な操作はまったくやっていません。

使っているキー操作は以下になります。
カーソル移動h/j/k/l
undou
redoCtrl+R
列選択Ctrl+V
列選択の前に挿入Shift+I
列選択部をカットd
行選択Shift+V
行切り取りd
行貼りつけp
以上が、だいたい基本的な操作です。では、実際にソースコードを読んでいって、そしてリファクタリングをしてみることにしましょう。

ソースファイルをざっと読む。



あたりまえのことではありますが、まだ読んだことのないコードをはじめて開いたときは、まずはそのソースコード全体をざっと眺めるのがよいと思います。
何行あるのか、どの範囲の機能が含まれているのか、どういったスタイルで書かれているのか、メソッドやプロパティにはどんなものがあるのか、そうしたことをざっと調べてから、目的の作業にとりかかったほうがよいでしょう。わたくし個人としては、コメントや書き方も含めてソースコードだと思っているので、何か分析的な手法を用いる前に、何はともあれ、そのファイルの全体のニュアンスを知っておくこと、また知ろうとすることは無駄では無いと思っております。
というわけで、ざっとファイルの中身をみましょう。vim には、たくさんのジャンプコマンドがありますが、わたくしはあまりいろいろ使いません。頁単位のジャンプ、ファイルの先頭と末尾へのジャンプくらいです。あとは、基本的に検索ベースで飛んでいくことが多いです。
例は javascript のメジャーなライブラリのひとつである jQuery のコア部分のソースコードです。core.js を開いて、Ctrl+F で1頁(=1画面)ずつみていきます(だいぶ早送りですが)。下までいったら、今度はお尻から前に戻って (Ctrl+B)、再度末尾に飛んで (Shift+G) 先頭に戻ってきています(gg)、今度はお尻から前に戻って (Ctrl+B) いっています。まあ、眺めるだけですが、それでもコードの規模や、ざっくりとした構成を把握することはできるでしょう。

使っているキー操作は以下になります。
頁移動Ctrl+F/Ctrl+B
ファイルの先頭へ移動gg
ファイルの末尾へ移動Shift+G

特定のメソッド(変数)を検索する。



ファイルの構成をぼんやりとつかんだら、次は個別にひとつずつ読んでいきましょう。これには、特定のメソッドやプロパティ、変数などをピックアップして、その周辺のコードを読み込んでいく、という場合が多いでしょう。
今回は、each という基本的なメソッドを探してみています。/each で検索して、結果をまずはひととおり眺めてみます。検索結果を辿るのは、n と Shift+N です。結果には、呼び出し側と呼び出され側の両方、それからコメントが含まれていることがわかったので、呼び出し側、つまり function の定義のほうだけ選ぶために検索キーワードを each: function に変えています。どうやら、core.js 内には、二つの each メソッドがあることがわかりました。なんでしょうか、これ。
ちなみに、カーソル部の単語検索をするには、単語の上で * を打つだけです。

使っているキー操作は以下になります。
カーソル移動h/j/k/l
検索/<キーワード>
次候補n
前候補p
カーソル直下の単語を検索*

特定のメソッド(変数)を置換する



まあ、そんな感じで、いろいろな単語で検索しながら、しばらくソースを読み込んできました。もう、そろそろいじれるかな、という気になってきたら、とりあえずいじってみましょう。手付けとしていいのは、変数名やプロパティ名、それからメソッド名を自分好みに変えてみることです。こうした変更なら、基本的に挙動に変化はないはずですから、急に壊れたりすることはない(はず)です。
ただ、ある程度一括で変える必要があるので、そのあたりをうまくケアすることが重要です。例では、error というメソッド名は個人的にはあんまり好きではないので、raise というメソッドにしてみることにしました(throw もいいんですが、これは JavaScript の予約語なのです)
これも、基本的にはソースコードを読み込んでいくときと同じく、検索がベースになります。つまり、ソースを読む作業を試しに変えてみる作業とは、シームレスに行き来するわけです。
/error で、エラーというメソッドを検索し、順番にたどりながら置換していきます。メソッド "error" は単語なので、cw で単語の書き換えをします。Ctrl+[ で insert モードから抜けたら、検索の次候補に n で飛び(前候補は p です)、直前の操作の繰り返し (.) を打ちましょう。すると、error が raise に一発で変わってくれます。あとは、この n と . の繰り返しです。
そんなの一括置換すればいいじゃん、と思うでしょう。わりと、わたくしもそう思いまする。が、この手法だと、一斉置換でやりがちな、変えてはならないところまで変えてしまう、ということを、かなり(全てではありませんが)抑制してくれますし、ひとつひとつ置換箇所を確認しながらやっていくので、変えたあとでエラーが起きたときにも、あたりがつけやすいのでお薦めです。個人的には、数百個くらいまでは、この方法でがりがり変えていっています。(五百個超えだすと、さすがになんか考え始めますが。。。)

使っているキー操作は以下になります。
カーソル移動h/j/k/l
検索/<キーワード>
次候補n
前候補p
単語置換cw
直前の操作(単語置換)の繰り返し.

このライブラリ中で呼び出される特定のメソッド(変数)を置換する。



core.js の error メソッドを raise という名前に変えましたが、変えたところで、jQuery.error() は、このファイル以外からも呼び出されるメソッドだということに気づきました。こいつはまずい、他も変えねば、ということで、複数のソースファイルの jQuery.error 呼び出しを jQuery.raise することにしましょう。core.js の変更は u でいったん破棄して、git grep で error を探します。まあ、そんなに数はなさそうなので、src 以下のすべての js の error を raise に置き換えてしまいましょう。
複数のファイルにまたがる検索は vimgrep というたいへん便利な機能があるのですが、わたくしはあんまり使っておりません。なんか設定めんどくさい。。。(いや、めんどくさないんですが)というわけで、わりと単純に grep か git grep の出力を vim の起動引数にする、という方式を用いております。
例では、error という語が含まれるファイルを git grep で検索して、-l オプションの出力結果を、vim のコマンドラインに展開します。あとは、前の例と基本的には同じです。/error で検索、cw で置換して、n と . で適用していきます。
ファイルの末尾まで行ったら、:n で次のファイルに移りましょう。前のファイルに戻ってやり直したいときには :N です。ファイルを閉じなければ、各ファイルの undo の履歴は残っているので、いつでも好きなところまで戻ってやりなおすことができます。

使っているキー操作は以下になります。
カーソル移動h/j/k/l
検索/<キーワード>
次候補n
前候補p
単語置換cw
直前の操作(単語置換)の繰り返し.
次のファイル:n
'error' という語を含むすべてのファイルを開く$ vim `git grep -l error`

ソースファイルを分割して整理する。



リファクタリングの主要な作業のひとつに、ソースファイルの統廃合があります。ファイル構成(多くの場合、それはクラス構成です)が適切でないと、大抵の開発者は、自分の付け加えたい機能をどこにおいてよいかわからず、その機能がすでに存在しているか、十分に探さずに追加してしまうので、結果として、よりソースコードが複雑化する、というすばらしいスパイラルに突入してしまうことが往々にしてあります。
そうやって書き足されて水ぶくれしたコードをメンテナンス可能な状態に維持するには、あるタイミングで整理してやる必要があります。こうしたときにも vim は標準的な操作を組み合わせることで、かなりうまくこうした仕事をやってのけることができます。
ファイルの構成を整理する場合には、二つ以上のファイルを同時に開いて作業をするのが効率的です。それも、タブなどで開くのではなく、片方にもとのファイル、もう片方に新しいファイルを並べて作業するのが理想でしょう。vim ではこうした作業のために、ウィンドウを分割することができます。普通の分割は水平分割ですが、5.x くらいから縦方向の分割が増えました。
この例では、elRTE の wiget.css から、ui-xxx というクラスを含むものを ui.css に移しています。起動引数で、widget.css と ui.css を開き、:vs で、ウィンドウを縦に分割して、左側に wiget.css を、右側に ui.css を配置します。ウィンドウ間の移動は、Ctrl+W を2回でローテーションしていくか、Ctrl+W と hjkl のいずれかで移動方向を指定して移動します。分割したウィンドウを閉じるには、ふつうに :q をすれば OK です。
例をみれば分かるように、検索語やコピペのバッファは共有しているので、あとは、これまでの例と同じく、対象に適切にジャンプ、行選択をしてカット、ウィンドウを変えてペースト、という段取りを繰り返します。

使っているキー操作は以下になります。
カーソル移動h/j/k/l
検索/<キーワード>
次候補n
前候補p
行選択Shift+V
カットd
ペーストp
ウィンドウの縦分割:vs
ウィンドウの移動Ctrl+W Ctrl+W
次のファイル:n

処理を抜き出してメソッド化する(JavaScript)



ここまでのリファクタリングは、基本的にプログラム的には挙動をまったく変えない変更ばかりでした。これだけでも、リファクタとしてはそこそこのことができると思いますが、やはり、ソースの挙動を含めて調整してこそ、リファクタリングということでありましょう。
リファクタをする際に基本となるのは、複数箇所に記述された同じ処理をうまく調整して、ひとつのメソッドの呼び出しにまとめる作業です。リファクタリングの出来の良し悪しというのは、結局のところ、このあたりのカットの適切さにあると言っても過言ではないでしょう。
リファクタ作業をしている際によく出会うケースはだいたい以下のようなものであることが多いと思います。
  • その処理のコアロジックはもうすでに書かれている(そして、動いている)。
  • だから、新たに書く必要もないし、また何も変えないほうが基本的には好ましい。
  • なぜなら、挙動が変わってしまえば、テストしなければならないし、思わぬ副作用が隠れていたりするかもしれない。
  • けれども、そのインターフェースは、そのコードの特定のコンテクストにべったり張り付いてしまっているので、使い回しがまったくきかない。
  • そのせいで、別の場所で同じことを、今度はそちらのコンテクストにべったりの書き方で書いている。
  • そんな感じの同じ処理が、ことそこの二箇所だけではなくて、そこらじゅうにある。
  • つまり、まとめてひとつにすべきだ。そうすれば、メンテナンス性が向上するし、場所によっては性能も向上するかもしれない。

こうしたケースでリファクタを行う際に重要なのは、インターフェースをいかにして維持するか、という点でしょう。中身はいくら書き換えてもかまいませんが、インターフェースが揃っていなければ、あたりまえですがプログラムは壊れてしまいます。そして、広範なソースコードを取り扱うリファクタリング作業においては、実際に動作させなくても、同じ挙動であることをどの程度保証できるか、という点が実際上、かなり重要であったりするわけです。
このようなインターフェースを維持しながら、メソッドの統廃合を行う作業も、vi は得意です。そして、それは特別な作業ではありません。これまでの作業の延長線上にあります。
例では、jQuery attributes.js の removeAttr というメソッド(これは、対象のDOM群から、指定した属性を取り除くものです)から、1 つの HTMLElement を操作する部分だけを抜き出して removeAttrOne というメソッドにしています。
メソッド化する部分を、行選択 (Shift+V) して切り出し (d)、メソッドを置くスペース(JavaScriptの場合は、メソッドはしばしばオブジェクトのプロパティのひとつです)へ移動します (p)。メソッド名をつけ、function の宣言をして、何が引数として必要か調べて記述します。貼りつけた処理のインデントを調整し(Shift+V と <<)、function を閉じます。それから、もとの処理があった部分へ戻って、宣言した function を呼び出します。
あんまりいい例でなくてすいません。jQuery のコードはストイックで、きわめてよく書かれているので、リファクタの余地が基本的にまったくないのであります。ともかく、こうやることで、とくに難しい操作なしにインターフェースを維持したまま、メソッドの切り出しができました。
が、呼び出しを書いているうちに、this は引数に含めてはいけないことに気づいて、メソッド化した部分では this を target に変更します。それから、この新しいメソッドは this (この場合は HTMLElement のインスタンスですが)のものではなく、jQuery のものだったことにも気づいて、それも修正しています。

使っているキー操作は以下になります。
カーソル移動h/j/k/l
行選択Shift+V
カットd
ペーストp
挿入i
追加a
一文字削除Ctrl+H (insert mode)
インデントを左へ<<
インデントを右へ>>

メソッドをグローバルにする(JavaScript)



さて、もうひとつの例として、前の例でいじった removeAttr 自体をグローバルに移してみましょう。
jQuery の所属から、グローバルなメソッドに変更しています。処理内容そのものにはまったく手をつけていない、という点に注意してください。これはすなわち、syntax エラーさえ取り除けば、挙動の保証は(ほぼ)できている、ということを意味しています。
removeAttr の function ブロック全体を選択して (Shift+V) カット (d)、グローバルなコード領域にまで移動します (p)。JavaScript は、function の宣言の syntax に 2 通りあるので、ローカルなスコープ(まあ、それがグローバルなわけですが)用のメソッド名の前に function 句を置くほうに変更しています。インデントを動かすのは << や >> を使います。
その後、グローバルなメソッドから、もと jQuery のクラスメソッドに戻す作業をしています。そして、最後に undo (u) ですべてを巻き戻して、初期状態に帰ってきます。これ自体に、特に意味はないのですが、このように、いつでも適切な編集状態に戻れる状態を保ちながら作業をするのは、とても重要なことです。これを維持しておくことで、間違えたら、間違えたところまで戻って書きなおせばいい、ということが簡単に言えるようになり、これがリファクタ作業の敷居を大きく下げ、結果としてリファクタリングのインセンティヴを高めることになるのです。

使っているキー操作は以下になります。
カーソル移動h/j/k/l
行選択Shift+V
カットd
ペーストp
挿入i
追加a
検索/<キーワード>
次候補n
単語置換cw
直前の操作(単語置換)の繰り返し.
インデントを左へ<<
インデントを右へ>>



まとめ


さて、いかがだったでしょうか? わたくしがコーディングと呼ぶ作業というのは、だいたいこんなことの積み重ねからなっております。逆にいうと、プログラマであるわたくしは普段これ以外のことをしておりませんw
本物の vi 使いの方々は、もっとイカしたやり方をされていると思われますが、個人的には、vi は所詮道具に過ぎないので、だいたい思ったとおりに動かせれば満足なのであります。
今回、自分の使っているコマンドを整理してみて、その数の少なさにちょっとびっくりしています。vi には、それこそ何百ものコマンドがありますが、実際に使うのはほんの 20 ほどしかありません。
そして、こうして他人の書いたソースもどんどんいじって(編集して)整理していくと、そのコードの良し悪しも分かるようになってくるものですし、その箇所がなぜ他の書き方ではなく、その書き方で書かれているかが分かってくることでしょう。
今回、例にとった jQuery はたいへんよくできたソースで、いじれるところがまったくといっていいほどないのですが、リファクタリングというのは、まさにこうしたソースコードの状態(つまり、それは美しいコードということなわけですが)を手さぐりで探していく営みなのであります。
他人のコードを読むときは、どんどんリファクタリングしてみましょう。それは、それを書いた人との間接的な対話なのですし、自分の書き方に合わせていく過程で、そのコードがずっと親しいものになってくるでしょう。親しくないコードをメンテナンスしたり、使用したりするのは気持ちのわるい、不安なものですが、よく書かれたコードを、自分のコードから呼び出すのは楽しいものです。シンプルなコールの中で、どれだけ面倒なことが行われているかを知っているからこそ、良質なライブラリへの感謝がわいてくるのですし、自分も良質なコードを書こうという気持ちになるのであります。まあ、逆に、クソコードへの怒りも強くなってしまうわけですがw
と、最後はなんだか精神論になってしまいましたが、そうした意味で、プログラミングというのは、読書などよりも、より書き手(作り手)との直接的な対話になると思います。
というわけで、みなさん、動けばいい、とか言っていないで、せいぜいよいコードを書いていきましょう。それは誰かが見ていますし、分かってくれてもいるものです。

ちなみに、シャノンでは vi 使いは少数派で、社長の中村をはじめ、emacs 派がメインストリームであります。シャノンもまた、長年続く UNIX 系エディタ神学論争の舞台のひとつなのであります。
それでは。


3/11 追記:
いくつかの typo 修正しました。やはり入力には補完を使うようにしたいものです。わたくしは特に。
また、空行の挿入など体裁を整えました。このへんは、vim -> Blogger via コピペ、という変則作業をやっているとありがちなボロであります。
さらに、検索の前候補は p ではなく、Shift+N でした。p はペーストですね。すいません。言ってることとやってることが違う、というやつであります。

あと、twitter のアカウントはこちらでございまする。
難癖をつけたい方はどうぞ。難癖で返しますよ、たぶんw
http://twitter.com/#!/kiyoto01

それから、あらためて言うまでもないこととは思いますが、記事中で勝手に参照した、とってもよくできた JavaScript ライブラリであるところの jQuery とそれベースの WYSIWYG エディタ elRTE へのリンクを張っておきます。


elRTE は、Shanon Marketing Platform でも採用しています(ver.1.0 になるまえのやつなんですけどね)。
公式サポートは IE7 からのため、IE6 対応がちょっと大変でしたが、それはまた別の機会にでも。

ではでは。
次の記事
« Prev Post
前の記事
Next Post »

3 コメント

Write コメント
うりん
AUTHOR
2011年3月26日 23:52 delete

私の周りにはvim使いがいません。
他人のvim技を動画で見れるのがとても新鮮でよかったです。
Ctrl+Vでの編集はよくやりますが、
Iで先頭に挿入できるのは知りませんでした。
いつもsとかrとか使ってました。勉強になります。

単語置換はこっちの方が良く使います。

:%s/\/raise/gc

使いませんか?

Reply
avatar
kiyoto.s
AUTHOR
2011年3月30日 23:27 delete

どうも、ちょう亀レスあんど投稿承認遅れすいません。
ブログは慣れないもんで、わたくしめのオペレーションがクソなのであります。

置換は、:%s/xxx/yyy/g を使う、というコメントは他にもちょいちょいいただきました。
ええ、わたくしめも使っておりますよ。

ですが、リファクタリングの際にはこのような一括置換というのは、置換された部分を読まない可能性がある、という点で、少し危険だと思っております。
というあたりのお話しをまた、別の記事でさせていただくつもりでおりますので、よろしくお願いいたします。

Reply
avatar
うりん
AUTHOR
2011年7月5日 23:33 delete

遅レス過ぎですみません。gではなくて、gcですよ?

Reply
avatar
Related Posts Plugin for WordPress, Blogger...