2014年10月22日水曜日

vimdiffで単語単位の差分表示: diffchar.vimが超便利

今日もプログラミングや文書作成にvimを巧みに操り続ける全国のvimmerの皆様におかれましては、vimを利用した差分表示であるvimdiffは欠かせないツールであることと思います。

当方も今までvimdiffについては色を見やすくしたり差分計算アルゴリズムを賢くしたりと、カスタマイズによって使い勝手を向上させてきましたが、唯一実現できていなかったのが、「単語単位の差分表示」なのであります。

しかしついに、vimdiffで単語単位の差分を表示できるようにするvimプラグイン「diffchar.vim」を先日見つけました。最初の公開が今年5月という新しいプラグインです。
diffchar.vim - Highlight the exact differences, based on characters and words : vim online

ということで、早速インストール。このプラグインはGithubにもミラーされており、すでにNeoBundleをお使いであれば導入はとっても簡単で次の一行を.vimrcに追加して ":NeoBundleInstall" するだけです。それ以外の場合については省略。

NeoBundle 'vim-scripts/diffchar.vim'

実際サンプルで試してみましょう。まず、vimdiffで差分を表示させると、次のようになりますね。


一つの行に複数箇所の変更が含まれる場合も、最初の変更から最後の変更までを含むような大きな1つの変更として認識されてしまっています。

しかしここで<F7>キーを押すと!


うおおおおぉ!すばらしい。単語単位の差分を表示できました。一行に複数の変更があってもちゃんと認識して表示。しかも、追加部分と変更部分で色分けもされています。

ちなみに、再度<F7>キーを押すと元に戻ります。なお、<F7>キーは文書全体について単語単位の差分表示を切り替えますが、<F8>キーを押すと現在の行のみ単語単位の差分表示を切り替えることができます。

これだけでも便利ですが、欲を言えば、vimdiffコマンド実行時やgit diftoolにvimdiffを使っている時に、いちいち<F7>を押すのは面倒。そんな時には、

" vimdiffで起動した際自動的に単語単位の差分(diffchar.vim)を有効にする
if &diff
  augroup enable_diffchar
    autocmd!
    autocmd VimEnter * execute "%SDChar"
  augroup END
endif

と.vimrcに書いておけばOK。vimdiffコマンドで起動した時には自動的に単語単位の差分が有効になります。(この場合、単語単位の差分をOFFにしたければ<F7>キーを押す、という使い方になります。)

これでvimdiffで差分をチェックする作業が一層はかどりますね。

※補足:autocmdのイベントはFilterWritePost、BufReadPost 、BufWinEnterなども試しましたが、FilterWritePostでは効果がなく、BufReadPostやBufWinEnterだとどうやらdiff表示途中に実行されてしまうらしく余計な箇所まで単語単位で差分表示しようとしてしまい表示が崩れます。VimEnterを指定したら期待した動作になりました。

※この記事について指摘・意見・提案・感想などありましたら下のコメント欄にどうぞ。

2014年10月21日火曜日

OS X Yosemite で固定IP(手入力)時にVPNが繋がらない

MacをOS X Yosemiteにアップデートしたら、今まで正常に動作していたVPNが繋がらなくなりました。

ところが、iMacの方は繋がらなくなったものの、MacBookAirでは繋がります。VPN設定は同じ。なのになぜかiMacの方だけダメ。ファイアウォールを切ってみたり再起動してみたりしても繋がりません。

色々情報を探してたら、ネットでこんな情報を発見。
http://arstechnica.com/civis/viewtopic.php?f=19&t=1258743

要するに、YosemiteのL2TPクライアントにバグがあり、固定IPの場合接続できなくなる、というもの。上記リンク先ではWi-fiの時に再現を確認したとの情報ですが、Ethernet(ケーブル)接続においても同様かもしれないと思ったら・・・やはりそうでした。IPの設定が「手入力」になっていると、L2TPを利用したVPNに接続できません。MacBookAirだけ繋がっていたのは、IPアドレスがDHCP利用に設定されていたからです。

iMacで「手入力」にしていたのはIPアドレスを固定するためですが、これだとVPNに繋がらないし、どうしようか・・・と思っていたら、Macには

「DHCPサーバを使用(アドレスは手入力)」

という設定があるんですね。これに設定すると、IPアドレスのみて入力で固定することができ、デフォルトゲートウェイあネットマスクなどの他の設定はDHCPで取得することになります。この設定を行うことで、VPNに接続することができました。

