« 2009年10月 | トップページ | 2009年12月 »

2009年11月の25件の投稿

2009/11/29

静的型付けの何が良いか

以前、「動的型付け言語はやはり使用できない」というタイトルでエントリを書いたのだが、「Scalaスケーラブルプログラミング[コンセプト&コーディング] (Programming in Scala)」という本に言いたかったことが書かれていたので紹介する。

 

p.34 1.3.4 静的な型付け(簡潔性、柔軟性、検証可能性、安全性、ドキュメント性):

静的な型システムは、ある種のランタイムエラーが存在しないことを証明できる。たとえば、真偽値が整数に加算されていない、非公開変数がクラス外からアクセスされていない、関数が適切な数の引数に対して適用されている、文字列の集合に追加されているのは文字列だけである、といったことを保証できるのである。
しかし、今日の静的型システムでは、その他の種類のエラーは検出されない。たとえば、終了しない関数、配列の境界を越えたアクセス、0による除算などは検出されない。[中略]そのため、静的型システムは、一部の人々からはあまり役に立たないものだと軽視されている。さらに、静的型システムは単純なエラーを検出できるだけだが、「単体テストならもっと広い範囲のエラーを検出できるのだから、わざわざ静的型システムを使う必要はない」とまで言う人々もいる。

上記の意見は、前エントリのブルース・エッケルの意見と同じ方向だろう。これに対して、以下の反論が続く。

確かに、静的型システムは単体テストの代わりになるわけではないが、プログラムの性質を確認するために普通なら必要だった単体テストの数を減らしてくれる。さらに、単体テストは静的型付けの代わりにはならない。Edsger  Dijkstra(エドガー・ダイクストラ)が言ったように、テストが証明できるのはエラーの存在であって、エラーの不在ではない。静的型付けが与えてくれる保証は単純なものかもしれないが、どれだけテストをしたとしても得られない本物の保証なのである。

 

ダックタイピングという言葉がある。動的型付けにおいて、ダック(と思われるもの)を用いたとき、テストは

  • それがダックであることを確認する(鳴かせてみる)
  • 鳴き声が妥当であることを確認する

の2種類が必要になる。一方、静的型付けにおいては、それがダックであることは確実なので(保証されているので)、

  • 鳴き声が妥当であることを確認する

の1種類で済む。

テストコードを書く場合、もしかすると両者は同じ1つのテストケースで実行可能かもしれない。が、コードレビューを行う場合(実際にプログラムを実行できない場合)では、かなりの負荷になると思う。

2009/11/27

NicoBrowser ver.0.2.0 待機時間の設定項目追加

ダウンロード処理が続けて行われるような状況で、一定時間内にニコニコ動画サーバへ既定回数以上アクセスすると、サーバからはじかれる。

従来、少なくとも5秒間間を置いてアクセスするようにしていたが、5秒では短すぎるようだ。

この問題に対応するため、この待機時間をコンフィグファイルで設定できるようにした。

初回起動時に作成される ~/.nicobrowser ディレクトリ(Windows XPでは C:\Documents and Settings\user_name\.nicobrowser ディレクトリ)以下ののnicobrowser.propertiesファイルに、

download.wait=20

という1行を追記すればよい。上記の例なら20秒待機するようになる。

 

ダウンロードはこちらから。

2009/11/26

easymockを利用してみる(2) – easymockのインストールとHelloWorld

Mock Objectツールは、interfaceを元にモックのインスタンスを生成するのが基本らしいが、easymockにせよjMockにせよ、classからモックインスタンス生成が可能になっている。今回はこの機能を利用する。

動作させるために、easymockのサイトにあるEasyMock2.5.2、Class Extension2.4、そしてcglibのサイトからcglib-nodep-2.2.jarの3点をクラスパスに設定すればよい。

 

次に、動作確認のため、dJUnitのサイトにあるHelloWorldをeasymockで動作させてみる。

   1: import java.io.PrintStream;
   2: import org.junit.After;
   3: import org.junit.Before;
   4: import org.junit.Test;
   5: import static org.easymock.classextension.EasyMock.*;
   6:  
   7: public class HelloWorldTest {
   8:  
   9:     private PrintStream mock;
  10:     private PrintStream original;
  11:  
  12:     @Before
  13:     public void setUp() {
  14:         mock = createMock(PrintStream.class);
  15:         original = System.out;
  16:         System.setOut(mock);
  17:     }
  18:  
  19:     @After
  20:     public void tearDown() {
  21:         System.setOut(original);
  22:     }
  23:  
  24:     @Test
  25:     public void testMain() {
  26:         mock.println("Hello World.");
  27:         replay(mock);
  28:         HelloWorld.main(null);
  29:         verify(mock);
  30:     }
  31: }

 

dJUnitではPrintStreamクラス自体に作用できるので、「ソース例」の2番目のコード10行目

String arg = (String) getArgument("java.io.PrintStream", "println", 0);

でPrintStream#println(String)の引数に設定された文字列を取得できている。

一方、easymockでは、createMockメソッドで作成したモックオブジェクト(mock)を、System.setOutメソッドで標準出力に設定してやる必要がある(上コード10-13行目)。元々のSystem.outは、普段と何ら変わらないオブジェクトなので、動作を設定することは出来ないためだ。

その他補足すると、djUnitでjunit4相当の記述をしようと思うと、始めにMockObjectManager.initializeメソッドを呼ぶ必要があり[参考]、Virtual Mock Objectもいきなり利用できる(=いきなりクラスを差し替えられる)わけではない。

 

…とここまで書いて気付いたのだが、easymockでは、private methodやstatic methodに対する操作が行えない。上記のSystem.outのようなstatic fieldもそうだ(上の例ではたまたまsetterがあるので問題ないが)。

これらのmethod,fieldに対して操作しようと思うと、easymock(等)を拡張するPowerMockJMockitやJMockitのページで参照されているいくつかのプロダクトがあるようだが、結局dJUnitとアプローチは変わらない様に見える。そうするとやはり実行速度がネックになりそうだ。

PowerMockはまさにdJUnitと同じような仕組みのようだ。JMockitのサイトのPowerMockについて、以下の記述がある。

PowerMock uses custom class loaders (usually one per test class) in order to generate modified versions of the mocked classes. Such heavy use of custom class loaders can lead to conflicts with third-party libraries, hence the need to sometimes use the @PowerMockIgnore("package.to.be.ignored") annotation on test classes.

