2014年4月2日水曜日

UbuntuへのRのインストール

Ubuntu 13.10にR3.0.3とRStudioをインストールした時の手順を残しておく。

CRANのインストール手順に従って、Rをインストールする。

まず/etc/apt/sources.list に下記のような1行を追記して、リポジトリを追加する。
deb http://<my.favorite.cran.mirror>/bin/linux/ubuntu saucy/

ただし、<my.favorite.cran.mirror>はをミラーサイト一覧参照して適当なミラーサイトに置き換える。

また、末尾の(saucy/)はUbuntuのバージョンに合わせたコードネームに書き換える。コードネームは下記コマンドで確認できる。
cat /etc/lsb-release

例えば、筑波のミラーからUbuntu 13.10 (saucy)にインストールする場合、次の様になる。
deb http://cran.md.tsukuba.ac.jp/bin/linux/ubuntu saucy/

リポジトリへのアクセスに必要な公開鍵を取得する。
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E084DAB9

リポジトリからRをインストールする。
sudo apt-get update
sudo apt-get install r-base

インストール確認。次のコマンドでRが起動したらOK。
R

続けて、推奨Rパッケージもインストールしておく。
sudo apt-get install r-cran-*

References

2013年12月9日月曜日

Javaのアサーション (assert文) の使いどころ

Javaのアサーションについて、少し調べたことをメモしておく。『言語設計者が考えること』の「12章 Java」で、Javaプログラマへの助言として
assert文を至る所に散りばめること
なんて書かれていたけれど、使いどころがよく分らなかったのが、調べたキッカケ。

アサーションを使用したプログラミング (Java言語仕様) によると、使いどころは次の3つ。リンク先には具体例がもあるので、これを見るとおおよその想像がつく。
  • 内部の不変条件
  • 制御フローの不変条件
  • 事前条件、事後条件、およびクラスの不変条件

この内、3つ目の「事前条件、事後条件、およびクラスの不変条件」のさらに「事前条件」には「publicメソッドの引数チェックに使ってはいけない」という但し書きが付く。publicメソッドの引数が満たすべき事前条件はAPI仕様の一部だというのがその理由。『Java セキュアコーディングスタンダード 』の「MET01-J. メソッドの引数の検証にassertを使わない」に詳しい。
アサーションは、public メソッド内の引数チェックに使用しないでください。

引数のチェックは通常、メソッドの仕様 (または規約) の一部になっており、アサーションの有効/無効にかかわらず、この仕様に準拠する必要があります。アサーションを使用して引数をチェックした場合、不正な引数によってランタイム例外 (IllegalArgumentException、IndexOutOfBoundsException、NullPointerException など) が発生する可能性があります。アサーションが失敗しても、適切な例外はスローされません。

「適切な例外をスローする」とあるけれど、例外は使わないで通常の制御フローを前提にアサーションを使うのか、それともアサーション以外の例外を使うのか、一般解は存在しない。例外設計における大罪や『Effective Java 2nd Edition』の「項目57: 例外的状態にだけ 例外を使用する」が参考にはなるけれど、最後は作ろうとしているソフトウェアがどう振る舞うべきか、自分で考えるしかなさそう。

というわけで、指針は掴めたけれど、簡単な話ではない。

References

2013年11月26日火曜日

FindBugsのDetector Pluginチュートリアルをやってみた

FindBugsのDetectorPluginTutorialを試してみたときのメモ。FindBugs Eclipse Pluginへの追加を想定している。使用したバージョンは次の通り。
  • Eclipse 4.2
  • FindBugs 2.0.2
以下、見出しごとに躓いたポイントをメモしておく。



Creating Our Plugin


Setting Up Eclipse

素直にそのままやって問題なかった。

Setting Up the Classpath

findbugs.jar, bcel.jarに加えて、jsr305.jarもClasspathに追加する必要があった。findbugs.jarが依存しているみたい。

Writing the Bug Detector

