開発環境に関わるメモ

今月で今やってる仕事の契約が切れるので,ここで培ったノウハウなどをメモしておこうと思う。
しかし,今後この手の開発系の仕事ができるとは限らないってのが悲しいところ。

プロジェクトポータルまわり

とりあえず,Subversion(SCM), Trac(ITS/Wiki), Hudson(CI)は必須。この3セットがないプロジェクトなんてうんこ。
とにかくTrac-Subversionの連携が強力なので,Subversion以外のSCMは無視していい。HudsonはCIつうよりプロジェクトダッシュボードとして使うのが吉(数あるプラグインを有効利用しよう)。


Subversionといえば,ブランチ-マージは必修科目。これホントに便利で,もうブランチ使ってなかった時が信じられないってくらいに便利。ただ,ブランチの運用をはじめたのはメンテナンス・フェーズに移ってからで,初期開発時はメインライン一本でやっておりましたよ。はい。


今回やってたブランチの運用ルールは,こんな感じで,trunkが安定ラインとリリース候補ラインを兼務。マージしたら,ブランチのフォルダ名を「-CLOSED」にリネームするのが,ちょっと異端。

ビルドスクリプト

もうAntでいい。:-)
Mavenの魅力は,インハウス・リポジトリを用意できるかどうかだと勝手に思っているので,用意できなきゃムリしてMavenizeする必要もないかなと。


ビルドスクリプトbuild.xmlを使うかどうかは,NetBeans使いがいるかどうかで思案したほうがいい(あたしは,build.xmlは使わない事にしている)。それと,XML嫌だからAnt以外のビルドツール使うってのは,あんまりオススメしない。


ビルドスクリプトとCIネタであるが,ビルドした生成物にはビルドナンバーとリリースビルド/スナップショットビルドなどがわかる識別子を必ず埋め込むこと(そんでもって,その確認手段も)。これ,とっても重要。


あと,ビルドスクリプトは目的に応じて数種類作っておくことをオススメする。

テスト

JUnitは鉄板。Seleniumは便利なんだけど,CIで自動運転させるのにちょいと工夫がいるのが難点だが,これほど便利なツールはないので,多少無理してでも使うべき。
JUnitは工夫次第で,プログラムの構造検査や耐圧テストにも使える。さらに工夫すれば,目的別にJUnitのテストハーネス置き場を変えた方が良い(下記参照)。

src/
 |- test/       ... 普通の単体テスト
 |- stress/     ... 耐圧テスト用
 +- inspection/ ... 品質検査用

カバレッジは取れるんだったら取っておいた方が良い。レポートの見栄えの好みでCoberturaを愛用していたが,インスツルメンテーションが不要なEMMAのほうが良かったんじゃないかと最近では思っている。
理由は先の目的別JUnit。特に耐圧テストなどは,いちいちカバレッジ取ることないし,むしろカバレッジ取得にかかるオーバヘッドが邪魔でもある。そんな場合,Coberturaだとビルドし直し(もしくはクラスパス変更)せにゃならなくて面倒だった。

その他

IDEはもうすぐ6.0も出るし,こだわりがなければNetBeansでOK。使用するIDEが統一してあるんなら,プロジェクトのディレクトリ構成も,そのIDEが得意な構成にしちゃってもいいか?と言えば,CIで自動ビルドとか考えると,あんまりIDEに依存しないほうがイイに決まっている。
メタ情報をExcelで定義するのも構わないが,自動ビルドのさまたげになってはイケナイ(考え無しにVBA組むのもいい加減にしろと)。

正直,みんながどのIDE使うかはどうでもいいのだ。あたしがIDEA使うのを邪魔しなければ,それこそ何してくれても構わない。:-P
#今や,プラグインを自作してでもIDEAを使い続ける所存であります。:-D


利用サイドと信頼関係ができてないと,モジュールをリリースしても難癖付けて適用してくんないことがある。あとで四の五の言わせないように,変更点や変更事由のとりまとめはしといたほうがいい。とりわけ,APIの差分は準備さえしておけば,手間いらずで作れるのでハッタリかますのに便利。


これは開発環境ではなく,実行環境ネタになるが,エラー画面はリッチなほうがいい。例えば,スタックトレースをログするタイミングを奪い取れるのであれば,そんときのシステムプロパティやら業務プロパティやらも一緒にダンプしたほうがいい。
この手の情報は邪魔になることはないぞ。
あと,余力があればアバウトページを作って自己診断情報をいつでも参照できるようにするのも良い...。イヤ,これは余力とは言わず,多少ムリしてでも用意した方がいいな。


開発環境,実行環境の両方に言えることだが,「EJBEARなんてうんこ」。WARのほうが取り回しが簡単なので,WARで済みそうならWARにとどめた方が全然良い。どうしてもEARじゃなきゃイケナイ場合もあろうが,そんなときは自分の身の上を呪うが良い。:-P