ちなみにdJUnitでは、無視するパッケージはAntのxml、djunitタスクのプロパティに設定する(excludesPath)。

JMockitはjavaagentを利用しているようだが、やはり動作速度は遅いらしい。

ssogabe – twitter:

JMockitをフルに使ったら、テスト時間が2sから7.2sに増加した。予想以上に遅い。

当初の目的である、クライアント/サーバ間の通信でサーバのモックを作成するという点についてはeasymockで問題ないと思うが、上記の点はどうしたものか。

2009/11/25

easymockを利用してみる(1) – Virtual Mock Object と Mock Object の違い

以前Mock Objectに少し触れたことがあるが、私自身使用したことが無かったので今回試してみた。

また、Virtual Mock Object として、dJUnitを利用したことがあるので、これとの比較も書いてみたいと思う(したがって、タイトルのVirtual Mock Objectは、正確にはdJUnitを指すものであって、Virtual Mock Object全体の性質であるとは限らない)。

 

テストカバレッジについて日本語のサイトを検索すると、dJUnitがよくヒットする。また、Eclipseプラグインとしても提供されており、導入難易度が低いせいか実プロジェクトでもよく利用されているようだが、実際に利用してみて何点か不満が出た。例を以下に記載する。

  • カバレッジについて、かなり古いバージョンのJCoverageを利用している。
    • 現在オープンソース版のCloverが提供されなくなって久しいが、dJUnitでは当時のGPL版のものを用いているはず。
  • Eclipse以外から利用するのに、設定が煩雑である。特にVirtual Mock Objectを利用する場合。
  • Antで実行する場合、専用のタスク(junitタスクに似てはいるが)で実行する必要がある。
  • テスト対象の規模が大きくなると、実用に耐えられないくらい遅い。
    • 1テストケースごとに、クラスロードに数分、というようなことも。
      • forkは常にtrueなので、テストケースごとにVMが分かれる。
      • 仕様なのかバグなのか不明だが、テストケースをロードした直後(具体的には@BeforeClassアノテーションを付けたメソッド内)にしかVMO動作設定できない現象が出たので、テストを細分化してVM起動からやり直す必要が出た。
  • dJUnit、Hibernate共にasm(cglib)を利用するのだが、必要とされるバージョンが異なるのではまる。
    • これについては、Hibernateが古いバージョンを利用しているのが問題なのだが。
    • easymockやjMockでもcglibを利用しているようなので、この問題はdJUnitに限ったことではないのかもしれない。

Mock Objectはオブジェクトに対して動作を設定するのに対し、Virtual Mock Objectはクラス自体の動作を書き換えるらしい。このためVirtual Mock Objectは動作速度が遅くなりがちなのではないかと思う。また、Mock Objectではこの問題が表れにくいのではないかと期待しているが、冒頭に記載したとおりMock Objectの使用経験が無いため実際のところは未知である。

JCoverageの問題については、Coberturaを利用すればよいだろう。

2009/11/23

[読書]「科学研究者になる方法」上田寿

 

  • SEのフシギな生態」の研究者版だなあ、というのが読後ぱっと思いついた感想。
  • 13年前の本。
    • 始めの方の章は定量的な分析が載っているが数値が古い。
    • 以前3分類したうちの公的研究機関に該当する記述は、国立研究所が想定されている(独立行政法人はまだこの頃無かった模様)
  • ただ、傾向としては当時と変わらない部分もあるはずなので、全く役に立たないわけではないだろう。
  • タイトルである「科学研究者になる方法」として役に立つのは、全8章のうち、1章「日本の科学研究者」、6章「科学研究者になる方法」の2章くらいだろうか。

2009/11/22

[読書]「企業の研究者をめざす皆さんへ」 丸山宏

帯書きより:

刻々と変化する世界経済や企業戦略の中で、基礎研究部門の果たすべき役割とは?研究員に求められるあり様とは?グローバル企業IBMの東京基礎研究所で所長を務めた著者が、これらの解答として日々発信してきたレターを集大成!
★さらにこれから企業の研究所を目指す学生にも重要なアドバイスを送ります。

目次:

  1. 企業における研究のあり方
  2. 研究について
    1. 研究者像
    2. 研究の面白さ
    3. 研究のやり方
    4. 論文について
    5. 研究力とは
  3. コミュニケーションの大切さ
    1. コミュニケーションの基本
    2. コミュニケーション・テクニック
    3. 異文化コミュニケーション
  4. 研究者のキャリア
    1. テクニカル・キャリア
    2. 二つのヒント
    3. グローバル統合の時代の中で、研究者はどうあるべきか
    4. 変わっていくということ
    5. 外の世界を経験すること
  5. リーダーシップについて
    1. 組織の運営戦略
    2. どうしたら人は動くか
    3. リーダーシップのベスト・プラクティス
    4. 知的刺激を与える
  6. 企業の研究所のマネジメント
    1. 企業の研究所のあり方
    2. イノベーションを起こす仕組み
    3. グローバル・テクノロジ・アウトルック、グローバル・イノベーション・アウトルック
    4. 基礎研究部門マネジメントの変化
    5. 研究所の価値
    6. 研究の評価
  7. 知財・契約・技術倫理
    1. 特許について
    2. お客様との契約について
    3. 技術倫理
  8. 研究所の風土
    1. わくわくするDNA
    2. ビジネスマナー
    3. 仕事場を離れて
  9. 企業の研究者をめざす学生の皆さんへ
    1. 学生時代に何を学ぶか
    2. 博士課程に進学すべきか
    3. 企業について知る

2章~8章までは、著者が所長を務められていた時期に、所員に向けて書かれたレター(元は社内ブログに書かれたものだそうだ)と、そのときの背景や補足、9章は丸々この本のための書き下ろしだろうか。

このような体裁になっているため、冒頭帯書きには対象者が「企業研究者」「企業の研究所を目指す学生」となっているのだと思う。

が、この2者に限らず、その他の研究者(前回の分類でいうと、「大学研究者」「公的機関研究者」)に対しても同程度に有用なのではないかと思う。

また、2章に書かれている、研究対象をどのように設定するのか、研究のストーリーをどう考えるのかといったようなことは、大学で研究を行っている学生に対しても助けになるだろう。

