その手の平は尻もつかめるさ

ギジュツ的な事をメーンで書く予定です

mvn test で findbugs と checkstyle を走らせて,1つでも violation があれば fail させるの術

OSSJava をやっていく場合,ロジックのテストだけではなく checkstylefindbugs などによる静的解析を適用して,それを CI で回していかないととてもではないがやっていけない!!! という感じになるので,そこら辺を何とかしたい.
具体的に言うと mvn test でこれらの静的解析をテストと一緒に走らせて,静的解析が1つでも violation を吐き出したら BUILD FAILURE にしたい (もちろんテストがコケても BUILD FAILURE になる).

ということで以下のように pom.xml を記述してやります.

<build>
  <plugins>
    ...
    <!-- findbugs の設定 -->
    <plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>findbugs-maven-plugin</artifactId>
      <version>3.0.0</version>
      <executions>
        <execution>
          <phase>test</phase>
          <goals>
            <goal>check</goal>
          </goals>
        </execution>
      </executions>
      <configuration>
        <effort>Max</effort> <!-- ここらへんは好みに応じて -->
        <threshold>Low</threshold> <!-- ここらへんは好みに応じて -->
        <failOnError>true</failOnError> <!-- Error が出た時に build failure にする -->
        <!-- 以下ファイル出力系なのでお好みで -->
        <xmlOutput>true</xmlOutput>
        <outputEncoding>UTF-8</outputEncoding>
        <xmlOutputDirectory>target/site/findbugs</xmlOutputDirectory>
        <findbugsXmlOutputDirectory>target/site/findbugs</findbugsXmlOutputDirectory>
      </configuration>
    </plugin>

    <!-- checkstyle の設定 -->
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-checkstyle-plugin</artifactId>
      <version>2.13</version>
      <executions>
        <execution>
          <phase>test</phase>
          <goals>
            <goal>check</goal>
          </goals>
        </execution>
      </executions>
      <configuration>
        <!-- checkstyle のポリシーファイルの場所を指定した場合はここに書く.この場合はプロジェクトルートにcheckstyle.xml が置いてある -->
        <configLocation>checkstyle.xml</configLocation>
        <violationSeverity>warning</violationSeverity> <!-- warning よりレベルの高い警告を violation にする -->
        <!-- 以下お好みで -->
        <encoding>UTF-8</encoding>
        <consoleOutput>true</consoleOutput>
        <outputFile>${project.build.directory}/site/checkstyle/checkstyle-result.xml</outputFile>
      </configuration>
    </plugin>
  </plugins>
</build>

以上のように書いて,mvn test を実行すると test -> findbugs -> checkstyle という順で実行されて便利な感じです.
<executions> の中身と,checkstyle<violationSeverity> の中身でちょっとハマってアレでした.<violationSeverity> の中身はお好みに応じてという感じだと思いますけど,厳格にやっていくなら warning が妥当ではないかと思った次第.


こうしてやると Travis 等の CI で継続的に回してやることもできるので便利.

capture-output-stream というのを書いた

こちらも温泉で出したやつです.Maven Central にもアップしました.


http://search.maven.org/#artifactdetails|net.moznion|capture-output-stream|1.0.0|jar


標準出力や標準エラー出力をキャプチャする君です.キャプチャしつつ標準 (エラー) 出力にも併せて出すという tee-ing にも対応しています.テストとかに使うと結構便利.
PerlCapture::Tiny からインスパイアされています.


Java の場合,STD(OUT|ERR) のキャプチャはめちゃめちゃ簡単*1 なのでわざわざライブラリ化する必要性も薄そうだったんですが,
AutoCloseable が実装されていると try-with-resource でアレコレできて便利だよなーという意識だったので書いた次第.空前の AutoCloseable 期!



ご利用くださいませ.

*1:perlio をいじったりしなくて良い

javadocio-badges というのをつくった

