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

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

git でファイルごとのコミット数を取ってきて,プロジェクト中のホットなファイルを割り出すという試み

途中の段階でプロジェクトに入った時などに,「どれがそのプロジェクトの中心となっているファイルなんだろうか」というのを手っ取り早く知りたくなる時があります.僕はあります.


そこで「どのファイルが盛んに変更されているのか」という点を指標として注目すると,良い感じにそこら辺取れるのでは無いかと思って試してみました.
コミット数が多いファイルは多く変更を加えられているということから,そうしたファイルはホットであるということが言えそうな気がしたので,git でファイルごとのコミット数を取ってきて,それをソートして見てやれば良いよな,という意識でやっていきました.もちろんコミットの粒度などもあるでしょうから一概にはそうとは言い切れませんが,参考にはなる気はします.


使うスクリプトは至って簡単.以下の様な感じです.

git ls-files |
while read file ; do
  commits=`git log --oneline -- $file | wc -l`;
  echo "$commits - $file";
done | sort

git で管理されているディレクトリ内でこのシェルスクリプトを走らせるとそのような情報を取ってくることが出来ます.
railsリポジトリで試してみました所,以下の様な結果が得られました.

1 - actionmailer/lib/rails/generators/mailer/templates/application_mailer.rb
1 - actionmailer/test/fixtures/anonymous/welcome.erb
1 - actionmailer/test/fixtures/another.path/base_mailer/welcome.erb
1 - actionmailer/test/fixtures/asset_host_mailer/email_with_asset.html.erb
1 - actionmailer/test/fixtures/asset_mailer/welcome.html.erb
<中略>
549 - activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
556 - actionpack/CHANGELOG.md
745 - activerecord/lib/active_record/associations.rb
1134 - activerecord/CHANGELOG.md
1145 - activerecord/lib/active_record/base.rb

なるほどという感じです.正しいのかどうかはよくわかりません.rails 識者の方どうでしょうか.
めっちゃコミット数あった (5万コミットくらい) ので実行に15分くらいかかって大変微妙な心境になります.


よくわからなかったので,なんとなくわかるであろう Plackリポジトリで試してみます.

1 - eg/dot-psgi/Dumper.psgi
1 - eg/dot-psgi/echo-stream-sync.psgi
1 - eg/dot-psgi/runnable.psgi
1 - eg/dot-psgi/static/index.html
1 - eg/dot-psgi/static/test.js
<中略>
113 - Makefile.PL
150 - lib/Plack/Response.pm
178 - Changes
197 - lib/Plack.pm
211 - lib/Plack/Request.pm

なるほど,それっぽい感じがしますね!! (こっちはすぐ実行し終わった)


という感じでまあまあ参考になる情報が取れるのではないでしょうか,という気持ちです.試しに色々なリポジトリに適用していってますが,それっぽい結果が得られてて面白いですね.
逆にコミット数が少ないファイルはメンテされてないから危険,みたいなのも分かるんでしょうか.要検討という感じです.
グラフ等で可視化してやるとまた面白さが出てくるかもしれませんね.

Groovy 所感

開発のサポートツールやらなにやらで,こまごましたものを Groovy でちょいちょい書いて思ったことです.
Groovy で Web アプリケーションを書いたとかそういうゴツい話ではないのでそのあたりはよくわかりません.
なお本記事中に出てくる Java っていうのは Java 8 以降のことを指していると思ってください.

所感
  • 楽にコードが書けるという点では良い.言語的にそういうところを重視している気がする.
    • defとか.あとは DB 操作とか結構良い.楽.
    • System.out.println() とか書かなくて良いのは本当に良いですね.
    • とは言え,なんだかんだで補完の支援を受けないと記述コストは大きいと思う.賢い補完が要る.
  • gradle は pom.xml 書くよりもストレスが小さい気がする.
    • とは言え maven でもめんどいことは gradle でもめんどい印象.
    • 結局なんか,適宜やっていきましょうという感じになる.
    • つうか gradle はあんまモリモリやってないからよくわからん!
  • 実行速度は特に感想無いです.チョイノリみたいなツールだと全く問題にならない.
    • 重い処理するやつとか,Web アプリケーションとかだと色々あるかも.知らない.
  • 書いたら LL 感覚ですぐ動くので,挙動を確認するための書き捨てのコードとかにはうってつけだと思う.フットワークが軽い.
  • groovysh 便利.Groovy の REPL 的なやつ.挙動をパッと調べたいときに有益.
  • Java と比較した時にコードが簡潔に書ける傾向にあるので,本質的な処理を理解しやすい.
    • サンプルコードとかに向いてると思う.
  • Groovy の便利記法結構あるけど,Java に似たようなのがちょいちょい入ってるから (lambda とか),そこがマッシブな優位点になるかどうかという点.
    • まあ Groovy の便利記法は便利は便利.
    • Java でも8以降は戦えるのでは.
  • 当たり前の話だが groovy の処理系が別途必要となってくる.
    • Groovy のスクリプトJava のプロジェクトの支援ツールとして配布するとなると,その利用者にGroovy のインストールを強制することになる.
    • まあ入れれば良いですねという感じだけど,めんどいですよね.
    • Java のプロジェクトの開発支援ツールに Groovy を含めるのはまま便利だ (った) と思うんですが,21世紀にはなんと CI ツールなどが存在していて,CI 回すたびに jar をパッケージできる感じになってきているので,Groovy のスクリプトではなくその jar を配布すれば良いのではという意識の高まり.
      • 新たに処理系を入れる手間とか心理的なアレとかが消える.
      • そういう jar のパッケージングが極めてめんどい時は Groovy 使うと良いのではという気持ち.
      • ブックマークコメントで便利情報もらったので追記しました.
  • Pivotal がスポンサーから外れるの心配ですね.