研究者のバックグランドについて書かれた書籍は、(少なくとも情報工学に関係視しそうなものは)JSTなどの機関や大学の先生が著者となっているもの(前述分類で「大学」「公的機関」)が大半のようなので、企業研究者の著作、という意味でも貴重だ。

 

本筋と外れる感想だが、「情報の秘匿クラスがIBM Confidentialとそれ以外しかない」というのはうらやましい限りなのだが、顧客に関わる情報(例えばプロジェクト限り)とか、経営情報(例えばマネージャ以上限り)とかはどうするのだろうか。

[読書]「実装パターン」ケント・ベック

まえがきより:

この本で取り上げないことを以下にあげよう. この本には多くの見解が含まれ, 最終的な判断は読者任せにされている. よって, スタイルガイドではない. この本の大部分は, 一般的なプログラマでなければ, 1日に何度も行うような小さな決定について書かれている. よって, コード設計の本ではない. パターンの記述形式は独特で, その場限りなので(特定の目的のためだけに作られているから), パターン本ではない. Java言語の機能の多くを網羅しているが, 読者にJavaの知識があることを前提としているので, 言語の本でもない.

以下、読んだ感想を箇条書き的に。

  • タイトルに「パターン」とあり、表紙にもでかでかと書かれているにも関わらず「パターン本ではない」とはこれいかに。
  • Javaの言語仕様に依存した話の割合が多い。コード例もJava。
    • 他の言語学習者がこの本を読む意味は無いと思う。
  • クラスを設計する際、どういうことに注意を払って、どういう実装を選択すべきかというような内容が書かれた本。
  • Effective Javaリファクタリングテスト駆動開発入門を読んだことがないのであれば、先にそちらを読むべきだろう。これらの方が具体例が書かれており、理解しやすい。
  • 具体例があるものもあれば、無いものもある。
    • 実際に出会ったことがあるパターンであればすぐ言いたいことの見当がつくが、コード例も無く出会ったこともない記述は、意図が分からないものもあった。
  • 同一コンテキスト内では文の抽象度を同一に保とう、というような話題が何回か登場するのだが、この本自体、パターンの説明ごとに説明の具体度が異なるので、あまり読みやすいとは思えないのが残念だ。

2009/11/19

MacOS/Linuxへの対応 (ipum ver.0.4)

LinuxでのDnDに対応したipumを作成した。

Mac OSについては、動作環境がないため本当のところは分からないが、Webを見る限りWindowsと異なるというような記述は見当たらなかったので、動作環境に含めてしまっている。

ただし、Mac/Linuxについては、ffmpegとMP4Boxのバイナリは同梱していないため、別途入手が必要。

Mac/Linuxのコンパイル済みのffmpeg/MP4Boxはこちらからダウンロードできるようだ。ソースコードからビルドする場合はそれぞれ公式サイトから入手できる。

 

最新版ipumのダウンロードはこちらから。

 

参考:

2009/11/18

Androidで時計ウィジェットを作成するときにACTION_TIME_TICKを利用しようとしたがうまくいかなかった

Nixie Clockについて、省電力モードの時には秒表示を止めて分ごと画面更新を行う、という案も考えたことがあった(より「らしい」見せ方に気付いたので廃案にしたが)。

この際、ACTION_TIME_TICKというアクションを受け取るようにすれば正しいタイミングで描画更新が出来るのではないかと考え、少し試してみたのだがうまくいかなかった。

上記リファレンス(Javadoc)には以下のように記載されている。

You can not receive this through components declared in manifests, only by exlicitly registering for it with Context.registerReceiver()

つまり、AndroidManifest.xml中で<intent-filter>設定を行っても有効ではなく、ソースコードで実装する必要がある、ということらしい。

そこで、AppWidgetProvider#onEnabledでregisterReceiverを呼んでみるように変更したのだが、これもうまくいかない。

この点についても、リファレンスを読んでみると

this method cannot be called from a BroadcastReceiver component

と書かれていた(AppWidgetProviderはBroadcastReceiverの子クラス)。

ここまで確認して止めてしまったので、本来どう実装すべきだったのかは未確認。AnalogClockクラスがAppWidgetで利用できるようなので、これを利用するのだろうか[参考]。

 

AppWidgetProviderインスタンスのライフサイクルが全然理解できていないのが問題なのだろうな...

2009/11/17

Nixie Clock - Android用秒表示時計(Desktop Widget)

 

ダウンロードページはこちらへ移動しました

 

desktop widget というのか AppWidgetというのか。

今まで使用してきた携帯電話は、全て時計の秒表示が行えていたのだが、Androidに標準で表示されている時計は全て分までの表示しかなかったため、自作してみた。

その他の動機としては、XBOX360のゲームSteins; Gateのにちゃんねるスレッドでいくつか自作Flashアプリ時計が紹介されていた()ので、これをHT-03Aでも実現してみよう、というのがある。

機能としては以下の通り。

  • 時、分に加え、秒までの表示に対応。
  • 省電力モード。
    • 省電力モードからの復帰はウィジェットをクリック。

設定項目も色々と考え付くのだが、シンプルさを重視した結果、何も無くなった。将来的にAndroidプログラミング学習を目的としてActivityなどが増えていく可能性は、ある。

インストール時、以下の2つの警告が出るようだ。これらの警告、単純なHello, worldアプリでも必ず出るのだが(1.6かららしい[参考])、意味のない警告は、本当に重要なセキュリティ警告に対する意識も低下させてしまうのではないだろうか。

  • 電話/通話 - 携帯のステータスとIDの読み取り
  • ストレージ - SDカードのコンテンツを修正/削除する

 

それにしても、EclipseよりGIMP使用時間のほうが長かったような。レイヤーやレイヤーマスクといった機能を初めて使用した。

Android1.6ではandroid:updatePeriodMillisの最小値は1800000

AppWidgetProviderを利用して、秒表示が出来る時計ウィジェットを作成してみようと考えた。

取り敢えず動くものを、と考えたとき、表題のupdatePeriodMillis設定で周期更新処理を簡単に実装できることが分かったので、これを用いて時刻表示更新を行ってみた。

ところが、エミュレータ上では正常に動作していたが実機では表示更新されない。

