2014年3月31日月曜日

自動化テストを取り入れよう

テスト駆動開発を初めて取り入れようとした時には、準備が大変でした。自動化の仕組みを用意するのも結構手間がかかりましたし、テストのためのプログラムを書くことも、最初はどう書けばいいのかを調べながらやったので時間かかりました。

でも、実際自動化テストを書いてやってみて、それで本当に心から思ったんですが、開発している時の安心感が全然違いますね。特に、ある部分の変更が別の部分に影響してないかどうかを判断する際には、自動化テストがあるのと無いのとでは、手間が全く違います。

僕はWebアプリの開発をずっとやってきたわけですけれど、自動化テストを取り入れていなかったプロジェクトの時は、何か変更を加えたら、影響を受けそうな怪しそうな部分を全部ブラウザ上で動かして手動と目視で確認していましたからね。非常に手間がかかっていました。自動化テストがあれば、テストを実行して放っておけば完了します。テスト実行中に別の作業もできますし、効率は比べ物になりません。

結果的に、テストプログラムを書く手間は後になって回収できているのですね。最初の自動化テスト用の環境構築とテスト用プログラムの記述の部分でハードルがありますが、頑張って乗り越え、自動化テストを導入する価値は十分あると思います。

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

2014年3月30日日曜日

フルスタックエンジニアって結構よくある話だよね

なんか最近フルスタックエンジニアってキーワードを目にして、なにかと思ったら、「インフラからミドルウェア、モバイル、デザインまで、あるいは設計からプログラミング、デプロイまで、何でもこなせるエンジニア」ということらしい。

ほう、僕の時代が来たか、って思ったんですけど、よく考えて見れば、別にこれって珍しい訳でも何でもなく、例えば比較的小規模のプロジェクトでは、一人のエンジニアが様々な仕事をこなさなければいけないので、自然とフルスタックエンジニアになるんですよね。Web系でしたら、自分でサーバを用意し、ネットワークやOS周りをセットアップし、要件定義・設計・開発・テストを実行し、デプロイまで行う。さらにメンテもする。そんな感じで仕事してれば一通りできるようになりますよ。

逆に言えば、1つの分野(例えばDB設計だったらDB設計だけとか)に依存している人にとっては、今後厳しい時代になるのかな、と思います。皮肉なことにそういうのは大規模プロジェクトに多く、大規模なプロジェクトに多く関わった人ほど自分の専門分野以外のことを何も知らなかったりします。だから大規模プロジェクトの経験イコール良い経験だとは限らないですね。

ということで、僕と同じように中小規模のプロジェクトで何でも屋のようにあらゆる作業を任されてきたフルスタックエンジニアの皆様、いよいよ我々の時代のようですよ?

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

2014年3月29日土曜日

VimとEmacs両方に慣れておくべき理由

エディタ界の2大巨塔といえば、言わずと知れた Vim と Emacs でございますが、まあ僕は不毛な宗教論争に関わるつもりはありませんので、どっちを使うべきだなんて言うつもりは毛頭ございません。

学生時代にUnix/Linuxに触って最初に使ったエディタがEmacsでした。その頃はVimは全く使わず、Emacsで全てのテキスト編集を行っていた時期が2年くらい続いたと思います。Lispでカスタマイズも色々やりました。

ある時とある先輩にVimを強力にお勧めされて使い始め、慣れるために卒論を全部Vimで書いたことでVim使いになりました。慣れるまでには結構苦労しましたけど、慣れると便利ですよね。プログラミングをするなら断然Vim派です。普段使うエディタはVimになっていきました。

こんな経緯があって、両方のキー操作の流儀を身に付けたんですが、普段エディタとしてはVimを使っていますが、Emacsのキー操作でテキストを編集することも結構あるのです。

例えばメールを書く時は、昔はメーラー、今はGmailを使いますけれども、この時はEmacsのキー操作を使います。WindowsでしたらAutoHotKeyなんかで結構簡単に実現できますし、MacだとデフォルトでEmacs風のキー操作を受け付けてくれます。。それに限らず、テキストエディタ以外の部分でのテキスト入力はほぼすべてEmacsのキー操作でやっています。

その上で、テキストエディタはVimですね。カーソル移動やコピー&ペースト、入力などを使いこなすと非常に便利で、繰り返しになりますけれどもプログラミングをするなら断然Vimが快適です。

ということで、Emacs風のキー操作とVim風のキー操作の両方に慣れておくと、状況に応じて使い分けられて便利ですよ、という話でした。

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

2014年3月28日金曜日

vimdiffの色設定を変更して見やすくする(黒背景用)

Linuxにおける差分表示ツールとしてはdiffコマンドがありますけれども、複雑な変更になってくるとvimdiffが使いやすい場面も多々あるわけでございます。特に横に並べて比較できるのは大きなメリットですよね。

ところが、デフォルトの設定ですと結構色が見辛いわけで、何とかしたいわけです。ちょっと検索して調べてみましたが、自分が思うような色設定がどっかに載ってたりとかしなかったので、自分で設定してみることにしましたよ。いつも黒背景で使っておりますので、そこに最適化してあることにご注意ください。

というわけで、下記の記述を .vimrc に加えればOKです。

" vimdiffの色設定
highlight DiffAdd    cterm=bold ctermfg=10 ctermbg=22
highlight DiffDelete cterm=bold ctermfg=10 ctermbg=52
highlight DiffChange cterm=bold ctermfg=10 ctermbg=17
highlight DiffText   cterm=bold ctermfg=10 ctermbg=21

これでvimdiffコマンドを実行するとこのようになります。


背景の色を差分の種類によって分けており、追加行は緑、削除行は赤、変更行は青で変更部分が明るい青になってます。

これでだいぶ見やすくなるんじゃないかと思います。

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

2014年3月27日木曜日

Macの端末内Vimで挿入モード時カーソル形状切り替え

Macで端末を起動してリモートにSSH接続し、Vimでソースコードを編集するって使い方を普段良くするんですけれども、以前からの不満の1つが挿入モードの時のカーソル形状を切り替えできないことでした。

MacVimであれば、ノーマルモードのカール形状はブロックで、挿入モードの時はカーソル形状が垂直バーとなります。これにより現在が挿入モードかどうかすぐ分かりますし、文字が挿入される位置も見やすくなります。

で、端末上で起動するVimにしても、実はカーソル形状の切り替えができるらしいことが調べてわかったんですが、いかんせんMacのOS X標準で用意されている"ターミナル.app"は、カーソル形状の切り替えに対応していないようです。しかしながら、"iTerm2"という端末アプリが対応しているらしいとのこと。

ということで、標準の"ターミナル.app"から"iTerm2"へ乗り換えるとともに、カーソル形状をモードによって切り替える設定をしました。

iTerm2のインストールと設定


下記からダウンロードして解凍し、出てきたアプリを直接「アプリケーション」フォルダにドラッグ&ドロップしてください。
http://www.iterm2.com/#/section/home

設定は好みですが、プロファイルの以下の部分は重要と思われますので書いておきます。

「Text」タブ
Treat ambiguous-width characters as double width にチェック → これにチェックを入れておかないと、□や◯といった記号の混じった文章がおかしくなります。

「Window」タブ
Disable session-initiated window resizing のチェックを外す → ウィンドウサイズを変更した時に追随させるにはチェックを外します。

「Terminal」タブ
Save lines to scrollback in alternate screen mode のチェックを外す → Vim起動中にウィンドウサイズを変更した場合に、Vim終了後の端末ヒストリーがおかしくならないようにするにはチェックを外す必要があります。

Report Terminal Type: "xterm-256color"に設定 → デフォルトだと"xterm"ですが、カラー表示が一部不完全になるので、この設定に変更します。

「Key」タブ
ターミナル上でMac側のショートカットキーが効かなくなる場合がありますので、ここで設定して回避します。僕の場合、日本語/英数の入力切り替えに使うキーを効くようにするために次のように設定しました。
Ctrl+Shift+J → Do not Remap Modifiers
Ctrl+Shift+: → Do not Remap Modifiers

Vimの設定


さて、カーソル形状をモードによって切り替えるには、下記の設定を.vimrcに記述してVimを再起動します。

" 挿入モードでカーソル形状を変更する
let &t_SI.="\e[6 q"
let &t_EI.="\e[2 q"
" カーソル形状がすぐに元に戻らないのでタイムアウト時間を調整
set ttimeoutlen=10
" 挿入モードを抜けた時にカーソルが見えなくなる現象対策(なぜかこれで治る)
inoremap <ESC> <ESC>