※この記事について指摘・意見・提案・感想などありましたら下のコメント欄にどうぞ。

2014年8月20日水曜日

プログラミングにおける「コメント」を軽視してないか

「他人が書いたプログラムの解読」は、ソフトウェアエンジニアにとってもっとも厄介な仕事の一つでありながら、必ず求められる作業です。

他人が書いたプログラムとの格闘戦は、ソフトウェアエンジニアの方なら経験がおありだと思います。もしかしたらそれが日常かもしれません。

逆にプログラムを白紙の状態から書いていく機会というのは、新規のソフトウェア製品や新規サービスの開発に初期メンバーとして参画するといったものがあります。しかしソフトウェアエンジニアの仕事としては、それよりも既存の製品や既存のサービスに機能を追加したり不具合を修正するなど、すでに存在するプログラムに手を加える機会も多いです。むしろこちらの方が多いかもしれません。だから、すでに存在する他人が書いたプログラムを解読する必要が出てくるわけですね。

そもそも、なぜ他人が書いたプログラムの解読が難しいのかといえば、プログラムに書かれる情報はあくまでプログラム上の処理の流れを記述してあるのであって、その処理の目的や背景、その処理を行う理由といった、いわば"プログラムの文脈"に関する情報は含まないからです。

だから、プログラムの処理自体が完全に理解できたとしても、それがどういう目的で何を達成するための処理なのか、全体の中で果たす役割は何なのかさっぱり分からない、という事態もありえます。

そこで大きな役割を果たすのが、ソースコードに挿入するコメントであると考えます。コメントが書いてあることによって、"プログラムの文脈"に関する情報を得ることができれば、プログラムへの理解は飛躍的に速くなります。

一方、プログラミングにおいて、コメントは極力少なくすべきであるという主張もあります。「関数やメソッドを十分小さい単位に分離し、適切に名前をつければ、その関数やメソッドが果たす役割は名前によって十分表現できる。構造化を適切に行えば、コメントを書く必要はない。コメントは最後の手段だ」という考え方ですね。

しかし、それでもコメントを書かない理由にはならないと思います。構造化と命名の工夫によってプログラムが理解しやすくなるのは確かです。しかし、それはプログラムの処理自体が分かりやすくなるだけであって、その処理の目的や背景、その処理を行う理由といった"プログラムの文脈"に関する情報が含まれないことには変わりありません。

つまり、ソースコードをコメントに書いておかなければ、プログラムを理解するのに極めて困難を要する場合が多々あるのだから、ソースコードには適切にコメントを書くべきであって、コメントを極力少なくする方針には賛同できない、ということです。

そして、どこにどのようなコメントを入れるか、というところに、ソフトウェアエンジニアとしてのセンスが現れると思っています。

実際、絶妙な場所に適切なコメントが入っているソースコードは、プログラムの解読が大変行いやすく、メンテナンスも容易で、大変ありがたいプログラムです。多少プログラム自体が上手く書けていなくても、そのソースコードをもとに作業する人間としてはコメントが適切に入っている方が速く理解できたりするのです。

エンジニアの美学としては、コメントが無くて、プログラムのみのソースコードを扱うほうがカッコいいのかもしれませんが。そこは格好よりも実利を尊重すべきだと思うんですよね。

というわけで、ソースコードに適切なコメントを書くことを決して軽視してはいけないし、コメントは最後の手段なんかではない、と言いたいのです。

「なるほど」と思ったら
↓このリンクをクリックを。



※この記事について指摘・意見・提案・感想などありましたら下のコメント欄にどうぞ。

2014年8月8日金曜日

gitコミットとRedmineチケットは1対1にする

ソフトウェア開発のプロジェクトでgit(あるいはSubversion)を使っていない方が珍しいと思います。と同時に、極めてよく使われるツールがRedmineなどのプロジェクト管理ツールですね。

昔はバグトラッキングシステム(BTS)と呼ばれていましたが、バグの管理はもちろんのこと、プロジェクトのタスク管理につかうシステムとしても非常に優れており、広く使われるようになったことから最近では "プロジェクト管理ソフトウェア" などと呼ばれているようです。BTSに変わる決まった呼び方があるのかどうかはよく知りません。