Issue 3990: Desktop Widgets: since 1.6 there is a minimum value for updates, which is documented nowhere によると、Android1.6より、ここで設定できる値の最小値は1800000であり、これより小さい値を設定してもこの値に切り上げられるようだ。1800000ミリ秒、つまり30分未満の更新周期を持つような処理はこれでは実装できなくなったようだ。エミュレータは1.5のものを使用していたため、更新できていた。

30分未満の更新周期を実現したい場合、王道的手法はAlarmManagerを使用することのようだ。

 

参考:

Android1.6でHomeを回転させるとウィジェットが強制終了する

Android端末のなかには、Android Dev Phone1などのようにHomeが回転する機能を持つものがある。HT-03Aでも、アプリケーションを導入すれば回転させられるようになるらしい。また、エミュレータもCtrl+F12キーで回転させられる。

AppWidgetを作成している過程で、回転を行うとウィジェットが以下の例外によって強制終了する現象が発生した。

java.lang.ClassCastException: android.view.AbsSavedState$1
    at com.android.launcher.Workspace.onRestoreInstanceState(Workspace.java:903)

Issue 3981: ClassCastException in the Launcher with certain widgets on Donut/master によると、Android1.6のバグだそうだ。

上記のレポートによると、発生する条件は6個を超えるidを動的に生成、つまりlayoutのxmlで

<Button android:id="@+id/ok_button"

のように、idを@+id/で設定している場合に起こるそうだ。

従って暫定対応策としては、idを自分で定義せず、あらかじめandroid.R.idクラスで定義されているものを用いることになる。上記のような箇所を、例えば

<Button android:id="@android:id/addToDictionary"

のように、あらかじめ定義されているandroid.R.id.addToDictionaryに置き換えればよいらしい。

この暫定対応策の問題は以下の通り。

  • idと実際のオブジェクトの対応付けが分かりづらくなる。
    • 上記の例では、ボタンにaddToDictionaryというidを割り当てているが、後から見てすぐ理解できるだろうか。
  • あらかじめ定義されているid数は限りがある。
    • 40個程度しか定義されていないので、これを超えるウィジェットを持つAppWidgetは作成できない。

冒頭に記載したとおり、日本で発売されている唯一の端末であるHT-03AはHomeは縦方向固定で回転できないため、あまり気にする必要は無いのかもしれない。

 

参考:

2009/11/14

Androidでのミュージックファイルアートワーク(カバーアート)仕様

 

カバーアートやアルバムアートなどとも呼称されるアートワークについて。

正確にはAndroidの仕様なのかアプリケーションの仕様なのか分からないが、少なくともHT-03Aの標準音楽プレーヤと、meridianでは以下のような動作になっていた。

  • アートワークはアルバムごとに1つ

「アルバム」の定義は後述するが、上記の意味するところは、同一アルバム内の楽曲ファイルに異なるアートワークを設定したとしても、プレーヤ上はどれも同じアートワークが表示される。

どのアートワークが用いられるかは

  • アルバム内で最初にアクセスした「アートワークが設定されたファイル」のアートワークを、アルバムアートワークとしてキャッシュする

ということのようだ。一旦キャッシュされると、次回以降はそのキャッシュを使用しているように見える。

  • キャッシュはルート直下のalbumthumbsディレクトリに保存される
    [追記]OSのバージョン(あるいは機種?)によってこのディレクトリがある場所は異なるようです。ファイルマネージャなどで検索すれば正確な場所は分かる。Galaxy Nexusでは以下の場所であった。
    /mnt/sdcard/Android/data/com.android.providers.media/albumthumbs

このディレクトリ以下に保存されているファイルを画像ビューアで開くと、アートワーク画像そのものだということがわかる。

 

次に「アルバム」の定義だが、

  • 異なるディレクトリに保存されたファイルは必ず異なるアルバムとして扱われる
  • 同一ディレクトリに保存されたファイルでも、ID3タグ上のアルバム名が異なるファイルは異なるアルバムとして扱われる

逆に言うと、

  • 同一アルバムとして扱うためには、以下の条件を満たす必要がある
    • 同一ディレクトリに保存されたファイルである
    • ID3タグのアルバム名が同一である

ということになる。

 

ところで、HT-03Aでの楽曲管理にdoubleTwistを用いている方も多いと思うが、このアプリで同期すると音楽ファイルは単一ディレクトリに保存される。

したがって、アルバム名を設定していないと、全て同一アルバムの楽曲だとみなされてしまう。

ipumではニコニコ動画音楽ファイルにID3タグを付与する設定にしていても、アルバム名の設定は行わない。このため、初回アクセスしたファイルのアートワークが、全てのファイルで表示されてしまう。対策としては

  • ファイルごとに保存ディレクトリを変える
  • ファイルごとにアルバム名を変える(ファイル名をアルバム名に設定する、など)

といったことが考えられるが、前者はファイル管理が煩雑になる(し、同期アプリに依存する)、後者はAndroid上だけで扱うファイルであれば良いかもしれないが、タグの本来の意味と異なるものを設定することになるため、相互運用で問題が出るだろう。

 

追記:

Google code の Issuesでは、Issue 2945: Music player doesn't recognize different images in the id3 tags of multiple files in one album で”Defect”として登録されているので、仕様ではなくバグのようだ。

ニコニコ動画のRSS一覧作成するGroovyスクリプト

 

最近全くGroovyを触っていなかったので、手慣らしにスクレイピングでニコニコ動画のRSS一覧を作成するスクリプトを書いてみた。[追記: 下のコードは古いので現在のニコニコ動画サービスには対応できていません。最新版はgithubに上げています。]

import org.cyberneko.html.parsers.SAXParser
 
def rankUrl = 'http://www.nicovideo.jp/ranking'
def kinds = ['総合':'fav', 'マイリスト':'mylist', '再生':'view', 'コメント':'res']
def spans = ['毎時':'hourly', 'デイリー':'daily', '週間':'weekly', '月間':'monthly', '合計':'total']
 
def rankHtml = new XmlSlurper(new SAXParser()).parse(rankUrl)
 
def groups = rankHtml.'BODY'.'DIV'.'DIV'.'TABLE'.'TR'.'TD'.'TABLE'.'TR'.'TH'.'A'
def groupMap = [:]
groups.each{groupMap[it.text()] = it.@href.toString().split('/')[6]}
//groupMap.each{println it.key + ', ' + it.value}
 
 
println '<HTML><BODY>'
 