最初のt_SIとt_EIの設定では、エスケープシーケンスを用いてカーソル形状を設定しています。

また、ttimeoutlenはエスケープシーケンスをその時間内に入力すれば認識するという意味で、逆に言えばその時間まで待って初めてエスケープシーケンスの効果を認識するということになります。この時間が認識できるくらい長いと挿入モードを抜けた際にカーソル形状がすぐにもどらない、なんて事が起きます。エスケープシーケンスは手入力しないことがほとんどだと思うので、10msecに設定しています。(0でもいいという情報もみかけましたが念のため10msecにしてます。)

さらに、なぜか挿入モードを抜けた時にカーソルが次の操作をするまで見えなくなるという現象がたまに発生したので、上記設定をしたら治りました。なぜ治るのかの理由は不明ですが、追求しても仕方ないのでよしとします。(分かる人いたら教えてください。)

ちなみに、iTerm2は標準でマウスイベントに対応してまして、mouse=aと.vimrcに書いておけばホイールスクロールできますし、マウスドラッグがビジュアルモード選択になります。なおMac側でコピペしたい時にはOptionキーを押しながらドラッグするとできます。

これで快適にVimで操作できるでしょう。楽しいVimライフを!

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

2014年3月26日水曜日

Macのターミナル上のvimでマウスホイールスクロール

僕もvim愛用者の一人ですけれども、MacBookではMacVimとターミナル上のvimの両方を使い分けております。また、sshでリモート接続してターミナル上でvimを使うこともしばしばあります。そこで前から、ターミナル上でvimを使う時もマウスホイールでスクロールできたら便利だと思っておりまして、方法を調べてみました。

要点としては、

  • EasySIMBLをインストールする
  • MouseTermをインストールする
  • vimの設定でマウスを有効にする

の3点です。

EasySIMBLをインストールする


SIMBLは、MacのCocoaアプリケーションの動作をカスタマイズできる機能拡張です。このSIMBLの上にさらに用途別のプラグインをインストールすることで様々なカスタマイズができます。EasySIMBLは、本家SIMBLを改良して、ドラッグアンドドロップで簡単にプラグインをインストールできるようにしたものです。ダウンロード先はこちら↓
https://github.com/norio-nomura/EasySIMBL/

MouseTermをインストールする


Macのターミナルがマウスイベントを送信できるようにするSIMBLプラグインです。先ほど上で述べたEasySIMBLを使ってインストールします。ダウンロード先はこちら↓
https://bitheap.org/mouseterm/

ダウンロードして解凍インストーラが出てきますが、このインストーラは使わずに、直接拡張子が「.bundle」のファイルをEasySIMBLの画面にドラッグアンドドロップしてください。

MouseTermをインストールすると、ターミナルの「シェル」メニューに「Send Mouse Events」が出現し、チェックのON/OFFで切り替えができるようになります。普段はONにしておき、Mac内の別のアプリにターミナル上の文字をコピペしたいときなどはOFFにするとよいでしょう。

vimの設定でマウスを有効にする


.vimrcに次の記述を追加します。

set mouse=a
set ttymouse=xterm2

なお、僕の環境ではttymouseは元々xterm2になっていたので2行目の設定は不要でした。

これで、ターミナル上のvimでもマウスが効くようになります。マウスホイールでのスクロールに加えて、クリックした部分へのカーソル移動、ドラッグによるビジュアルモード選択もできるようになります。

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

2014年3月25日火曜日

コードは「簡潔」に。「短く」ではない。

プログラミングにおいて、コードは「簡潔」に書くようにしよう、とはよく言われることですね。冗長な書き方を排し、スッキリ読めるようにすることは大切なことです。その点にケチを付けるつもりはありません。

しかし、「簡潔」とは「短く」という意味ではありません。最も重要なのは、読んで処理の流れが分かりやすいことであって、短いほうかがそうなるかというと、僕は違うと思います。むしろ、あまりにコードを短くすることは、かえってコードを分かりにくくします。今プロジェクトでRubyを使っていますけれども、特にRubyのように豊富な組み込みライブラリを持ち、1つの処理を無数の方法で書けるような言語に関しては、短く書こうと凝り過ぎた記述がむしろ難読化を招くという罠があります。

もちろん、処理の流れを分かりやすく書こうと努力することで自然にコードが短くなり、見た目も美しくなるという副作用が発生しますから、見た目の美しいコードは読みやすいという法則があるのは確かなのですが、見た目の美しさとコードの短さは必ずしもイコールではありません。

さらにタチの悪いことに、同じ処理を短く書けるということは使用する言語に対するマニアックな知識がないとできないので、短いコード=高い技術力という思い込みにも陥りがちであるように思います。しかし、よく考えて見れば、書いた人以外が読むのに苦労するようなコードを書く人間が本当に技術力が高いと言えるのでしょうか。むしろ、本来ならば難しいはずの処理を、簡単に分かるようにコード化して見せられる人間の方が、高い技術力があるといえるんじゃないかと、僕は思います。

プログラミング以外においても「難しいことを難しく説明するのは凡人であり、本当に頭のいい人間は、難しいことを易しく説明できる人間だ」とよく言われますけれども、プログラミングにおいてもこれは同じことだと思います。

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

2014年3月24日月曜日

アジャイル開発が適する場合、適さない場合

僕も実際ウォーターフォール型の開発とアジャイル開発と両方の経験がありますし、それ以外の方法、例えばプロトタイプ+反復型などの経験もあります。一時期はアジャイル開発が今のIT業界、とくにソフトウェア開発の現場の問題を解決してくれるんじゃないかと救世主のように思った時期もありましたが、自分の環境がそこからまた変わった時に、どうもアジャイル開発は万能薬ではないと気づいたんですね。ジョエル・スポルスキーが "Joel On Software" の中で、ソフトウェア開発には5つの世界があるとして

  • パッケージ
  • インターナル
  • 組み込み
  • ゲーム
  • 使い捨て

の5つを挙げて、さらにソフトウェア開発の方法論、例えばテスト駆動開発やエクストリーム・プログラミングなどのアジャイル開発手法を提唱している人々は、インターナルソフトウェアの開発について話していると指摘していました。(※注1)

これを読んでハッとしたんですね。僕がアジャイル開発でうまくいったのは、正確にはインターナルソフトウェアでは無かったものの、実質的にインターナルソフトウェアの性格を持ったソフトウェア開発であることには違いは無かったからです。

今は環境が変わり、今取り組んでいるプロジェクトはパッケージソフトウェアの分野に近いです。そしてアジャイル開発は全てではなくその一部を取り入れようと思っている所です。

※注1)http://japanese.joelonsoftware.com/Articles/FiveWorlds.html

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

2014年3月23日日曜日

プラスアルファでググる

よく仕事中には技術情報をググって検索したりしますよね。そこで、目的の情報を探し当てた段階でそこで満足するのは、少々勿体無いです。

関連情報をついでに1つ調べるようにしてみると、知識を広める良い機会となりますよ。

ちなみに、直ぐに役に立たない情報を調べるのに意味は無いと思われるかもしれませんが、こういう時についでに得た情報が、何かのタイミングで役に立ったりするものです。

プラスアルファでググることを心がけるといいですね。

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

2014年3月22日土曜日

jQueryでHTMLの内容を入れ替えるいくつかのパターン

ユーザのアクションに応じてHTMLの内容を入れ替えるというのは、jQueryを使うと手軽に実現できますよね。幾つか書いてみようと思います。

1.文字を書き換える


文章だけ変化すればいい場合、text()メソッドで書き換えればよいです。

<html>
  <head>
    <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
    <script src="./script.js"></script>
  </head>
  <body>
    <div id="container">
      <div id="content1">click me!</div>
    </div>
  </body>
</html>

$(function(){
  $('#content1').click(function(){
    $(this).text('fuga');
  });
});


2.要素を生成・削除して入れ替える


要素自体を別のものに変えたいような場合は、新たに要素を生成して古い要素の後ろに追加し、古い要素を削除します。

<html>
  <head>
    <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
    <script src="./script2.js"></script>
  </head>
  <body>
    <div id="container">
      <div id="content1">click me!</div>
    </div>
  </body>
</html>