ともあれ、git と redmine を連携させて使っているプロジェクトも多いことでしょう。Redmine 上のプロジェクトには git のリポジトリを関連付けることができ、gitのコミットメッセージにチケット番号を特定の書式で書くと、自動的にRedmine上のチケットとgitのコミットが関連付けされます。チケットの表示画面にgitコミットの概要とリンクが表示され、またコミットの表示画面ではチケットへのリンクが表示されます。これは後からソースコードの変更を確認したいときに、タスクの記録と一緒に追うことができて大変便利です。

ところで、1つのチケットに複数のコミットを関連付けることもできます。また逆に1つのコミットに複数のチケットを関連付けることもできます。ただし、僕の意見としては、極力チケットとコミットを1対1に対応させると、後から過去の変更を調べる際にすごく楽になります。(当然完全には無理でしょうから、出来る限りということです。)

例えば、1つのコミットに複数のチケットに関する変更を入れてしまうと、それらの変更がそれぞれどのチケットに関するものか判別するのは、変更した本人でない限り結構手間がかかるものです。あるいは、1つのチケットの解決に要した変更が複数のコミットにまたがっていると、これまたどんな変更がそのチケットに関連してなされたのかの結論を確認するのに骨が折れます。

だから、チケットとコミットを1対1に対応させるのがよいのです。もちろん、自分の手元でコミットを1回きりで済ませるのは大変だと思いますので、例えばローカル専用ブランチを作ってそこにコミットし、1つのチケットの分がまとまったら提出用ブランチにmerge --squash でまとめるといった方法をとればよいと思います。

※この記事について指摘・意見・提案・感想などありましたら下のコメント欄にどうぞ。

2014年8月7日木曜日

リファクタリングは早めに行うべし

前回「既存のコードはなるべくいじらない」と書いてますが、それは他人が書いたコードとか、すでにテストを通過したコード、公開されて十分に使われているコードなどについてのことです。

自分で書いたコードで、リリース用のテストが始まる前の段階のものについては積極的に修正を行っていくべきでしょう。もしタイミングを逃してそのままリリースされてしまうと、今度は下手にいじれなくなってしまいますからね。

特にリファクタリングでコードの質を向上させておくことは後々のためになります。とはいえなかなか時間をとれないとは思いますが、例えば変数・関数・メソッドの名前の付け方だけでも見なおしておくことは役立ちます。

※この記事について指摘・意見・提案・感想などありましたら下のコメント欄にどうぞ。

2014年8月6日水曜日

既存の他人のコードは書き直したくても我慢する

以前から続いているプロジェクトに自分が新しく入った時とか、オープンソースで公開されているソースコードに追加・修正を加える時か、他人の書いた既存のコードを見ていると、ついつい全て書き直したい衝動に駆られたりします。

しかし、既存のコードを書き直すのは得策ではないです。以前そのコードは製品リリースの段階でテストされており、機能が正常に動作することは確認済みだったりするからです。下手にいじることはむしろ余計なバグを産むことになりかねません。

だから可能な限りもとのコードを尊重するのです。いじらなくてすむ部分はいじらない。シンプルです。

※この記事について指摘・意見・提案・感想などありましたら下のコメント欄にどうぞ。

2014年8月5日火曜日

既存のプログラムの修正時には「郷に従え」

他人が作ったプログラムに手を加える時とか、オープンソースで公開されているプログラムを利用する際に一部改変する時とか、既存のプログラムを修正する機会はIT系エンジニアには日常的な仕事の一部であると思います。

新規でソースコードをイチから書いていける場合と違い、既存のソースコードに追加・修正を加える際に意識すべきことは、「郷に入っては郷に従え」ということです。

同じ動作をするプログラムの書き方は無数にあります。単に望み通りの動作をさせたいだけだったら、既存のソースコードをほとんど無視して書くことも出来てしまいます。

でも、それをやってはいけません。既に書かれたコードにおいては、プログラム全体への影響が考慮されているものがほとんどであり、他の部分との整合性がとれています。だから、何かの機能を追加したり修正する場合には、既存のコードを出来る限り利用すべきです。これは無駄なバグの発生を防ぐ事にもなります。

他にも、変数の命名規則やインデントの体裁なども含めて、既存のコードに沿って追加や修正を行うべきです。そうすることでコードが読みやすくなり、バグも発見しやすくなります。

※この記事について指摘・意見・提案・感想などありましたら下のコメント欄にどうぞ。