まとめ
  • 挙動を確認したりするための書き捨てのスクリプトに使うのは良さそう
    • ついでに言うと groovysh が便利
  • サンプルコードに使うのは向いていると思う
  • それ以外の用途で積極的に使う理由が積極的に無い……
  • Java のプロジェクトの開発支援ツールみたいな用途だったら,Groovy じゃなくて (fat-packed) jar を配ってやっていく方が良いのではないか


という感じです.こういう意識になりました.書き味は気持ちのよい部類だと思われます.
gradle はちょっと評価できるほど使っていないので感想変わるかもしれないですね.


[追記]

Groovy 所感 - その手の平は尻もつかめるさ

Groovyのインストールを強要するのでなく、groovy-all.jarをクラスパスに含めるだけで良いのでは?

2015/01/28 22:12

なるほど.良さそう.ありがとうございます.


[追記]
Java のプロジェクトに Groovy のプログラムを含めるの,まあ自分は良いんですけど他の人にも Groovy の読み書きを強いる事になるので,そのへんはどうなんでしょうね.学習コストが上がるというか,些細なことでもお作法を覚えなきゃ駄目なのは面倒臭いのではと思ってしまう.で,結局 Groovy 読み書きできる人が永劫そのあたりを面倒見る,みたいな事になったら地獄っぽい.まあ普通に Java 読み書きできたら Groovy も読み書きできそうですけども.はい.


[追記]
別の処理系 (つまり今回の場合 Groovy) に依存すると,気を配る対象 (処理系の動向追ったりとか) が増えるためにコストが高まるという見方もあるので,そのコストを Groovy のメリットでうまく相殺できるのかどうか考えていく必要がある (Java も8とかはまあまあ書き心地が軽いのでそこが支配的なメリットになるかどうか.直接実行できるというのも,配布時にコンパイルしたパッケージを置くスタイルと比較した時にどうか.まあトライアルアンドエラーや修正は楽だけれど).
依存が少なければ少ないほどメンテコストは低くなる傾向があるので,依存はバチバチ減らしたい.結局、ソフトウェアのライフサイクルを考えるとメンテフェーズが一番長くなるはずなので,そこでコストがかかるようになるとリソースをどんどん奪われてしまう.総じたコストを低く保つにはなんやかんやで単一の言語でやっていった方が良いのではないかという立場です.
我々はどうすべきか.

CUDA で 2 枚以上の GPU を使って cufft する時は FFT Plan を各々の device に乗せる必要がある

以下は間違い.

cudaSetDevice(devices[0]);
cufftHandle fft_plan;
cufftPlan1d(fft_plan, SIZE, CUFFT_C2C, BATCH); // ここで作られる FFT Plan は device 0 にしか確保されない

cufftComplex *ffted_data[2], *orig_data[2];
cudaSetDevice(devices[0]);
cudaMalloc((void **)&orig_data[0], SIZE);
cudaMalloc((void **)&ffted_data[0], SIZE);
cudaSetDevice(devices[1]);
cudaMalloc((void **)&orig_data[1], SIZE);
cudaMalloc((void **)&ffted_data[1], SIZE);

cudaSetDevice(devices[0]);
cufftExecC2C(fft_plan, ffted_data[0], orig_data[0], CUFFT_FORWARD);
cudaSetDevice(devices[1]);
cufftExecC2C(fft_plan, ffted_data[1], orig_data[1], CUFFT_FORWARD); // ここ (device 1 上) で使っている fft_plan は device 0 にしか乗っていないのでマズい

この場合,fft_plan が device 0 にだけ乗っている為,device 1 で FFT を走らせようとすると変な結果が得られる.
エラーではなく変な結果が得られる!!!!
つらい!!!!!!!!!!!
原因がわかりにくい!!!!!!
あああああああああああああああああああああああああああああああああああああああああああああ!!!!!!


正しくは以下のように,FFT を実行する各々の device 上で FFT Plan を確保しなければならない.

/*
 * ここで各 device 上で FFT Plan を確保する
 */
cufftHandle fft_plan[2];
cudaSetDevice(devices[0]);
cufftPlan1d(fft_plan[0], SIZE, CUFFT_C2C, BATCH);
cudaSetDevice(devices[1]);
cufftPlan1d(fft_plan[1], SIZE, CUFFT_C2C, BATCH);

cufftComplex *ffted_data[2], *orig_data[2];
cudaSetDevice(devices[0]);
cudaMalloc((void **)&orig_data[0], SIZE);
cudaMalloc((void **)&ffted_data[0], SIZE);
cudaSetDevice(devices[1]);
cudaMalloc((void **)&orig_data[1], SIZE);
cudaMalloc((void **)&ffted_data[1], SIZE);

/*
 * 各 device に応じて使用する FFT Plan を差し替える
 */
cudaSetDevice(devices[0]);
cufftExecC2C(fft_plan[0], ffted_data[0], orig_data[0], CUFFT_FORWARD);
cudaSetDevice(devices[1]);
cufftExecC2C(fft_plan[1], ffted_data[1], orig_data[1], CUFFT_FORWARD);

こうするとちゃんと動く.ハマった……

あああああああああああああつらい!!!!!!!!!!!!!!! 勘弁してれ!!!!!!!!!!!!!

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分くらいで読めてお手軽.

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