$(function(){
  $('#content1').click(function(){
    var newElem = $('<p>foo</p>')
    $(this).after(newElem).remove();
  });
});


3.要素の表示・非表示を切り替える


大きめの画像などを入れ替える場合、HTMLの内容を書き換えて新しくimg要素を追加すると、画像の表示にタイムラグが発生したりします。そういった場合、あらかじめ表示させる予定の要素を全て並列に用意しておき、初期状態で表示させたいもの以外はCSSでdisplay:"none" を設定しておきます。そしてjQueryのshow()とhide()メソッドで表示・非表示を切り替えます。

<html>
  <head>
    <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
    <script src="./script3.js"></script>
  </head>
  <body>
    <div id="container">
      <div id="content1"><img src="sample1.png"/>click me!</div>
      <div id="content2" style="display:none"><img src="sample2.png"/>bar</div>
    </div>
  </body>
</html>

$(function(){
  $('#content1').click(function(){
    $(this).hide();
    $('#content2').show();
  });
});


今回挙げたのはあくまで一例にすぎませんが、jQueryだと記述が分かりやすく状況に応じて最適な方法を模索しやすいのがいいですね。

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

2014年3月21日金曜日

ソフトウェア開発者には想像力が重要

今進めてるプロジェクトで、開発中のソフトウェアを実際に使う人を何パターンか用意して実際に利用するシーンを書く、ということをやっております。これはシナリオづくりってやつです。利用者像という意味ではペルソナって用語もありますね。まあ、年齢とか家族構成みたいな細かい部分までは考えませんけど、ざっくりおおまかなイメージは作ります。

画面の構成やユーザインタフェースの詳細をこれから作っていくにあたり、どういう人がどういうシーンで、どういう心境で使うのか、といったことを想定するのはソフトウェア設計の初期段階において非常に大事です。この使用シーンを文書化して仕様書の一部に盛り込む手法は業界のベテラン開発者も提唱しており、今回僕もそれに倣って、仕様書の一部としてシナリオを盛り込むことにしたわけです。

さて本題ですけれども、ソフトウェア開発者はプログラミングさえできればいいわけでは勿論ありません。上で述べたように、自分が開発しているソフトウェアがどのような人達にどういうシーンで使われるのか、想像力を駆使しなければ良いソフトウェアが開発できません。

そういえば、昔ながらのウォーターフォール型開発においては、設計部分とプログラミング部分が分離しており、ともすればそれらが別々の人間、あるいは別々の会社で行われることも多々あるように思います。僕自身もそのようなプロジェクトに携わった経験もあります。しかし、今現在は設計もプログラミングもどちらも行う状況にあります。要するに、プログラミングの工程になったら仕様通りに作ればいいとか言う話では全くなく、プログラムの実装中であっても、ユーザビリティを常に考慮して細かい仕様を変更できるし、すべきだということなのです。

このボタンの位置はもっと右にあると押しやすいとか、あるいは後戻りできない決定のボタンだから逆に押し間違い防止のためあえて押しにくい位置にするとか、選択肢の順序を入れ替えて最も選ばれる頻度の高い選択肢を選びやすくするとか、そもそも本来次の画面での入力項目だったが、よく検討してみたらその前の画面で入力できたほうが分かりやすいから移動するとか、もう色々様々ありとあらゆる細か〜い仕様を使い手の視点に立って最適化しなければいけません。だから、想像力が重要なのです。

このような状況は僕自身については今後も続くと思いますし、業界全体としても、設計からプログラミングを同じ人間、同じチームが行う状況はますます多くなっていくでしょう。そうなると、ソフトウェア開発者全てにおいてやはり想像力の重要性はもっと高くなっていくと言うべきでしょう。

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

2014年3月20日木曜日

[Ruby]開発環境をEclipse(Aptana)からVimに変更した件

開発環境にはEclipseを愛用してきた僕ですけれども、Rubyでの開発プロジェクトを本格的に進めるにあたり、色々試行錯誤の結果Vimに乗り換えることにしました。いえ、乗り換えるというと語弊がありますね。正確に言えば、コーディングすなわちソースコードをガリガリ書く部分にはVimを使いますが、EclipseはGitリポジトリの状態を見るのに使ったりするので併用していく方式にした、ということです。適材適所。

PHPの時にはEclipseのPDTプラグインが大変良く働いて、例えば文脈に応じての補完機能などは非常に便利でした。これは動的にコードから補完ができる優れ物で、自分で書いたクラス定義を参照してインスタンスのメソッド名を補完できたりしたんですね。さらに、フレームワークのソースコードをライブラリを読み込ませることで、フレームワークに用意されたクラスやクラス内のメソッドまで補完が効きました。あとクラスやメソッドにカーソルを合わせてショートカットで定義元にジャンプできたりとか。

一方、EclipseでRuby開発に使えるプラグインとしてはAptana Studio3がありますが、動的にコードから補完するところまではできないようでした。また、フレームワークのクラス名やメソッド名も補完が働きませんでした。もしかしたら僕の設定が間違っていた可能性もありますが、ある程度時間を掛けたところで諦めました。

そもそも、純粋なテキストエディタとしての使い勝手としてはVimが好きで、EclipseにVim風のキーバインドを実現するプラグインのvrapperを入れて愛用していたくらいです。PHPで開発していた時には、文脈を理解した動的な補完とライブラリからの補完がよく出来ていたので書きやすさを少し犠牲にしてEclipseを使っていましたが、それがイマイチならEclipseを使う優位性は薄れてしまいます。

調べてみると、Vimで一定レベルの補完や自動文法チェックもプラグインでできるので、それならRubyを書くのにはVimの方がいいかと思ったんですね。ということでコーディングはVimで行うことにしました。

ちなみに、Gitリポジトリの状態を見るためにEclipseは併用します。コミットグラフが見やすいので。ヒストリービューはほぼリアルタイム(長くても5秒くらいの遅延)でコミットグラフを更新してくれるので、状態を把握しつつブランチ間を移動したりコミットしたりできます。Eclipseは検索なんかも結果が見やすいですし。タスク・タグの一覧とかも便利です。普段はVimでコードを書きつつ、裏でEclipseを起動させておいて必要な時だけ見る、という使い方になると思います。

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

2014年3月19日水曜日

ドキュメントはいつ書き、いつ修正すべきか

アジャイル開発の有名な指針には「詳細なドキュメントより、実際に動くコードを優先する」というものがあり、その影響かどうかは分かりませんが、開発中にドキュメントを書かないプロジェクトも多いと聞きます。

そもそもアジャイル開発の対局にあるウォーターフォール型の開発であったとしても、一度フィックスしたドキュメントを修正するのは容易ではなく、一度設計プロセスを通過してしまったプロジェクトではドキュメントの修正は後手に回ってしまいやすく、結局誰も見ないという事態が発生しがちです。

こういう問題は一概に答えを出すことは難しいものですね。以下の文章は、1人〜数人程度のチームで小規模開発を行う場合に限定した意見として読んで頂ければ幸いです。

ドキュメントを最初に全部作ってフィックスさせてしまうのも、あるいは開発中ほとんど(あるいは全く)手を付けずに、最後になってコードに合わせてドキュメントを作るのも両方良くないと思います。もちろんそんなことは分かっていると仰るでしょうが、実際のプロジェクトでは特に後者のパターンは結構頻繁に行われていますよね。

ドキュメントを書く利点の1つは、コードを変更する手間よりもドキュメントを変更する手間のほうが少ないため、いきなりコードを書いてしまってから修正するよりは効率よくデザインが出来るということです。しかしながら、逆にドキュメント上だけで実際のソフトウェアの詳細な動作や操作感を想像するのには限界があり、ドキュメントを詳細に作りすぎると今度は実際その通り作ってみたら期待と違った、なんてことも起こります。

だから考え方としては
「難なく想像できる詳細度まではドキュメントのみを先に書き、それより詳細な部分のドキュメントは開発しながら書く」
という感じがいいのではないかと思ってます。

例えばWebアプリケーションで言うと、画面遷移や画面のざっくりした大まかな構成はコーディングを初める前に書き、それより先はコーディングを進めつつ書く、みたいな感じですかね。

ドキュメントの更新を最後にまとめてやるパターンは実に多いんですが(そして気持ちもよく分かりますが)、ひたすらドキュメントだけを作るのは大変で退屈な作業である上に抜け漏れも発生しやすいので、やはり開発中に頻繁に更新すべきでしょうね。