先週の3連休で温泉シバソンというイベントを有馬温泉でやってきて,そこで書いたアプリケーションがまあまあ使えるレベルに達したので公開しました.


シバソンについての詳細は以下のブログを見ていただけると良いと思います *1.僕はこのハッカソンで MacBook Pro の電源アダプタを栓抜きとして使った結果破壊しました.

本題

さて,Maven Central にアップした package の javadoc を参照する時には javadoc.io というサービスを使うと便利です.
(参考: javadoc.io が便利 - blog.64p.org)

http://www.javadoc.io/


基本的に javadoc.io は Maven Central にアップされたすべての package の javadoc を良い感じに参照できて便利なのですが,あんま皆さん使っていない感じがするというかそもそも導線が張られていないというか,とにかくそんな雰囲気だったので,見た目にも楽しいみんな大好き badge 形式にしたら気軽に使えて捗るのでは! ということで作りました.


Heroku の無料プランでホスティングしてるのですぐ使うことが出来ます.
Markdown を例に取ると,以下のように書いてやることで

[![javadoc.io](https://javadocio-badges.herokuapp.com/net.moznion/mysql-diff/badge.svg)](https://javadocio-badges.herokuapp.com/net.moznion/mysql-diff)

こんな感じの badge が出ます.


javadoc.io


なんだかオシャレ!*2 ご利用下さいませ.
そうそう,Heroku は Maven Plugin が良く出来ていて,Java の Web Application のデプロイが楽にできて良かったです.

*1:見返したけどさっぱりわからん

*2:果たしてそうだろうか

“プロトタイピング ― 模型とつぶやき”を読んだ

藤村龍至の“プロトタイピング ― 模型とつぶやき”を読んだ.


これは建築設計に関する本で,プロトタイプの模型を作って,更にそれに改善を加えた模型を作って,またそれを繰り返して……という感じで,設計を完成形に持ち込むという手法が紹介されている (“超線形プロセス”という名前で紹介されている).
すべての過程のプロトタイプ模型の写真が,その時の思考 (試行) の流れと共に時系列順に掲載されていて豪華.考えの移ろいが模型写真の変化と共に見られるので面白い.プロトタイプの模型と一緒にその時の思考がキャプション的に載ってるのは Git のコミットログを彷彿とさせる.プロジェクトのコミットログを見返してみると結構面白いのだけれど,この本はそれと同種の面白さを提供しているように感じる.
また,そのプロセスに従って設計された建物の施工時や竣工後の写真も載っていて,プロトタイプから実際の成果物が導かれる様子は非常に興味をそそる.


前書きの部分に良い事が書いてあって,それは「ルールの一貫していないように見える部分を指摘する」だとか「新しい模型と1つ前の模型を比較して,改善点を見つけて,それを元に新しい模型を作る」だとか「(プロトタイピングをする過程で) ジャンプしない,枝分かれしない,後戻りしない」だとかで,これはソフトウェアの開発にも通じるものがある気がする.

「ルールの一貫していない部分を改善して,一貫性を持たせるようにする」というのは良い設計を実現するにあたってはもはや必須項目とも言えると思う.

「1つ前のリビジョンと現在のリビジョンを比較して新たな改善点を洗い出す作業」というのは今日のウェブサービスにおいては様々な計測手法によって実現可能になっている.あるいはソフトウェアの内部的な話に焦点を当てるとこれは「リファクタリング」と呼ばれる設計構造に起因する作業かもしれない.

「ジャンプしない,枝分かれしない,後戻りしない」というのはソフトウェア開発ではあまり見られない気がする (VCS の branch とか,revert とかはよく使われる) けれど,高速なプロトタイピングの過程ではこれは望ましい制約な気がする.


ものを作って,前と比較して,改善点を洗い出して,その改善点を反映した新しいものを作る.そしてそれをどんどん繰り返していく,という一連の作業はソフトウェア開発では割と一般的になってきている気がしているんだけれど,そうしたプロセスが建築という他分野でも行われている事が分かって面白かった.ソフトウェア開発と似通った手法を採っている分野というのは他にも結構あると思っていて,そうした異分野から学べる点というのは多いのではないかと感じた.


とりあえず,最初の何も無い所からシンプルなプロトタイプがボコッと現れて,それが写真を追うごとに洗練されていってスタイリッシュな最終形まで到達する,という流れを見るだけでも面白い本だったので良い.

殆ど写真がメインの本なので,読もうと思えば10分くらいで読めてお手軽.

たまにはソフトウェア以外に関する本を読みたいね,ということで買って読んだのだけれど,結局ソフトウェアの話題に結びつけてしまった……

ベンチマークを取り続ける為にやってる小技

たしか,実践ハイパフォーマンスMySQL に書いてたテクニックだと思うんですけど.

ベンチマークを取る時に同時に lock file を作っておいて,それが存在し続ける限りベンチを回し続ける,という風にすると何かと便利.

setvbuf(stdout, NULL, _IONBF, 0); // stdout のバッファリングを無効にしておく (しなくても良い)

char *bench_lock_file = "./bench.lock";
fopen(bench_lock_file, "w"); // ここでロックファイル作る

// lock ファイルが存在している間,処理を回し続ける
while (access(bench_lock_file, F_OK) != -1) {
    // ここで何らかのベンチマーク的な処理をさせる
    printf("Bench no Kekka Dayo!\n");
}


これをコンパイルして,

$ ./a.out > ./bench_result.log

という感じでやってやるとベンチの結果が延々延々取れる.
(なお,上のコードでバッファリングを無効にしたのは tail -f 等でログファイルを見たかったからです.)


「ベンチ回すのをやめる!!」という時は

$ rm bench.lock

という風に lock ファイルを消してやると,回っている最中のベンチが回り終わったらプログラムを終了させることが出来ます.


便利!


実践ハイパフォーマンスMySQLMySQL の話だけではなくてこういう技法についても言及されていて有益な感じでした.

実践ハイパフォーマンスMySQL 第3版

実践ハイパフォーマンスMySQL 第3版

Mac OS X で Eclipse を開くと環境変数を引き継がないので端末から起動するようにした

Mac OS X (手元の環境はバージョン10.10.1) で Eclipse (手元の環境はバージョンは Luna 4.4.1) を開くと環境変数を引き継がないので,IDE 上でプログラムを走らせたりテストを実行したりするとコケる場合があって厳しい気持ちになります.

端末上から Eclipse を開くと環境変数が引き継がれるようなので以下の様な alias を張り,端末上から Eclipse を起動することでこの問題を回避 (根本的未解決) しています.

alias eclipse='open /Applications/eclipse/Eclipse.app'


なんか他にもっと良いやり方知ってる方教えてください.

Git の Tag が打たれる毎に Travis CI を使って fat-jar を GitHub Releases にリリースする

Java で書かれた CLI ツールやアプリケーションを配布する時,依存するモジュールを全部まとめて1つの jar ファイルに固めて,単独で実行可能にしておくと何かと便利です.巷ではこうした jar ファイルを fat-jar と呼ぶようです.

この fat-jar ファイルをどこにホスティングしようかと考えた時,Perl だと fatpacked なスクリプト (fat-jar のように全部の依存を1つにまとめたスクリプト) をモジュールのコンポーネントに含めてそれごと CPAN にアップロードして CPAN 経由で配布するというのが一般的だったんですが,Maven Central ではどうやらそういう方法は人気が無いようなので,今回は GitHub Releases で配布することにしました.

今回は Git の Tag が切られて push された時 (つまりリリース処理がされた時) に自動的に fat-jar をビルドして GitHub Releases にリリースしたかったので,Travis CI の deploy 機能 (まじ便利!!) を利用して実現することにしました.


以下,その為に実行した手順です.
java-mysql-diff で同様のことを行っているので,適宜参照してもらうと良いと思います.

Releases · moznion/java-mysql-diff · GitHub

1. fat-jar な jar ファイルを maven でビルドする

Maven で fat-jar を生成する為に, pom.xml を以下のように記述しました.

...
<profiles>
  <profile>
    <id>fatjar</id>
    <build>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-assembly-plugin</artifactId>
          <version>2.5.3</version>
          <configuration>
            <descriptorRefs>
              <descriptorRef>jar-with-dependencies</descriptorRef>
            </descriptorRefs>
          </configuration>
          <executions>
            <execution>
              <id>make-assembly</id>
              <phase>package</phase>
              <goals>
                <goal>single</goal>
              </goals>
            </execution>
          </executions>
        </plugin>
      </plugins>
    </build>
  </profile>
</profiles>
...

maven-assembly-plugin を使い, jar-with-dependencies を有効にしておいて,package フェイズで走らせるようにする設定にしておくと,fat-jar を 生成する事が出来ます *1

以下のようにコマンドを走らせると fat-jar を生成することが出来ます.-P fatjar は profile の id です.

$ mvn -P fatjar package

参考: java - Building Maven fat jar conditionally - Stack Overflow

2. .travis.yml を編集して,tag が打たれて push される毎に GitHub Releases にリリースするようにする

手始めに travis コマンドをインストールします.travis コマンドは Ruby Gems で配布されているので適宜やっていきます.
travis | RubyGems.org | your community gem host

$ gem install travis

次に travis setup コマンドを実行して,リリースに必要な .travis.yml の内容を生成します.
今回は GitHub Releases にリリースするので,travis setup releases を実行します.

$ travis setup releases
Detected repository as your/repository, is this correct? |yes|
Username: foobar
Password for foobar: ******************************
File to Upload: target/fat.jar
Deploy only from your/repository? |yes|
Encrypt API key? |yes|

コマンドを実行すると色々訊かれるので適宜答えます.デフォルト値が yes になってるところは大体 yes で良いような気がしています.
正常に完了すると,以下の様な内容が .travis.yml に追加されると思います.

deploy:
  provider: releases
  api_key:
    secure: <SECRET KEY>
  file: target/$TRAVIS_TAG.jar
  on:
    repo: your/repository

これに色々足していきます.

deploy:
  provider: releases
  api_key:
    secure: <SECRET KEY>
  file: target/$TRAVIS_TAG.jar
  skip_cleanup: true
  on:
    repo: your/repository
    all_branches: true
    tags: true

all_branchestags が有効になってないと,tag を切った時にリリースというのが上手く動かなかったので追記しておきます.skip_cleanup: true はまあ適当にという感じ.


あとは .travis.yml に before_deploy のフェイズでデプロイ対象となる fat-jar (今回の場合は file: target/$TRAVIS_TAG.jar) を生成してやる設定を追記します.

before_deploy:
    - mvn -P fatjar clean package -DskipTests=true -Dproject.finalName=$TRAVIS_TAG

環境変数 $TRAVIS_TAG には git の tag 名が入っているので,それを上手いこと使ってやると mvn release:prepare のようなコマンドでリリース処理を行う時に,自動的に切られる tag 名と噛み合って便利だったりします.まあここらへんはお好みでという感じです.

3. tag を切って push

後は git の tag を切って push すると自動的にテスト・ビルドが走って自動的に GitHub Releases にリリースされます.




手順は以上です.

このように,リリースするたびに自動的に fat-jar をリリースするようにしておくと結構便利です.
今回は Travis CI を利用しましたが,wercker 等の他のサービスでも同様のことが出来ると思います *2

ぜひお試し下さい.

*1:build の設定で maven-jar-plugin を併せて利用する必要があると思います

*2:しかし wercker は tag が切られるタイミングでごにょごにょする,みたいなのをやるのがちょっと面倒くさくて見送ったという経緯が……