for(kind in kinds){
    for(span in spans){
        println '<A HREF="' + rankUrl + '/' + kind.value + '/' + span.value + '/' + 'all' + '?rss=2.0">'
        println '' + 'カテゴリ合算' + ' - ' + kind.key + ' - ' + span.key + '</A><BR>'
    }
}
 
 
for(group in groupMap){
    def groupUrl = rankUrl + '/fav/daily/' + group.value
    def groupHtml = new XmlSlurper(new SAXParser()).parse(groupUrl)
    def categories = groupHtml.'*'.'*'.'*'.'*'.'*'.'*'.'*'.'*'.'*'.'NOBR'.'A'
    def categoryMap = [:]
    categories.each{categoryMap[it.'DIV'.text()] = it.@href.toString().split('/')[6]}
    //    categoryMap.each{println it.key + ', ' + it.value}
 
 
    println '<P>'
    println '<H3>カテゴリグループ: ' + group.key + '</H3><BR>'
    for(category in categoryMap){
        for(kind in kinds){
            for(span in spans){
                println '<A HREF="' + rankUrl + '/' + kind.value + '/' + span.value + '/' + category.value + '?rss=2.0">'
                println '' + category.key + ' - ' + kind.key + ' - ' + span.key + '</A><BR>'
            }
        }
    }
    println '</P>'
}
println '</BODY></HTML>'

出力結果はこういう感じになる。

実行にはCyberNeko HTML Parserが必要。

2009/11/13

音楽ファイルに投稿者を設定する(ipum ver.0.3)

NicoBrowser ver.0.1.1 でニコニコ動画の投稿者名を永続化するように対応したのに合わせ、ipumで変換したファイルのID3タグにも投稿者名を埋め込むように対応した。

ダウンロードはこちらから。

従来、ニコニコ動画サイトで投稿者命を取得するには、各動画ページ内の「この動画を違反通報」リンク先を参照する必要があり、他の方が作成されているスクリプト等ではこれを見ているものが多いように思う。

この秋のバージョンアップからだろうか、動画ページ内に「投稿者プロフィールへ」リンクが出来ているようなので、NicoBrowserではこちらから取得するようにしている。

ipum - 動画ファイルから無劣化音楽抽出

 

ipum_front

ipum 最新版(2012/05/13 ver.0.5.1)をダウンロードする

Java6実行環境がインストールされていれば、ipum.jarをダブルクリックすることで起動できる。

 

機能と特徴

  • インターネット動画サービスが提供している動画ファイルから音楽を抽出する。
  • mp4,flv,swfファイルに対応。
    • 動画変換でよく利用されているffmpegはswfサポートが弱いので、swfに対応できているのは希少。
  • NicoBrowserとの連携により、ニコニコ動画のコンテンツではID3タグにサムネイル画像などを埋め込み可能。
  • 初期設定不要で、ドラッグアンドドロップで変換可能。
  • オリジナルの音質を保持して抽出するため無劣化、省容量。
  • 変換処理が無いので高速。

 

動作環境

java6実行環境がインストールされたWindows/Linux/Mac OS。