理想的には「ドキュメント駆動」的な開発ができるといいと思ってます。まずドキュメントに変更を加え、それに基づくテストを書き、それから実装コードを書く、っていう手順です。現在僕が取り組んでいるプロジェクトではこの進め方を実際試してみるつもりで、このテーマについてはまた書くと思います。

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

2014年3月18日火曜日

[Ruby] Cucumberで日本語テスト定義がエラーになる時の対処

最近初めてCucumberを導入したんですが、日本語でテストケースやステップ定義をする際に日本語をうまく認識できずエラーが出たので、それに対する対処と、若干のTipsをメモしておきます。

最初はネットにあるCucumberのサンプル通りfeacureファイルと対応するstep定義ファイルを記述して実行しました(この時は日本語なし)。これはうまくいきました。今度は、記述を日本語に変更して実行。ところがエラー。下記のように対処しました。

featureファイル


最初に出たのはこんなエラーでした。

Lexing error on line 1


調べてみると、そもそも全く文法を識別できない時のエラーだとか。そんなバカな。しかしどうやら原因は、日本語を使っていると認識できていないようでした。調べた結果、1行目に下記のようにコメントを入れることで日本語を使っていると認識でき、このエラーは出なくなりました。

#language:ja


step定義ファイル


ところが上記エラーを修正すると、今度はこんなエラーが出ます。

invalid multibyte char (US-ASCII)


勘弁してくれ。ただ、今度はエラーメッセージから明らかに文字コード認識の問題だと分かります。調べた結果、step定義ファイルも1行目に下記のようにコメントを入れないと、正しく文字コードを判別できないようです。(先ほどとは違うコメントなので注意。)

#encoding:utf-8


これらの記述をすることで、日本語で記述したテストが実行できるようになりました。

2014/03/20追記:step定義ファイルの文字コード認識の問題は、Ruby1.9系が上で書いたようなコメントを入れないとエンコーディングを正しく認識できないことが原因みたいなので、Ruby2.0以上をお使いの場合は不要かもしれません。

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

2014年3月17日月曜日

自動化テストは部分的にでもいいからやる

僕はテスト駆動開発が理想だと思っていますが、しかし全てのコードが100%テストファーストで書けるかというと、なかなかそうは行かないという現実も理解しています。それに、GUIに関わる部分など、そもそも自動化テストを書くのが困難なケースもありますよね。例えばメニュー選択の際にアニメーション効果やドラッグアンドドロップの動作確認など、間接的にステータスの値などを自動化テストで確認することはできても、直接的な確認は人間の目でやるしかなかったりします。

しかし、それでも自動化テストをやれる範囲で可能な限りやっておくことは非常に良いことだと僕は思います。テストコードはできるだけ先に書いたほうがいいですが、先に書くことができないなら後から書いてもいいです。それでもテストコードがないよりは遥かにましです。

僕が自動化テストを初めて実務で経験したのはPHPのフレームワークであるsymfonyを使ったプロジェクトを担当した時です。そもそもそれまで自動化テスト自体よく知らなかったので、symfonyに付属しているテスティングフレームワークのlimeについて調べながら行っていきました。実は最初は面倒だと思いましたし、自動化テストの恩恵をいきなり最初から実感できたわけではありませんでした。はっきり恩恵を感じたのは始めてから数ヶ月経過してからでした。

1つの仕様変更だとしても、実際はプログラムの様々んな箇所を変更しなければ整合性が保たれません。そしてその際、今まで自分が書いたプログラムがきちんと動くか全て確かめるのは手動では相当大変です。仕様の変更がかなり大胆に入るプロジェクトでしたのでなおさら毎回すべての仕様を確認手動で確認していたら非常に苦労したと思います。しかし、自動化テストのおかげで手動での確認作業を大幅に短縮できたので、開発をスムーズに進めることができました。また、自動化された部分は少なくともテストコードの書いた範囲での確認漏れは発生しないので、単純ミスによる漏れを心配せずとも済むという意味で安心して開発を進められました。

ということで、今進めているプロジェクトでも自動化テストをできるだけ広い範囲カバーする方針で進めています。前回の経験を活かしつつさらに効果的なテスト手法を取り入れていくつもりです。

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

2014年3月16日日曜日

技術書の読み方・使い方

プロジェクトを本格的に進めていくにあたり、Rubyの専門書が1つ欲しかったので、内容が新しくかつ網羅的だと感じた「パーフェクトRuby」(技術評論社)を買いました。これから読もうと思います。そこで関連して今回は、技術書全般について読み方・使い方について僕の考えを書いてみたいと思います。

特にプログラミングだとこの傾向は強いと思うのですが、よく使う技術に関しては、わからないことを辞書的に調べる「リファレンス本」を持っているべきだと言われます。これはその通りです。ネットでもかなりの情報は得られますけれども、体系的かつ信頼性のある情報を参照できる書籍を持っていることの意義は大きいと思ってます。

ただ、そのリファレンス本としての技術書に関してはこんな言われ方をすることがあります。

「最初に目次にざっと目を通して、すぐに使いそうな部分だけを読み、残りは読む必要はない。実際に別の部分に関連することをやる時になったら、その時に改めて必要な部分を読めばいい。使えるところだけ使えばいい。」

この説について、僕は賛同していません。これでは、せっかくの技術書の真の恩恵を受けられないと考えているからです。僕のお勧めする読み方はこうです。

「最初にひと通り、とりあえず最初から最後まで全部読む。ただし、内容を憶えようとする必要はない。ただ理解しておけば良い。理解したら一旦忘れて構わない。」

こう言うと、ひと通り全部読むのは時間がかかるとか、忘れたら意味ないんじゃないの?とか思われるかもしれませんが、この読み方には目的があるのです。それは、「頭の中にインデックスを作る事」なんです。ここでインデックスと言っているのは、「この本にこんな内容のことが書いてあった」と連想するための目印のようなものです。そのためには理解して納得しておくことが非常に重要なのです。

例えば、プログラミングをしていて、ちょっと分からない問題が出てきたとします。技術書を理解して読んでおいた人は、「あれ?この問題って、あの本に書いてなかったかな?」と本を読んだことを思い出すんですね。そして、本を手に取ってパラパラめくっていると、1回全部読んでいる人は本の内容の流れをたどっていますから、パラパラめくるうちにどの辺に何が書いてあったかを思い出していきます。すると「あの問題はこのへんだな」と実際に今直面する問題についての記述を簡単に探し当てることができます。

つまり、理解して納得しているからこそ、問題に直面した時に、本に書いてあったことだと思い出すことができるし、ひと通り全部読んでいるからこそ、パラパラめくるだけで問題に該当する箇所がどこだったかを簡単に探し出せるのです。もし特定の箇所だけ読んで、しかも中途半端な理解だったら、このような使い方はできませんよね。

なので、技術書を読み終わった時に、最初の方の内容は忘れていたりします。でもそれで全然構わないのです。実際に問題に直面した時に、それまで忘れていても「あ、あの本に書いてあった」と連想して「書いてあったという事実」思い出せますからね。この時点ではまだ内容までは思い出してませんが、本を開いてページをめくり、該当するページを開いた時に一気に思い出します。

ということで、技術書は「一通り最初から最後まで読み、理解し、そして忘れる。」という読み方がおすすめです。まあ、全部ってのはキツくても、読んでおく範囲をなるべく広げておくと、その分脳内インデックスを広く作っておけるので良いと思いますよ。

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

2014年3月15日土曜日

[Ruby] Padrinoをフルスタックで使う時にどのコンポーネントを使うか

以前にSinatraについて書きましたが、その後検討した結果Sinatraベースの軽量フレームワークであるPadrinoを使うことにしました。結局MVCの構造にするんだし、TDDやるし、となるとSinatraの上に色々作り込むことになるわけで、だったらひと通り用意されているものを使ったほうがよさそうだからです。以前PHPのフレームワークSymfonyを使っていた経験もあって、フルスタックフレームワークの恩恵はよく知ってましたので。でも自由度はPadrinoの方が高そうです。

さて、Padrinoはフルスタックフレームワークではおなじみのプロジェクト・ジェネレーターがありまして、コマンド一発でプロジェクトの雛形を生成できるようになってます。しかしながら、このプロジェクト・ジェネレーターには、機能ごとにどのコンポーネントを選ぶか、様々なオプションを付けることができ、迷うこともあるんじゃないかと思います。