そのままDetector codeのサンプルをコピーして問題なかった。

Deployment & Testing

Building

以下2つのxmlファイルは、プロジェクトフォルダーのルートに配置する。書かれている通りだけれど、読み落としがち。

findbugs.xml

コメントにあるとおり、公式サイトと要素名が異なるけれど、こちらの記載通りFindBugsPlugin要素で問題なかった。

サンプルには含まれていないけれど、一行目にXML宣言を追加しておく方がベターだと思う。

messages.xml

そのままサンプルをコピーして問題なかった。

Building in Eclipse

そのままやれば問題ないのだけれど、JAR Exportの設定が色々と初期値と異なる点に注意。間違えるとプラグインとして追加しても、Invalidと表示されて機能しない。一度やれば、jardescからその設定で再ビルドできる。

CIするためにAntタスクとして定義したい。

Loading Our Plugin

GUI (Eclipseの設定画面 Java > FindBugs) から追加した。EclipseのpluginsフォルダのFindBugsのpluginフォルダに追加しても、うまくいくかも試したい。


ここまでやって、Quizのコードスニペットを含むクラスでFindBugsを実行してみたら、期待通り動作した。めでたし、めでたし。

以下は、覚え書き。

このチュートリアルの"Debugging"はまだ書かれていない。テストケースの簡単な説明はFindbugsTestCasesにあるけれど、ここを読むだけではちょっと分りそうにない。実際のテストケースを見ながら、試行錯誤が要りそう。

チュートリアルではなぜこうするのか分らないけれど、Plugins4FindBugsで補完できる。Detector Pluginの概要が記載されている。

Eclipse Pluginに特化した内容として、コメントでFindBugs In Eclipse Tutorialが紹介されているのに、後から気がついた。ただ、FindBugs 1.3.9よちょっと情報が古い。

References

2013年8月21日水曜日

Javaのデコンパイラと難読化ツール

Javaのクラスファイルをデコンパイルしたソースコードは読みやすいと聞いて、「どれくらいソースを再現できるのか?」と「難読化したらどれくらいデコンパイル結果が読み辛くなるのか?」について試してみたくなった。というわけで、まずはデコンパイラ (decompiler) と難読化ツール (obfuscator) ついて調べてみた。今回はツールの調査だけで、実行方法についてはおいおい。なお、調査方法は、GoogleとStack Overflow頼み。

デコンパイラはJava Decompilerでいいのかな。デコンパイラとして真っ先に思い浮かんだJADは、更新が止まっていた。Java DecompilerもEclipseプラグイン・JD-Eclipseが最近のEclipseだと動かないようだけれど、少なくとも、Mchr3k - JDEclipse-Realignというフォークがメンテナンスされている。
Java Decompiler (Yet another Fast Java decompiler) has:
  • explicit support for decompiling and analyzing Java 5+ “.class” files.
  • a nice GUI:
decompiler - How do I "decompile" Java class files? - Stack Overflow
ともあれ、こちらはすんなり使えた。クラスファイルからほぼソースそのままにデコンパイルできてビックリ。Live Demoもある。

難読化はProGuardが良さそう。予備知識が無いので手探りだけれど。こちらは現在もアクティブな様子。最近はAndroidアプリの難読化に力を入れているよう。
Well, you can find here a list. ProGuard is pretty good. I've used it myself, but only to "minify" Java code.
obfuscation - Best Java obfuscator? - Stack Overflow
ただ、こちらは簡単には使えなさそう。設定が必要そう。幸い公式サイトのマニュアルが充実しているようなので、それを見ながらもう少し調べよう。

ところで、難読化すると、クラスやメソッドなどの名前が変わるから、リフレクションAPIを使っていると実行時例外が送出される。けれど、ProGuardのIntroduction > Reflectionによると、典型的なリフレクションAPIに対応しているみたい。

References

2013年8月3日土曜日

Out parameter, collecting parameter, visitor pattern