あ,そうそう。プロジェクトの運営スタイルはスクラムが望ましいってのは,今さらだから言わないよ(って言ってるじゃんか)。

プラグイン作って覚えたことを淡々と記録するよ(GUI編その3)

間を開けすぎると忘れてしまうなぁ...

RawCommandLineEditor

それなりに便利なUIパーツ。


上図のような外観(キャプションは別)を持ち,右端のアイコンをクリックすると,下図のようなダイアログが表示される。


名前からもわかるように,コマンドライン・オプションみたいな眺めの文字列を入力するのに便利なテキストフィールド。ダイアログのエディタ部分に入力した改行はスペースとして扱われるので,RawCommandLineEditor#getText()で得られる文字列に改行が含まれることはないってワケ。


用途は限定されると思うが,それなりに便利。なお,ダイアログのキャプションは,RawCommandLineEditor#setDialodCaption(String)で設定できる(UIデザイナのプロパティにも dialodCaptionってのがあるんで,UIデザイナからも設定可)。
...ということを今気付いたんで,あとでWinstoneプラグインにも設定しておく。

AddDeleteListPanel

これも名前のまんまな外観を持つUIパーツで,こんなの。


なんのヒネリもないが,あたしみたいにSwing慣れしてない人が,テキストフィールド以外のUIを作らないといけない場合なんかは便利。
おそらく,一番簡単な使い方はこう(AddDeleteListPanelはデフォルトコンストラクタがないので,createUIComponents()中に初期化しないとダメ)。

private void createUIComponents() {
    addDeleteListPanel1 = new AddDeleteListPanel("Add Delete ListPanel", new ArrayList()) {
        protected Object findItemToAdd() {
            String value = Messages.showInputDialog(this, "何か入力してください", "Input Dialog", null);
            return value != null && !"".equals(value) ? value : null;
        }
    };
}

ボタン(Add/Delete)のキャプションを変えたい場合は,こんなコードになる。

private void createUIComponents() {
    addDeleteListPanel1 = new AddDeleteListPanel("Add Delete ListPanel", new ArrayList()) {
        protected void initPanel() {
            super.initPanel();
            myAddButton.setText("Add...");
        }
        protected Object findItemToAdd() {
            String value = Messages.showInputDialog(this, "何か入力してください", "Input Dialog", null);
            return value != null && !"".equals(value) ? value : null;
        }
    };
}

こんだけでもリストに対する追加と削除ができる。ただし,変更はできない。たぶん,AddDeleteListPanelが内包しているDefaultListModelにListDataListener貼っ付けろってことなんだろうけど,そこまでは実装していない。:-P


ついで言えば,AddDeleteListPanelの親クラスは,PanelWithButtonsって言うんだが,こいつ継承すれば「左側にパネル,右側にボタン群」みたいなUIパーツが作れるようだ。ただ,そんだけのために,わざわざPanelWithButtonsを継承する利点が思い浮かばないんだけどね。

ダイアログについて

AddDeleteListPanelのコード例に,さりげなく(↓)こんな

String value = Messages.showInputDialog(this, "何か入力してください", "Input Dialog", null);

コードがあったのに気付いたろうか?


いくらあたしがSwingに疎いと言っても,Javaでダイアログっていやぁ,JOptionPaneを使うくらいは知っている。んが,JOptionPaneが作るダイアログは,どうにもIDEAとしっくり来ないようで,ファイル・チューザ同様,ダイアログもIDEA専用のが用意されている。それが,Messagesクラスっていうワケ。


Messagesにどんだけダイアログ生成APIがあるかは,プラグインSDKJavadocで確認してもらうとして,JOptionPaneとの違いだけを紹介しとく(といっても,極端な違いはないよ)。


SwingのJOptionPaneが作ったのダイアログ


IDEAのMessagesが作ったダイアログ


ん...まぁ,キモチの問題だな。:-)

CollapsiblePanel

そのなのとおり,折りたたみするパネル。これは,たまたま見つけただけで,有用かどうかって言われるとビミョーなので,説明もテキトー。


縮んでるとき

広がってるとき

コード例

private void createUIComponents() {
    collapsiblePanel1 = new CollapsiblePanel(new TestPanel(), true, true,
                                             IconLoader.findIcon("/actions/collapsePanel.png"),
                                             IconLoader.findIcon("/actions/expandPanel.png"),
                                             "Collapsible Panel");
}
Notification Popup

エラーとか起きたときに,画面右下からせり上がってくるアレ。


これは,UIパーツではなくてAPIで作るようで,なんか適当な処理中に,こんなコードを書くだけで良い。

WindowManager.getInstance()
             .getStatusBar(project)
             .fireNotificationPopup(
                 new MultiLineLabel("色は匂へど 散りぬるを?n我が世誰そ 常ならむ"),
                 Color.YELLOW);

fireNotificationPopup()は,第一引数にJComponentを受け取るんで,そこにNotification Popupに表示したいパーツを与えればいい。