ということで、今回どのコンポーネントを使うことにしたかと、その理由について書いてみたいと思います。

とりあえず、一覧はこちらです。(ちなみに選択可能な他の選択肢はここに載ってます。)

  • orm: activerecord
  • test: cucumber
  • script: jquery
  • renderer: erb
  • stylesheet: scss
  • mock: none

プロジェクト・ジェネレーターのコマンドは

padrino g project <the_app_name> -d activerecord -t cucumber -s jquery -e erb -c scss

ですね。

それぞれ理由について書いてみます。

orm: activerecord


ORマッパーです。activerecordを選んだのは、Railsで標準的に採用されていて情報が手に入りやすそうだったからです。もちろんここでactiverecordのやり方を習得したら、Railsのプロジェクトをやることになった際も役立つだろうという計算もあります。他の選択肢はよく知りません。

test: cucumber


テスト駆動開発のファンとしては重要なテスティングフレームワーク。これは以前も書いたようにcucumberをチョイス。ちなみに、選んでみて後から気づいたんですが、cucumberを指定すると自動的にcapybaraも組み込まれて使用されます(もちろんrspecも)。他の選択肢はrspec以外はよく知りません。

script: jquery


javascriptフレームワークはjQueryをチョイス。まあ最もメジャーで資料も豊富だし使いやすいしこれが一番ですかね。prototypeは古いイメージがあります。extcoreは書き方が好きじゃないです。dojoは面倒そう。rightjs, mootoolsはよく知りません。

renderer: erb


テンプレートエンジン。迷いました。hamlは確かに構造的に美しいかも知れませんが、学習コストが高く慣れるまで時間かかりそうなのと、後々デザイナーさんとの協業の際非常に面倒になりそうなのでパス。slimも同様の理由でパス。一瞬liquidのPHPでいうところのsmartyに似たシンプルさに惹かれましたが、調べてみると情報がとても探しにくい。柔軟性の高さも勘案して結局erbにしました。

stylesheet: scss


これもlessとscssどっちにしようか迷いました。たぶんコーディングの観点からは差はありません。しかしrubyのプロジェクトなので、ビルドエンジンがrubyであるscssとは相性が良さそうで、lessは結局node.jsの導入が面倒なので止めました。

mock: none


モックフレームワークは実は存在自体今回調べてて初めて知りましたが、あまり必要性を感じなかったので指定しませんでした。なんかJava界隈では結構活躍してるっぽいですね。誰かどんな風に便利なのか知ってたら是非コメント書いて教えてください。

以上、コンポーネントを選んだ理由でした。参考になれば。

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

2014年3月14日金曜日

開発初期は些細なことに気を遣う

今仕事で進めてるプロジェクトも開発の初期段階にありますけれども、初期段階は些細なことにホント色々気を遣います。

もちろん、言語はどれにするとか、フレームワークに何を採用するかとか、そういった大きな決定事項も重要ではありますけれども、それは当然誰もが注意を払います。僕がここで焦点を当てたいのは、もっと細かい部分のことです。

何故かというと、最初に決めたことがルールとなって後々に多大なる影響を及ぼすからです。ソフトウェア開発において統一性は大変重要であるため、最初の決定がたとえマズかったとしても、そのマズい最初のやり方に統一せざるを得なくなることも考えられます。だからこそ些細なことにでも気を遣わなくてはいけません。

例えばファイルとディレクトリの配置構成で階層をもう1段階深くするかフラットにするかだったり、ファイルとディレクトリを命名する際の単語をどうするかだったり、コーディングの際に全く同じことができる2つの書き方のどちらを採用するかだったり。こういった話はどう選ぼうがさほど影響がなさそうに聞こえるかもしれません。

でも1つ1つの選択が後々どう影響を及ぼすか全て予想はできません。例えば後になって、実はあるファイル群を別のディレクトリに置いたほうが効率的だったと気づいても、その構成を前提にプログラムを組んでしまっていると、構成を変えるだけでもものすごく大変になってしまう可能性もあります。

ということで、色々な物事が決まる前の開発初期段階は、何かを決める際には一つ一つについて「どっちでもいいや」と適当に決めず十分吟味することをオススメしておきます。

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

2014年3月13日木曜日

gitでmasterブランチへのマージを --no-ff で行う理由(コミットグラフ例つき)

gitを用いてローカルリポジトリで開発する際の1つの手法として、ローカル専用ブランチを切って、変更を自分の名前のブランチにmerge --squashで反映する方法を以前紹介しました。

そして、自分の名前のブランチを中央リポジトリへとブッシュし、中央リポジトリへの管理者が各開発者の名前のブランチからmasterブランチにマージするわけですけれども、その際、masterブランチに各開発者の名前のブランチの変更を反映する時には、常にfast-forwardのマージを避けて--no-ffでマージしています。

これはなぜかというと、各開発者の行った変更・修正がどのタイミングでmasterブランチに統合されたのかを明確に記録するためです。

また、コミットグラフを見た際にも、開発者の名前がついたブランチが1直線につながるので綺麗に見えるという利点もあります。

例をお見せしましょう。EclipseのEgitプラグインでコミットグラフを見てみるとこんな感じに見えます。


上の図で、一番左の線がローカル専用ブランチ、真ん中の線が開発者の名前のブランチ(tkasai)、一番右の線がmasterブランチです。
※上から2番目のコミットだけmasterのグラフが左に行ってますが、脳内で右に位置を替えてみてるとすっきりします。

真ん中の線のtkasaiブランチへのコミットは、左の線のローカル専用ブランチ(local/日付)をmerge --squashでまとめたものです。例えば、真ん中あたりのコミットID:689b51aはコミットID:6e1b3b7〜60f3d8e(つまりlocal/14.02.18ブランチにおけるコミット)をまとめたものになっています。そして、tkasaiブランチを任意のタイミングでmasterブランチへと--no-ffでマージしています。ここではローカル専用ブランチをmerge --squashした直後が多いですね。

こうしてみると、いつmasterにどのブランチをマージしたのかが明確にわかります。

ちなみに、Egitのコミットグラフは現在のブランチに直接つながりのないブランチを隠すことができます。するとこうなります。今度は左の線がmaster、右の線がtkasaiで、さっきの図と位置が逆になっているので注意。


スッキリして見えますよね。最新以外のローカル専用ブランチが省略されてこうなるのです。まだ開発者ブランチが僕一人の分しか無いからこれだけですが、もっと開発者が増えたら、コミットグラフが整理されて見える恩恵はもっと大きくなると思います。

関連記事:gitでローカルリポジトリにローカル専用ブランチを作って開発する

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

2014年3月12日水曜日

Rubyのシンボルについて

これから仕事で本格的にRubyを使うにあたり、しばらくRuby書いてなかったので文法とか色々忘れてましたから、ちょっと勉強しなおしてます。

で、シンボルに完全に忘れてたのでメモ。文字列に似てますが実態は整数というやつです。

シンボルの定義


以下のように書くとシンボルになります。

:hoge


空白やハイフン等を含む場合はダブルクオーテーションも必要です。

:"foo bar"


文字列の intern メソッドでも作れます。

"example".intern


シンボルの意義


シンボルはラベルのようなもので、内部的には整数として扱われるため「一致するかどうかの比較が高速」です。具体的な用途として例えば

・配列のキーとして使う。
・メソッドの引数がいくつかの選択肢をとるような場合の選択肢として使う。

といったものがあります。

参考:class Symbol (Ruby 1.9.3 リファレンスマニュアル)

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

2014年3月11日火曜日

Debianでパッケージからrbenvとruby-install入れて使う

ソフトウェア開発では、成果物をリリースする際にはプログラミング言語のバージョンを固定するため、後からメンテナンスする際にその言語のそのバージョンで固有のバグを再現して修正するため、言語をリリース時のバージョンで実行できるような環境を残して置かなければなりません。また、複数プロジェクトを持つことになった場合は、それぞれのプロジェクトで言語のバージョンが違ったりすると、言語のバージョンを切り替えつつ作業をしなければならなくなります。

そこで、1つのマシン上で特定のディレクトリごとに使う言語のバージョンを切り替えられる仕組みが存在します。Rubyではその1つにrbenvがあります。以前からrvmもあったらしいですが、最近ではより軽量なrbenvが人気で乗り換える人も多いようです(rvmは使ったこと無いので詳しいことはググってください)。