『Effective Java (第二版)』の「項目15 可変性を最小限にする」では不変オブジェクト (Immutable object) を推奨している。これは状態を持たないから、シンプルに扱える。反対に状態を持つ可変オブジェクト (Mutable object) は、扱いに気を遣う。扱おうとしているときにどういう状態なのか意識しないといけない。状態に起因したバグがあったら、最悪、状態が変更されている場所を全て確認しないといけない。

これに真っ向から対立しているのが、Out parameter。状態を変えるために渡す可変オブジェクトのことを指す。Webを検索してみると、アンチパターンとして紹介されている記事が見つかる。

でも、"Collectiong parameter"として『実装パターン』や『パターン指向リファクタリング入門』で紹介されていたりする。また、『パターン指向リファクタリング入門』では、その延長線上に"Visitor Pattern"を適用したパターンも紹介されている。

確かにこちらの方が合理的なケースもありそう。でも、基本的にはあまり使わない方がよさそう。コマンドとクエリは分離するのが原則だ。使うなら、Javadocに明記するなりしないと混乱を呼びそう。C#のoutキーワードに相当するものがJavaにはないから、引数の状態を変えるかどうか宣言だけから読み取れない。

ところで、out (C#)に使用例として「メソッドが複数の値を返すようにする場合に便利」だなんて書かれている。同時に扱いたい複数の値があるなら、クラスとしてまとめた方が読みやすくないだろうか。原則として、入力を与えたら戻り値が返ってくる関数として考えたい。

References

2013年7月6日土曜日

モンスターメソッドを解体する

『レガシーコード改善ガイド』の第22章「モンスターメソッドを変更する必要がありますが、テストを書くことができません」を自分なりに整理して、モンスターメソッドへの対処方法を要約してみる。

何をどこまでテストすれば?

まず、どういう種類のテストを書こうとしているか考える。それには、第13章「変更する必要がありますが、どんなテストを書けばよいのかわかりません」が役に立つ。そこでは、〈仕様化テスト〉と〈狙いを定めたテスト〉が紹介されている。〈狙いを定めたテスト〉を書くのが現実的だろう。モンスターメソッドの振る舞いは多様だから、いきなり全体を対象とした〈仕様化テスト〉は書けないことが多そう。

次に、モンスターメソッドを読み込んで、狙いを定める。どこまで狙いを絞り込めるかは、モンスターメソッドの作りと必要な変更によってケースバイケースになる。少なくとも自分にとっては、技芸の世界で、筋道立った説明をできない。

狙いが定まったら、検証方法を考える。この時、検証対象が一意に識別できなかったり (例: 別のブランチから同じ結果が返ってくる) 、テストから見えなかったりしたら、〈検出用変数〉または〈クエリメソッド〉を導入する。この時点では、これ以上の編集は避けた方が無難だと思う。やり過ぎると〈編集して祈る〉のと変わらない。

テストを書く

ここまでで、何のためにどの範囲でどんな検証をしないといけないか、具体的になってくるはず。ここまで来たら、テストを書き始める。書き始めたはいいが、モンスターメソッドを持っているクラスをインスタンス化できなかったり、モンスターメソッドの引数をインスタンス化できなかったりすることが多いと思う。その場合は、別の章を参照して対処する (ここでは深入りしない)。
  • 第09章 このクラスをテストハーネスに入れることができません
  • 第10章 このメソッドをテストハーネスで動かすことができません

変更とメソッド抽出

無事にテストが書けたら、実行してパスすることを確認する。この後、必要な変更を行うか、〈メソッドの抽出〉を行うかは、悩ましいところ。変更が局所的なら先に変更してもいいと思う。逆に変更がモンスターメソッドのあちこちに散らばるようなら、先にメソッドを抽出しておかないと後が苦しくなる。いずれにせよ、ここでは変更については触れずに、メソッドの抽出についてまとめる。

メソッドを抽出するときには、抽出後に残るメソッドの形を想像しておくと、どういう単位で抽出すればいいか方針を決めやすい。残る形には、〈骨組みメソッド〉と〈処理シーケンス〉の2種類がある。

〈骨組みメソッド〉は制御構造だけを持っていて、条件式や各条件下の処理はメソッドに任せてしまう。『実装パターン』だとConditionalに対応する。『デザインパターン』で例えるとFacadeやMediatorのイメージになる。

もう一つの〈処理シーケンス〉は単に順番にメソッドを呼び出していく。『リーダブル・コード』の無関係の下位問題の抽出を行うイメージ。「いちいちメソッドにするほどの問題ではないんじゃ?」と思っても、メソッドにして意図に即した名前を付けておくとリーダビリティが上がるはず (『実装パターン』のExplaining Message)。

どちらが適しているかは、モンスターメソッドの元々の役割によって変わる。大抵の場合、モンスターメソッドは、実装コストが低いところに追加が集中した結果であって、最初からモンスターメソッドとして生まれたわけではない。処理の振り分けが役割だったなら骨組みメソッド、抽象度の高いAPI提供が目的だったなら処理シーケンスを残す方が自然だと思う。

どういう形を残す決めたら、メソッドを抽出する前に、抽出したメソッドのテストを書く。先にテストを書けばレガシーコードは生まれない。アジャイルじゃなくたって、TDDした方がいいと思う。

さらに分割

ここまで来たら、細かい粒度でテストできるようになっている。でも、モンスターメソッドを持っているオブジェクトは、得てしてGod Objectだったりする。抽出したメソッドを〈メソッドオブジェクト〉として取り出して、委譲するように修正することも考えていく。つまり、『レガシーコード改善ガイド』の〈メソッドオブジェクトの取り出し〉、『リファクタリング』のReplace Method with Method Objectを行う。

References


2013年5月18日土曜日

JavaScriptで依存性を排除するためにデフォルトパラメータを導入する

JavaScriptのクラスHogeをテストしたいのだけれど、次のような状況でそもそもインスタンス化が大変な場合にどうするか? という話。
  • Hogeはコンストラクタ内で別のクラスFugaをインスタンス化してプロパティに設定している。
  • Fugaはインスタンス化の際にサードパーティ・ライブラリのAPIを大量に呼び出している。
  • サードパーティ・ライブラリは、開発環境では使えない(例えば、REST APIを提供するサーバがまだ立っていない)。
この場合をコード例で表してみる。サードパーティ・ライブラリが使えないため、Fugaのコンストラクタ呼び出しでエラーが発生し、Hogeをインスタンス化できないとする。
Hoge = function () {
  this.fuga = new Fuga();
  // ...
}
// ...
Fuga = function () {
  this.thirdPartyLibrary = new ThirdPartyLibrary();
  // ...
}
// ...

FugaがThirdPartyLibraryをラップしているから、テスト時にはテストダブルに入れ替えたい。でも、そもそもHogeもFugaもインスタンス化できない。

こんな状況に対応するためのリファクタリングとして、『レガシーコード改善ガイド』は25.14「コンストラクタのパラメータ化」か、デフォルト引数の追加を紹介している。オーバーロードのないJavaScriptでは、コンストラクタをパラメータ化できないので、デフォルト・パラメータを指定する。

デフォルト・パラメータがtrueと見なせる(false、null、0、""、undefinedのいずれでもない)なら、こんな風に短く書ける。||は真偽値ではなくてfugaを返す性質を利用している。
Hoge = function (fuga) {
  this.fuga = fuga || new Fuga();
  // ...
}
// ...

もっとロバストな書き方は次の通り。こちらは、デフォルト・パラメータがfalseと見なされる場合も使える。実用的なのは、デフォルト値が0やfalseの時。
Hoge = function (fuga) {
  if (typeof fuga === 'undefined') {
    fuga = new Fuga();
  }
  this.fuga = fuga;
  // ...
}
// ...

References