ID3タグ埋め込み機能を利用するためには、NicoBrowser Ver.0.1.1以降がセットアップされている必要がある。

    また、Linux, Mac OSについては、ffmpegとMP4Boxのバイナリを別途用意し、パスの設定を行う必要がある。

     

    設定

    設定ファイルはホームディレクトリ直下の.ipum/ipum.xml になる。これは初回起動時自動生成される。

    Windowsであれば%HOMEPATH%\.ipum(例えばWindows XPであれば、C:\Documents and Settings\user_name\.ipum)に、Linuxであれば ~/.ipum にあるだろう。

    項目詳細は添付のREADME.htmlを参照のこと。

     

    既知の不具合

    • NicoBrowser連携時、@CMや@BGMを用いている動画(典型的には、動画上部にこちらのようなカスタム表示を行っている動画)について、Author情報が取得できず、空欄表示される。

    データを保持したままテーブル構造を変更する(NicoBrowser ver.0.1)

     

    NicoBrowser Ver.0.1を作成した。ダウンロードはこちらから。

    なお、以前のバージョンから更新する際には、初回起動前に以下のコマンドを実行する必要がある(通常の起動コマンドにsyncオプションをつける)。

    java –jar NicoBrowser sync

     

    変更内容は以下の通り。

    • 永続化情報に「投稿者」を追加した。
    • 追加機能は特に無い。

     

    NicoBrowserでは、コンテンツ情報をインプロセスDBで管理している。今回、投稿者情報という新しい項目を永続化するに当たって、テーブルにカラムを追加する必要が生じた。

    従来のバージョンでは、JPAの機能を利用して、DBやテーブルが無ければ作成する(あれば何もしない)という動作にしていた。しかし、今回のように現在テーブルが既に存在する場合にプロパティ(永続化するBeanのフィールド)を追加しようとした場合は、この機能では対応できない。

    そこで、今回のバージョンからは、DB/テーブルの作成はLiquiBaseで行うことにした。

    LiquiBaseはDBリファクタリングツールという位置付けで、書籍「データベース・リファクタリング」で説明されている手法をツール化したもの、らしい。

    ともかく、このツールを使うことで、テーブルの内容を保持したままテーブル構造を変更することができるようになった。

    ただ、このツールは、DBの変更(リファクタリング)内容を、専用のテーブルで管理しており、NicoBrowserを従来のバージョンから今回の方式にあわせるためには、一旦現在の内容をその管理テーブルに書き込む必要がある。これを、冒頭に記載したsyncオプションで行うことにしている。

    このsyncオプションによる管理テーブルの同期は1回のみ行えばよく、今後はテーブル構造に変更があった場合でもLiquiBaseが自動で追従してくれるはずである。

    NicoBrowser - ランキング、公開マイリストからのニコニコ動画自動ダウンロード

     

    NicoBrowser最新版(2011/09/22 ver.0.11.0)をダウンロードする

    以前のバージョンを利用している場合には、後述「バージョンアップに関する注意事項」も参照のこと。

    注: このページの記載は情報が古いです。最新の情報はsourceforgeのWikiを参照してください。

    機能・特徴

    • ニコニコ動画に投稿された動画の自動ダウンロード
    • ダウンロード履歴管理
      • 一度ダウンロードした動画は重複してダウンロードされない
      • エコノミーモードでダウンロードしていた場合でも、高画質ファイルが取得できるのであれば再ダウンロードする
    • Pure Javaで開発
      • Windows, MacOS, Linux上などで動作可能
      • Java実行環境(バージョン6以降)がインストールされている必要がある
    • ipumとの連携でサムネイル付き音楽ファイルの自動生成が可能
    • さきゅばすのNicoBrowser拡張によりさきゅばすとの連携が可能

     

    操作方法

    コマンドラインで以下を実行。

    java -jar NicoBrowser.jar

    (適切にjava実行環境の設定が行われていれば)NicoBrowser.jarのダブルクリックでも起動できますが、この場合エラーメッセージ等は表示されません。

    その他詳細設定方法などは、ダウンロードファイルに含まれるREADME.htmlを参照。

     

    バージョンアップに関する注意事項

    ver.0.4.Xを利用していた場合の注意事項

    アップデート後(つまり今回のファイルで上書きした後)、1回目の起動前に以下のコマンドを実行する必要があります。実行しないとDB関連のエラーとなり処理が継続できません。

    java -jar NicoBrowser.jar sync4

    (引数にsync4をつけて実行する)

     

    2009/05/24版以前を使用していた場合の注意事項

    アップデート後(つまり今回のファイルで上書きした後)、1回目の起動前に以下のコマンドを実行する必要があります。実行しないとDB関連のエラーとなり処理が継続できません。

    java -jar NicoBrowser.jar sync

    (引数にsyncをつけて実行する)

     

    2009/03/23版以前を使用していた場合の注意事項

    nicobrowser.propertiesの互換性がありません。一旦リネーム(or 削除)してから
    実行してください。そうすると新しいnicobrowser.propertiesが作成されますので、そちらを編集して使用してください。

    path.dbの設定は、従来は"ファイル名"の指定でしたが、現在は"ディレクトリ名"の指定に変わっていることに注意してください。

    本体libディレクトリ以下について、構成が大きく変わっているため、libは上書きでなく置換することを推奨します。

     

    改正著作権法に関する留意事項

    2010年1月1日より著作権法が改正されました。これに伴い、本プログラムの使用用途によっては改正著作権法に抵触する恐れがあります。詳細は以下のペー ジ、及びこのページのリンク先文化庁サイトを参照のこと。
    http://feather.cocolog-nifty.com/weblog/2009/12/post-b7a9.html

    2009/11/09

    ニコニコ動画コンテンツをサムネイルつきで音楽ファイルに変換する(ipum ver.0.2)

    前回記載したとおり、iPod touchやHT-03Aでは専ら音楽を聴くのみで、動画再生機能は利用していない。

    ただ、せっかくディスプレイがあるので、音楽再生時にも利用できたほうが良いのではないか、ということで、ipumにアートワークを埋め込む機能を追加した。

    ドラッグアンドドロップで、以下のような情報が埋め込まれたファイルが自動生成される。

    id3tag

     

    この機能を利用するためにはいくつか制約がある。

    • NicoBrowser(使い方例1,2)でダウンロードしたファイルであること。
    • ダウンロード後、ファイル名を変更していないこと。

    NicoBrowserが持っているダウンロード履歴を基にWebアクセスを行い、ID3タグに埋め込むための情報を取得しているため、このような制約がある。

    その他、このipumのID3タグ埋め込み機能を利用する場合、NicoBrowserと同時起動すると正しく動作しないため、注意が必要である。

     

    ダウンロードはこちらから。

    デフォルトでは、本機能は無効になっている。有効にするためには、設定ファイル内の<useid3>オプションをfalseからtrueに書き換える。

    2009/11/08

    動画から音楽ファイルを抽出するipum ver.0.1

    ipum_front

    ダウンロードはこちらから。

    Java実行環境がインストールされていれば、ipum.jarをダブルクリックすることで起動できる。

     

    機能と特徴

    • インターネット動画サービスが提供している動画ファイルから音楽を抽出する。
    • mp4,flv,swfファイルに対応。動画変換でよく利用されているffmpegはswfサポートが弱いので、swfに対応できているのは希少。
    • 初期設定不要で、ドラッグアンドドロップで変換可能。
    • 変換処理をはさまないため、音質の劣化や変化がなく、オリジナルのまま抽出可能。
    • 変換処理が無いので高速。

     

    動機

    最近使用しているポータブルミュージックプレーヤは、iPod touchと、たまにHT-03Aである。双方とも動画再生が行えるが、動画を再生することは殆ど無く、単純に音楽を聴くだけに使用している。

    YouTubeやニコニコ動画のflvやmp4を、ポータブルプレーヤ向けに変換してくれるソフトウェアは多いが、簡単に音楽ファイルに変換できるものは少ないように感じた。あったとしても動画変換のおまけ機能といった位置付けで、機能が無駄に多く、最適な変換を行うための設定が分からなかったりする。

    従来、私はCraving Explorerの変換機能を利用していたが、

    • 変換するだけのためにブラウザを立ち上げるのは...
    • オリジナルの音源を使えば良いのに変換処理が入ってしまう(時間がかかる、ものによってはファイルサイズが肥大化する)。
    • swfファイルの変換が出来ない。ファイルタイプをみて使用するソフトウェアを変えるのは面倒。

    という不満点があった。

    技術的には、ドラッグ&ドロップをJavaで実装したことが無かったのでやってみよう、というのと、Jakarta Commonsの便利さを実感してみよう、というのがある。

     

    現在の制約事項は以下の通り。

    • ウィンドウ右上の設定ボタンは機能しない。現在のところ、設定変更はファイルを直接編集する必要がある。設定ファイルは初回起動時に、ホームディレクトリ直下に.ipum/ipum.xmlとして作成される。WindowsXPの場合は C:\Documents and Settings\user\.ipum\ipum.xml となる。
    • 一旦登録したファイルは削除できない。これはただの実装漏れなので、近いうちに修正したい。
    • ファイル名によっては変換に失敗するものがある(ハートマークが入ったもので必ず失敗することを確認)。これはffmpegの制約のようだ。対策としては変換時、一時的にファイル名を変更するなどが挙げられる
    • 音楽ファイルフォーマット(エンコード方式)は変換元のファイル拡張子から決め打ちしているので、想定と異なるエンコードだと変換できても聴けないものが出てくるかもしれない。
    • 動作環境はJava6ランタイムがインストールされたWindows。ネイティブバイナリを使用していることの他、Javaでのdrag&dropの実装がOSごとに異なるらしい。

    2009/11/06

    [読書]「科学者になる方法」 科学技術振興機構(JST)プレスルーム編

     

    本書「はじめに」より。

    進路に迷っている高校生の皆さんや、科学に興味を持っている方々が「理系に進んだらこんな仕事をするのか」、「研究者の日常生活はこうなのか」など、「研究者の実像」が分かるような本を作ってみようということになったのです。

    タイトルや掲載順は異なるが、原稿作成者はSciencePortalのページ「科学者になる方法」と同じであり、内容のイメージは掴める。おそらくwebにあるのが、原稿で、これを基にインタビューを行いまとめたものが本書なのだろう。

    研究分野ごとに章がわかれており、それぞれ以下の通りとなっている。

    1. 環境分野。2名。
    2. 情報通信分野。4名。
    3. ライフサイエンス分野。16名。
    4. ナノテクノロジー・材料分野。11名。

    webでは34名登場しているのに対し書籍では合計33名になっているのは、書籍では毛利衛氏の文章はコラムとして扱われているため。

    冒頭引用文及び、上記webのタイトルを一覧するとわかるが、本書は書籍名である「科学者になる方法」というより、『科学者の半生』という色が強い。

    この他、『○○先生の研究』という節でそれぞれの著者が行っている研究の概要を、『研究者になるなら-先生からのアドバイス』という節で研究者としての資質や、どう考え行動していくべきなのか等が記述される。この3節がこの書籍の構成になっている。

    研究分野の比率は前述のとおり情報工学分野は少ないため、研究内容についてはあまり関心が生まれなかった(全く無いというわけではなく、例えば野依良治氏の文章の中にある、鏡に映った右手の手袋から不斉合成の説明をされるくだりは大変面白かった)のだが、アドバイスの節は読んだ価値を感じさせてくれた。著者ごとに反対の意見とも言える主張をされているものもあり、面白い。

    途中のコラムに「研究者へのキャリアパス」というものがあり、ここでは、最終的な研究環境として『大学研究者』『公的研究機関』『企業研究者』の3種類が挙げられている。この書籍に登場されている方をカテゴライズしてみたところ、以下のようになった。

    1. 大学研究者: 25名
    2. 公的研究機関: 5名
    3. 企業研究者: 4名

    執筆の以来を行う際の伝手の問題なども影響しているのだろうが、やはり研究者になろうとした場合の正攻法は(おそらく世間のイメージどおり)大学研究者になることなのだろうか。

    2009/11/05

    FEST-Swingを利用する(6) 非EDTでのSwingアクセスを検証する

    Swingのスレッドポリシーに記載されている通り、Swingコンポーネント及び関連クラスはイベントディスパッチスレッド(EDT)で実行する必要がある。

    スタンドアロンなプログラムを作成している場合には、上記リンク先に記載されているとおり、あまり意識する必要がない。しかし、クライアント/サーバ間で非同期通信を行うプログラムなどでは、よく誤ったコーディングを見かける。

    本エントリでは、上記問題の簡単な実例と、それに対するFEST-Swingでの検証方法について記述する。

     

    サンプルの説明

    今回のサンプルコードはこちらになる。本サンプルコードは、GUIを持つクライアント(client.Client)とサーバ(server.Server)が登場する。

    クライアントは、サーバに要求を行い、サーバからその結果を受けた際に、画面に結果を表示する機能を持つ。

    サーバは、クライアントからの要求を受け付けた後、非同期で処理を行い結果を通知する機能を持つ。

    cs_sequence

    (余談。JUDE/Community 改め astash* community、最近のバージョンでは、印刷やコピー時に、上図のような透かしが入るようになったようだ。あくまで試用版、という色合いが濃くなったということか。JUDEは2009年末までダウンロード提供、とのこと。)

     

    注目すべき箇所

    結果を表示するラベル(resultLabel)に文字列を設定している2箇所に注目する。

    1箇所目はclient/Client.javaの106行目requestButtonActionPerformed メソッド中になる。要求ボタンを押した際に実行される。

       1: private void requestButtonActionPerformed(java.awt.event.ActionEvent evt) {                                              
       2:     resultLabel.setText("要求中...");
       3:     server.request();
       4: }

    2箇所目は同ファイル134行目 listen メソッド中になる。サーバからの通知を受けた際に実行される。

       1: public void listen(String str) {
       2:     resultLabel.setText(str);
       3: }

    どちらも同じようにイベントハンドラの中でラベルに文字列を書いており、実行してみても通常問題は発生しないため、このような実装が行われているのをよく見かける。

    しかし実際は、一方は問題ないが、もう一方は冒頭記述のSwingスレッドポリシーに反している。

    1点目のメソッドはJButton#addActionListenerメソッドで登録したハンドラであり、これは、ボタンが押された場合にEDTで実行されることが保証されている。

    一方、2点目のメソッドはサーバ側のタイミングで実行される(今回の場合はサーバスレッドが実行する)。従って非EDTで実行されてしまっている。

     

    FEST-Swingを用いた検出

    FEST-Swingでは、上記のようなコーディング誤りを検知する方法を提供している。FailOnThreadViolationRepaintManagerというクラスがこれに当たる。

    利用するには、JUnitのテストクラスの@BeforeClassで以下の1行を追加すればよい。

       1: @BeforeClass
       2: public static void setUpClass() throws Exception {
       3:     FailOnThreadViolationRepaintManager.install();
       4: }

    サンプルコードのテストケースを実行してみると、例外EdtViolationExceptionが発生し

    Exception in thread "Server Thread" org.fest.swing.exception.EdtViolationException: EDT violation detected

    から始まる例外スタックトレースによって、前述2点目のハンドラに問題があることが検知できる。

    ただし、JUnit自体は正常終了している。これは、前回記載した事項と同様で、JUnitを失敗させるためには、JUnitスレッドで例外を送出する必要がある。

    実際のプログラムでは、あらゆるスレッドやプロセス(通常、クライアントとサーバは別VMだろう)で発生した例外をJUnitスレッドに集約することはできないだろう。ただし、ユニットテスト時、このようなテストにはモックオブジェクトを使用するのが通例だと考える。従って、モックオブジェクトのスレッドで発生した例外を、前回のようにJUnitスレッドに教えるコードを追加すれば正しく問題を検知できるテストコードが作成できると考える。

    FailOnThreadViolationRepaintManagerを用いた検証は完璧ではない(これについては次回記載予定)のだが、十分役に立つのではないだろうか。

    Enum<?>にキャストしようとするとコンパイルエラー"変換できない型"が発生する

    こちらの例にあるように、

    public class Test {
        enum Planet { EARTH, MARS }
     
        public static void main(String[] args) {
            Enum<?> e1 = Planet.EARTH;
            // Hmm, doesn't compile
            Planet e2 = (Planet) e1;
            // Well this compiles, but it's not pretty!
            Planet e3 = (Planet) (Object) e1;
            // So does this ....
            Planet e4 = (Planet) (Enum) e1;
        }
    }

    をコンパイルすると、7行目(Enum<?>の部分)で"変換できない型(inconvertible types)"というエラーが発生する。

    どうやら原因はSun JDK6のバグだそうで、JDK7では解消されている[追記: JDK6u18以降でも対応された]。

    今回のようなバグは、Eclipse上で開発を行ってEclipseのコンパイラを使い続けていると全く気付かず、さあjarに固めようか、といってAntでjavacすると...というようなタイミングで発覚するので性質が悪い。

    NetBeansなら保存時の自動コンパイルでも(少なくともWindowsでは)デフォルトでSunコンパイラを使用するため、早期発見しやすいのではないかと思う(最終成果物はSunコンパイラでコンパイルすることが大半だろう、という前提の下で)。

    一応、Eclipseもビルダーの設定を行えば保存時コンパイルにSun JDKを使用するようにも出来るようだが。

    2009/11/04

    TrlLogEditor 1.1

     

    trlフォーマットファイルの編集ツールTrlLogEditorだが、Ver1.0aでは速度表示において、特定の条件下で誤差を含む値を表示していたため、これを修正した。

    TrlLogEditor.jar Ver.1.1をダウンロードする

    前回、

    ファイルフォーマットを独自で解析している都合上、このプログラムで保存したファイルが正しくない結果になる可能性がある。

    というように記載したが、他の方の解析結果も同様なので、間違いは無いのではないかと思う。

    Holux m-241のtrlファイルフォーマット

    以前予告したとおり、trlファイルについて記述しようと思ったのだが、既に日本語でも解説されているサイトが複数あるようなので、繰り返し説明する必要がないと考え、解説サイトの紹介にとどめる。

    それぞれ、自作ユーティリティやスクリプトも公開されている。

    « 2009年10月 | トップページ | 2009年12月 »

    other sites

    • follow us in feedly
    • github
    • stackoverflow

    ソフトウェアエンジニアとして影響を受けた書籍

    • Christain Bauer: HIBERNATE イン アクション

      Christain Bauer: HIBERNATE イン アクション
      理論と実践が双方とも素晴らしい製品であるHibernate。本書はそのプロダクトを書名に冠していますが、Hibernateを使うつもりがなく、ORマッピングの解説書として読むにしても十分な良書です。Second EditionとしてJava Persistence With Hibernateという書籍も出版されていますが、残念ながら現在のところ 和訳はされていません。-インアクションは2.xの、Java Persistence-は3.1の頃のものなので、最新版とはちょっと違うところもあることに注意。 (★★★★★)

    • アンドリュー・S・タネンバウム: 分散システム 原理とパラダイム 第2版

      アンドリュー・S・タネンバウム: 分散システム 原理とパラダイム 第2版
      クライアント/サーバシステムを構築する上で必要となる知識が総論されてます。Web技術者も、フレームワーク部分を開発するのであれば必読。 (★★★★★)

    • Joel Spolsky∥著: ジョエル・オン・ソフトウェア

      Joel Spolsky∥著: ジョエル・オン・ソフトウェア
      前述の書籍「ソフトウエア開発プロフェッショナル」をより砕いたもの、という感じでしょうか。 前書きではプログラマでなくSE向けの本のように書かれているが、プログラマが読んでも面白い本であると思われます。 SEになった新人(あるいはそういう会社に入る/入りたての人)にとっては、これからどういったことが仕事を遂行していく上で起こりえるのか、どのように考えて行なっていけばいいのか決定する助けになると思います。 元は″Joel on Software″というブログの記事で、web上でも一部日本語で読めます。 http://japanese.joelonsoftware.com/ (★★★)

    • ドナルド・C・ゴース,ジェラルド・M・ワインバーグ: ライト、ついてますか

      ドナルド・C・ゴース,ジェラルド・M・ワインバーグ: ライト、ついてますか
      問題解決(一昔前のの流行語で言うところの『ソリューション』)能力は、システムエンジニアのスキルとして備えるべきもののうちのひとつです。しかし、これは難しい。学校で出されるテストと違い、唯一の、(問題提出者が想定している)解を求めるだけが「問題解決」では無いからです。そもそも、何が問題なのか、それは本当に問題なのか、それは本当に解決すべき問題なのか、その問題解決方法は正しいのか、などを解決しなければ、「その解は正しいのか」に辿りつくことができません。この本の最も良いところのひとつは、本があまり厚くないこと。すぐに読めるし、何回も読み返す気になるでしょう。 (★★★★★)

    • スティーブ・マコネル: ソフトウエア開発プロフェッショナル

      スティーブ・マコネル: ソフトウエア開発プロフェッショナル
      コードコンプリートで有名なスティーブマコネルの著書。新人SEに読んで欲しい。個人として業界の中でどうあるべきか、組織としてどうあるべきか、SEのプロ意識とは?SEの心構え概論、といったところでしょうか。また、業界における資格の重要性についても説かれています。この業界では資格が特に軽んじられる傾向がありますが、この傾向はどんな弊害をもたらすのか、将来的にこの業界は資格に対してどのような姿勢で臨んでいくべきなのか。日経BP社では(他の出版社もだが)最近、似たような類いのあまり面白くない書籍が乱出版されていますが、この本は別格だと思うので安心して購入して欲しいと思います。 (★★★★★)

    無料ブログはココログ