で、開発にDebian7を使ってて、パッケージも用意されてるようなのでrbenvを入れました。ここでは利用するRubyのバージョンは1.9.3-p194としましょう。rubyをrbenv経由でインストールするにはruby-buildパッケージも必要です。

[user@host]% aptitude install rbenv ruby-build
[user@host]% rbenv install 1.9.3-p194
[user@host]% rbenv rehash
[user@host]% rbenv global 1.9.3-p194

~/.zshrc に以下の行を追記します。PATHに$HOME/.rbenv/binを追記するのはrbenvをソースからインストールした場合だけに必要なので、パッケージから入れた場合は下記だけで大丈夫です。

eval "$(rbenv init -)"

これで source ~/.zshrc で読み直すかログインしなおすと、先ほどインストールしたrubyがrbenvの制御下にあることがrubyのパスから確認できると思います。ちなみにgemも同様にrbenvの制御下にありますね。

[user@host]% which ruby
/home/user/.rbenv/shims/ruby
[user@host]% ruby --version
ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-linux]
[user@host]% which gem
/home/tkasai/.rbenv/shims/gem

特定のディレクトリ以下でrubyのバージョンを切り替えるには、

[user@host]% rbenv local <version>

のようにします。するとそのディレクトリに.rbenv-versionというファイルが作られて、使用するバージョンが記録され、次回からrbenvが自動的にバージョンを切り替えてくれます。

さらにgemの管理のためBundlerも入れましょう。rbenvはrubyのバージョン切り替えだけを行うのでプロジェクトごとにgemも切り替えたい場合はBundlerが必要です。インストール後の rbenv rehash を忘れずに。

[user@host]% gem install bundler
[user@host]% rbenv rehash

念のため、ログアウトしてログインし直します。bundleコマンドのパスを調べると、rbenv制御下に入っています。

[user@host]% which bundle
/home/user/.rbenv/shims/bundle

あとは通常のbundleコマンドと同じ使い方でOKです。

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

2014年3月10日月曜日

プログラムは仕様通り動けばいいってもんじゃない

以前勤めてたある職場では、システムの機能追加のために、過去のプログラムの動作を把握する必要がありました。その過去のプログラムは、僕がその現場に入る前からずっと使ってきたもので、僕が会話どころか姿を見たことすら無い人が書いたものです。もちろん、プログラムを書いた当の本人はとっくの昔にその現場を去っています。連絡先も分かりません。よくありがちな話ですよね。

そんでもって、やっぱりまともなドキュメントなんてあるわけがなく、ソースコードを読むしかなくなったわけですよ。それも「if文が7階層もネストした」ような酷いソースコードをです。これ実話ですよ。

仕方ないんでプログラムの動作を丁寧に追って、分かりやすく図式化した資料にまとめておいたら同僚の方々に凄く感謝されました。かなり大変だったので、役に立ってよかったと思いましたね。でもやっぱり他人のプログラムを解読するのはキツイ作業ですよ。資料作るのも、多分プログラム本人が作ったら10分の1の時間で済んだでしょう。

ホント、プログラムは仕様通り動けばいいってもんじゃないですね。可能な限りオブジェクト指向などを利用して分離性を高くして欲しいですし、if文やfor文などの制御構造も、条件を整理して流れを分かりやすくして欲しいと思います。論理的に等価なままネストを減らすことだってできますから。

ドキュメントは、まあ理想的には揃っていたほうがいいです。ただ現実的にはそこまでできない現場が有るのは僕も分かります。けど、せめてプログラム内に重要ポイントをまとめたコメントくらい入れておいて欲しいです。

結局プログラムは1回作ればそれで終わりで二度と見ないなんてことはなく、常に更新したり参照されたりするものです。仕様通り動けばいいってもんじゃないですね。

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

2014年3月9日日曜日

いつでもプロジェクトを引き継げるように意識する

まだプロジェクトの初期段階で、画面設計やらフレームワークの準備も手を付け始めた所ですけれども、僕が最初から意識しているのは「いつプロジェクトを別の人に引き継ぐことになってもいいようにする」ってことです。

それは例えば、僕の頭の中にしか無い事柄をなるべく少なくするということ。つまり必要事項をきちんと文章に残すという意味です。もちろん、全てのノウハウを書く時間の余裕はないですけれども、例えばネットで調べればそれほど苦労せず辿り着くようなことは書かなくていいわけで、そうではなくて僕がメモを残さないと、ネットで調べても意味不明になってしまうようなことに関しては、きちんとメモを残すということです。

他にも例えば、情報が分散しないようにすること。あることについて書いたドキュメントが複数の場所に散らばらないようにしますし、もしどうしても場所を分散する必要があるなら一箇所のファイルにどの情報がどの場所にあるのか一覧をつくります。

ドキュメントだけでなく、プログラムの構成もそうですね。見通しを良くするというと。例えばファイルの命名規則やディレクトリ構成を、初めて見た人でも分かりやすいように意識します。標準的によく使われる構成があるならそれに従うようにします。それでもわかりにくいようなら、ドキュメントに一言メモを書いておきます。

もちろん、本当に今からいきなりプロジェクトを引き継ぐことになる可能性は低いわけですけれども、いつでも引き継げるような体制をとることは、様々なメリットを生み出します。自分でもプロジェクトの細部に渡るまでしっかり把握するよう意識しますし、抜け漏れやあやふやな点もないように努力もしますからね。

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

2014年3月8日土曜日

Ruby開発にBundler使ってGitで管理する際のポイント

Rubyを使って開発を進めてて、必要なgemパッケージをBundlerで管理することにしました。Bundlerは開発環境と同じgemパッケージを本番環境に揃えることに関して管理を楽にしてくれるので安心便利ですよね。

Bundlerの使い方そのものについては詳しく解説された良いサイトが多数存在しますので省略させて頂いて、ポイントだけ書いておこうと思います。プロジェクトをGitで管理していることも考慮に入れてます。

bundle install の際は --path vendor/bundle オプションをつける


--pathオプションをつけないとシステムデフォルトの位置にgemパッケージがインストールされます。しかしせっかくBundlerを使うのであれば、プロジェクトごとに個別にgemを管理したほうがよいですね。プロジェクトごとに違うバージョンを使うこともありえますし。ということでインストール先を指定するため--path vendor/bundleオプションをつけます。vendor/bundleという名前にするのは、後で出てくる--deployment オプションと統一するためです。

Gemfile と Gemfile.lock だけをGit管理対象とし、.bundle ディレクトリと vendor/bundle ディレクトリは .gitignore で無視する


上記の --path 指定をして bundle install を実行すると、.bundle/configという設定ファイルも自動的に生成されます。このファイルにはインストール先が記録してあって、次回から--path指定をしなくても済むようになります。しかし.bundleには環境固有の設定も入るようなので、Git管理対象にはしないほうが良さそうです。もちろん、gemパッケージのインストール先であるvendor/bundleディレクトリも管理対象から外します。

そのため、Gitをクローンした各開発者には個別にbundle install --path vendor/bundleを実行してもらう必要があります。(gemをアップデートした際には bundle update)

デプロイする際は --deployment オプションをつけて bundle install しておく


bundle install コマンドにはデプロイ用のオプション --deployment があります。これは、vendor/bundle 内に必要な依存gemパッケージを確実に揃えるとともに、その後Gemfileを変更してバージョンを変えられないようにします。デプロイをスクリプトで自動化している際には、どこかのタイミングでbundle install --deployment を行うようにしておくといいでしょう。

基本的に--path vendor/bundle を指定して bundle install を実行するとvendor/bundle 内に必要な依存gemパッケージは揃うと思うんですが、システム共通でインストールしたgemが既にあるとインストールしてくれないみたいbundle install --disable-shared-gems vendor/bundle とやればいいみたいですが、だったら固定操作まで一気にやってくれる--deployment使ったほうが楽でしょうとうことで。

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

2014年3月7日金曜日

一番経験あるのはPHPだけど一番好きなのはRuby

Web系アプリソフトウェア開発者としての僕のキャリアにおいて、開発に使用したプログラミング言語は大半がPHPです。だから最も経験があって慣れているのはPHPなんですけれども、でも一番好きかと言われると、そうでは無いですね。

なんていうか、PHPって気をつけないと行儀の悪いプログラミングが容易に出来てしまいますからね。プロジェクトによってはソースコードが無法地帯で世紀末と化している場合もあります。書いたプログラマの秘孔を突きたくなりますができません。残念。

じゃあ一番好きな言語は何だと言われれば、そりゃやっぱりRubyです。学生時代の頃、研究室で自分の研究をサボりつつする傍ら、Rubyで皆が研究で使うツールを開発していたことがありまして、その時にRubyの魅力に浸かりました。

Rubyはやりたいことが素直に書けるのが魅力ですね。Rubyを作ったまつもとゆきひろ氏も、書いていて楽しくなるような言語にしたと確か言ってましたし、実際そのとおりだと思います。

ついでに言うと僕がオブジェクト指向について初めてまともに理解したのもRubyを書いている時であり、オブジェクト指向によるプログラミングを初めて本格的に行った言語でもあります。その意味でも思い入れがあるんですよね。

で、今進めているプロジェクトでは、メインの部分で僕が自分で使う言語を決めていい状況にあり、ついに仕事でRubyをメインに使えるということで非常にワクワクしてます。今ちょうどRuby周りを準備中でテンション高いです。そのうちこのブログにもRuby関係の投稿をしていけると思います。

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

2014年3月6日木曜日

仕様書を書きつつ別作業

現在プロジェクトの初期段階にあり、仕様書を書いておりますけれども、ドキュメントをずーっと書いてるとさすがに飽きてきますし、かなり脳味噌を使うので疲れるということもあります。

そこで仕様書を書きつつ、区切りのいいところで後の作業で必要になるサーバの構築・設定とか使う言語やフレームワークについて調べたりとか、ドキュメンテーション以外の作業を挟むようにしてます。

これがコーディングですと結構長時間どころか何日も集中して作業し続けたりできるんですがね。不思議なもんです。脳の使う部分が違うんでしょうね。ドキュメンテーションもコーディングもどちらも面白くて頭を使う作業ではありますけれども。

ということで、ドキュメンテーション以外にも色々やることはあるので適当に時間を配分しつつ進めていこうと思います。この辺の作業への時間配分が自由にできる今の環境はありがたいですね。

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

2014年3月5日水曜日

画面仕様書にはどこまで詳細を書くか

仕事でソフトウェア開発をしていて仕様書を書いてますけれども、今週から画面設計の部分にとりかかりました。そこで考えるのは、仕様書に画面設計の詳細をどこまで書くか、ということです。

以前仕事をしたある職場では、画面仕様書に関係する関数名や変数名の一覧まで書いてありましたけれども、ちょっとそこまでやるのはやり過ぎだと思います。実際コードを書く際にいくらでも変更される部分ですし、いちいちドキュメントを修正していたら手間がかかりすぎてそのうち仕様書を見向きもしなくなるでしょう。

逆に、以前アジャイル開発をした時は画面設計というはむしろ仕様書自体、開発中は全く手を付けていなかった状態でした。それはそれで最後に時間がなくなり、結局まともな仕様書を残すことはできませんでした。まあ、それは仕様書を残す必要のない性質のプロジェクトだったからよかったものの、そうでなければ少々まずい事態でしたね。

その辺の落とし所は一概にこうすればいいというものではなく、プロジェクトごとの個々の状況に応じて変わってくるんだろうなと思います。今回の僕の方針としては、機能を文章で説明しつつ、ごくごく簡単なワイヤフレーム(白黒で装飾の全くないもの)でボタンやテキスト等の要素の配置を示すことにしたいと思ってます。詳細に立ち入りすぎず、かつ機能の説明を最低限のラインで果たしているという感じを目指します。

あえて、「全ての機能を完全に」書くのではなく、文章の文脈や図などを見れば必然的に想像できることについては記述を省略する・・・って構成にできれば理想的です。この加減や方法については今後も研究していきたいと思います。

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

2014年3月4日火曜日

エンジニアのための「セーブポイント」仕事術

よくロールプレイングゲームだとセーブポイントってあるじゃないですか。最近のゲームはいつでもセーブできるものが多いと思いますけど、昔は特定の場所でしかセーブが出来なくて、それをセーブポイントと呼んだわけですよ。うっかり失敗して全滅して、セーブポイントまで戻らざるを得なくなった、なんて経験した諸氏も多くいらっしゃることでしょう。あれは実に時間を奪ってくれましたよね。

さて、ITエンジニアとして仕事してますと、なんか仕事にも「セーブポイント」に似たようなものがあると感じるんですよね。例えばプログラミングだったら、とあるモジュールのコードを書いていて、最後まで書き終わればそれで「セーブポイント」に達したようなもので、そこで仕事をやめても次から続きをすんなり開始できるわけですが、途中でやめて帰ると、次の日前日にやってたことを思い出さなくちゃいけなくなり、結局前日に書いたコードを読み直さないといけなくなってしまうので、それが以前の「セーブポイント」まで戻される感覚に近いわけです。他の仕事、例えば事務作業なんかだと別にいつ仕事を中断しても続きから始められるのかもしれませんが、エンジニアの仕事だとそうは行かないと思います。

その意味で、自分の仕事はどこまでやったら「セーブポイント」なのか常に意識しておくと仕事の効率を上げることができます。例えば、帰る予定の時刻まで残り1時間しかない状況で、「セーブポイント」まで2時間かかりそうな仕事を始めると、結局「セーブポイント」に達する前に帰る時刻になってしまい、無駄が生じるわけですよ。

ここで注意していただきたいのは、「セーブポイント」と言っているのは仕事の全体量を言っているのではないってことです。上で挙げた例でも、残り1時間だから「1時間で終わる仕事をしよう」と言いたいのではないのです。例えば全体が6時間かかる仕事でも、「セーブポイント」が1時間おきにあるのであれば問題ないわけですね。

もしフレックスタイム制など時間の調整の自由が効くのであれば、日々の勤務時間を「セーブポイント」のキリの良い時間に合わせるという手も使えます。そうすれば仕事の効率をかなり上げることができます。

ということで、普段から仕事をする上でも「セーブポイント」を見つけるようにしておくといいですね。

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

2014年3月3日月曜日

派遣エンジニアとキャリアパス

僕も昔、派遣エンジニアをやっていたことがありまして。いわゆる特定派遣ってやつですね。どっかの会社の正社員でありながら職場は別の会社で、そっちに毎日通うというやつです。僕自身の現場経験を思い出してみてもこの形態のエンジニアは多く、IT業界にはかなりの人口がいるはずです。

別に派遣エンジニアそのもの自体は悪くもないと思うんですよね。1つの組織にとどまらず様々な現場を経験するのはそれはそれで面白いと思いますし、バリエーション豊富な経験というのはエンジニアとしての財産であり武器になります。

ただし問題は、特にIT業界の構造として年齢の上昇とともに派遣エンジニアの受け入れ先が少なくなるということです。これはIT業界の構造が原因ですね。

派遣エンジニアの仕事が発生する主な場面の1つとして、システム開発を請負う会社がプロジェクトを受注し、そこで自社で足りない人員を募集するというものがあります。その際に人員募集の情報をエンジニアを擁する会社に流して、条件に合うエンジニアを派遣してもらうわけですね。派遣されたエンジニアは、受け入れ先企業ではチームリーダーの下に就くわけですが、プロジェクトのチームリーダは受け入れ先企業の正社員である場合が多いです。そしてその際に、チームリーダーより年齢の高い派遣エンジニアがいると気まずいだろうと受け入れ先企業は考えるんですね(僕自身はそんなのどうでもいいと思いますが)。だから、条件として明記してなくても、年齢の高いエンジニアは敬遠される傾向があります。

また、派遣エンジニアは炎上したプロジェクトに増員要員として現場に集められるケースが多々あります。そういったプロジェクトはスケジュールが既にかなり伸びてしまっており、赤字の危機(もしくは既に赤字状態)にあります。ということは追加費用はなるべく抑えたいわけです。だから、集める派遣エンジニアも安く済ませたいわけで、すると単価の低い若いエンジニアが選ばれてしまいます。(それで実際大丈夫なのかというと全く違いますが。)

このような事情があるいせいで、派遣エンジニアは年齢が上がると仕事が少なくなるんですね。

僕がIT業界に飛び込んだ時はこういう業界構造を理解してませんでしたし、最初に入った会社がエンジニア派遣で主に儲けていることも分かっていませんでした。だいたい求人情報には「エンジニア派遣やってます」とは書いてません。一般派遣と違って正社員ですし、求人情報見ても区別はつきません。ある程度業界経験積めば分かりますけどね。

それでも最初の切っ掛けをつかませてくれたという意味で派遣エンジニアは大きな意味がありましたし、業界の構造も知ることが出来ました。最初のステップとしてはアリだと思ってます。

ただ、今派遣エンジニアの人は、将来のキャリアパスを見据えて次のステップは早めに考えておくべきとは思います。ある程度経験を積んだら、例えば独立してフリーのエンジニア(個人事業主)になるとか、派遣エンジニアではないビジネスを自社でしている会社に転職するとかですね。ちなみにエンジニア派遣会社の営業になる人もいますが、オススメできません。(ここで書くと長くなるんで別の機会に。)

本当は、業界全体がもっと変化して年齢の高い派遣エンジニアも積極的に受け入れられるようになっていくのがベストだと思います。実際、様々な現場で経験を積んだエンジニアは頼りになりますよ。チームリーダより年齢が高いからと避けるのはもったいないし、高い報酬を出すだけの価値はあります。

しかしいかんせん、業界が変化を待ってたら先に自分が食えなくなるかもしれませんから、やっぱり対策を打つしかありません。

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

2014年3月2日日曜日

エンジニアの大切な要素「しつこさ」について

ITエンジニアに必要な知識なんて無限にあるわけですよ。ある物事についてあらゆる知識を持っている人を「生き字引」なんて言ったりしますけれども、ことITエンジニアの世界においては「生き字引」ってあまり価値ないんですよね。何故かというと1つの理由は必要な知識はネットにあるので覚えておく必要がない、もう1つの理由は新しい技術が次々に生まれるので、古い知識は凄まじいスピードで役に立たなくなるということです。(だからといって知識の蓄積に意味が無いと言っているわけでは勿論ありません。)

さて、いくら勉強しても尽きることのない知識の広大な海の中で僕らエンジニアは成果を出していかなければならないのですが、その際大切になってくる要素の一つが「しつこさ」であると僕は考えてます。

結局日々仕事に取り組む中で目の前に現れてくる問題というのは、自分にとって未知の問題であるわけです。そもそもIT関係のプロジェクトというのは今まで無かったものを実現したり、新たな仕組みを構築したりするわけで、その意味でルーチンワークにはなり得ないんですね。それがこの仕事の面白いところであり、同時に難しいところでもあります。ともあれ、仕事の性質上、ぶち当たる問題は未知の問題であるというのは納得頂けると思います。

だから問題に取り組む時は常に自分の持たない知識を調べ、試行錯誤を重ねなければなりません。ところが、ここで分かれ道があります。

例えば、あるシステム開発プロジェクトで開発を進めるうちに、ある機能の実現について問題にぶち当たったとします。エンジニアとしては、諦めてそれは技術的に不可能ということもできます。しかし、もっと調べたり考えればもしかしたら実現可能かもしれません。

じゃあ、実現可能な方法を発見できる、あるいは考え出せるかどうかは何で決まるのか。知識?経験?いえ、上で述べたように、過去の知識や経験はすぐに陳腐化する業界です。多少はアドバンテージになっても、決定的な差にはなりません。

だからこそ、僕は「しつこさ」が重要だと思ってるんですよ。結局のところ、問題にぶち当たったら僕らエンジニアはほとんど同じスタートラインに立つわけです。過去の知識や経験はほんの数歩のリードくらいにしかなりません。その状況において、問題を解決できるかどうかというのは、やっぱり諦めの悪い人間、すなわち問題が解決するまでしつこく粘れるかどうかで決まるんじゃなかと思います。

ITエンジニアにとっての本当の「経験」とは、問題のぶち当たった時の「しつこさ」を獲得すること、粘リ方を覚えることなんじゃないかとさえ思えるんですよね。

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

2014年3月1日土曜日

ドキュメント管理のためSphinxを導入してGitで管理

ソフトウェア開発においてはドキュメントの変更は頻繁に起こるものです。といいますか、「起きるようにすべき」ってことなんですがね。

ドキュメントの更新は得てして(非常に高い確率で)放置されがちなタスクです。古くなってカビとキノコが生えたドキュメントは役に立たず、誰からも参照されなくなります。そして、リリース直前になって慌てて開発チームが更新作業に追われるのですね。

昨今ではすっかり市民権を得た(と少なくとも見える)アジャイル開発においても、「ドキュメントよりも動くソフトウェアを重視する」という方針のおかげか、ドキュメントは開発中は手を付けず、最後にまとめて作るやりかたも実際に行われてるという話も聞いたことがあります。

僕自身、アジャイル開発を本格的に行った以前のプロジェクトにおいては、開発中にドキュメントは作りませんでした。しかし考えてみれば、そのプロジェクトはWebサービスの開発であって、誰かに仕様を1つにまとめて伝える必要性がそこまで高くないものだったのです。しかし今取り組んでいるプロジェクトは製品として外部に出荷することを想定しており、その意味では仕様をまとめる必要性があります。

しかし、最後にまとめて変更するやり方ではそもそも大変ですし、ミスも生まれやすくなります。何より、ひたすらドキュメントの更新をするのはあまり楽しい作業ではありません。やはり、ドキュメントを開発にともなって随時変更していきたいところです。しかし、それは放置されがちになることは既に述べました。

プログラムのソースコードがなぜアジャイル開発のような頻繁な変更にも耐えられるのかといえば、SubversionやGitのようなバージョン管理システムの貢献が大きいです。コードのどの部分がいつ誰によってどう変更されたのか明確に把握できてこそ、一度書き上げたコードの一部をかいつまんで変更し続けることが容易になるのですね。そうでなければチームは大混乱に陥ります。その意味で、バージョン管理システムが発達していなかった時代、ウォーターフォールしか選択肢がなかったのも頷ける話です。

つまり、ドキュメントの変更を開発に伴って頻繁に行うには、どの部分がいつ誰によってどう変更されたのか把握できるようにしなければなりません。残念ながらExcelやPowerPointではこのことは実現が非常に困難です。

だったら、もしバージョン管理システムによってドキュメントを管理できれば、開発しながらドキュメントも書くということが実現できそうです。そのためには、ソースコード管理システムによって変更を把握できる形式、すなわち「プレーンテキスト」である必要があります。

そこでプレーンテキストからドキュメントを生成する仕組みを導入すればいいと気づくわけですね。有名なものに科学論文向けのTeXがありますが、ソフトウェアのドキュメント向けに開発されたツールの1つとしてSphinxがあります。SphinxはPythonの公式ドキュメントに使われている他、多くのマニュアルやサイトに使われています。

なんか前振りだけで長くなりましたが、まあこういったツールの導入には考え方が重要ですからよしとしましょう。手順自体は大したこと無いんで、簡潔にまとめます。環境はDebian Linuxです。

まず、Sphinxをインストールします。Pythonは既にインストールされているものとします。Debianのパッケージは古いので、公式リポジトリからソースをダウンロードして使います。

$ wget https://bitbucket.org/birkenfeld/sphinx/get/1.2.1.tar.bz2
$ tar jxvf 1.2.1.tar.bz2
$ cd birkenfeld-sphinx-3238dc3d4528/
$ python setup.py build
$ su -
# python setup.py install
# exit

これで/usr/local/bin以下に実行ファイルがインストールされます。次に、ドキュメント管理用のGitリポジトリを用意し、その中でsphinxプロジェクトを初期化します。

$ mkdir foo-doc
$ cd foo-doc
$ git init
$ sphinx-quickstart

sphinx-quickstartを実行すると、幾つか質問されます。その際、プロジェクトの名前と著者名(複数可)だけ答えてあとはデフォルトでいいという説明をよく見かけますが、こんかいはGitで管理する都合上、ソースと生成したドキュメントを分離することにします。以下の質問をされた時に y と答えればいいです。

You have two options for placing the build directory for Sphinx output.
Either, you use a directory "_build" within the root path, or you separate
"source" and "build" directories within the root path.
> Separate source and build directories (y/n) [n]: y

これでSphinxでドキュメントを作成するための基本のファイルが生成されます。 .gitignoreでbuildディレクトリを除外しておきましょう。ドキュメントのソースコードはsource ディレクトリ内にあります。ドキュメントを生成するには、Makefileのあるディレクトリで

make html

などと打てば生成されます。html以外にもpdfなど様々な形式を指定できます。具体的なドキュメントの書き方の詳細については日本ユーザ会のマニュアルなどを参照ください。

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