ISBNから本のタイトルを取得する

android 
作りたいAndroidアプリがあって、ISBNから本のタイトルを取得するWEB-APIを探した。

以前使ったことがあるAmazonのWEB-APIを使おうかと思って、以前はずいぶん色々面倒だったけど今は改善されてるかなと思いながら探してみたのだけれど、他のいろいろなAPIばっかり案内されて迷子になったので保留。(そういえば昔使ったときもドキュメンテーションが分かりにくかったのを思い出した)

適当に他のをぐぐってたらGoogleBookSearchというのがいつの間にか出来ていて驚いた。詳しく見てないけどブクログみたいなソーシャルサービスっぽいのもあって、これもWEB-APIで操作できるらしい。リファレンスを検索してみると、ISBNから本の情報を取得できるっぽかったので取りあえずそのままリファレンスを読みつつクライアント用のソースコードをダウンロードをしてみる。やっと終わったと思ったらファイルサイズが10Mくらいあって面倒そうな感じがしたので、解凍する前にこれはパスした。

さらにぐぐってたら、楽天ブックスが提供するWEB-APIがあった。これはrest形式で取得できるらしいのでクライアント側をシンプルにできそうだと判断して試用。リファレンスを読んで、試してみたらとりあえず目的は達成できそうな感じだったので本採用。

こうしてブログに書いてみると「っぽい」とか多くて大丈夫か自分、と我ながら気になったものの、趣味なんだから構わなということにして実装続行。

photo:AttributionNoncommercialShare Alike Some rights reserved by Saad Irfan

[Java,log4j]log4jでのログ出力を、標準出力と標準エラー出力に振り分ける

cc:mwichary

仕事で以外に手間取ったのでメモ。

log4jのログ出力機構は、Loggerごとに複数Appenderを設定できるが、各Loggerには1つの出力レベルしか設定できない。なので普通に設定するだけだと、同一カテゴリに対する特定レベルのログを複数Appenderに出力することは出来ても、ログレベルごとに出力先Appenderを振り分けるような事は出来ない。

なので例えば、標準出力にはdebugを含めて全てのログを出力し、標準エラー出力にはerror,fatalだけを出力したいような場合に困ってしまう。

これを解決するには、Appenderにfilterを適用する。

ログ出力設定を読み込む。(javaコード)

org.apache.log4j.xml.DOMConfigurator.DOMConfigurator.configure("log4j.config.xml");

log4j.config.xml

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

    <!– 標準出力へのアペンダ –>
    <appender name="stdout" class="org.apache.log4j.ConsoleAppender">
        <param name="Target" value="System.out" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d %5p %c{1} – %m%n"/>
        </layout>
    </appender>

    <!– 標準エラー出力へのアペンダ(ERROR,WARNのみ出力) –>
    <appender name="stderr" class="org.apache.log4j.ConsoleAppender">
        <param name="Target" value="System.err" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d %5p %c{1} – %m%n"/>
        </layout>

        <!– ERROR, WARNのみ出力するfilter設定 –>
        <filter class="org.apache.log4j.varia.LevelMatchFilter">
            <param name="LevelToMatch"  value="ERROR" />
            <param name="AcceptOnMatch"  value="true" />
        </filter>
        <filter class="org.apache.log4j.varia.LevelMatchFilter">
            <param name="LevelToMatch"  value="FATAL" />
            <param name="AcceptOnMatch"  value="true" />
        </filter>
        <filter class="org.apache.log4j.varia.DenyAllFilter" />
    </appender>

    <!– 特定製品についてはdebugレベルで出力しておく(不要ならこの要素ごと削除する) –>
    <logger name="com.example">
        <level value="debug" />
        <appender-ref ref="stdout" />
    </logger>

    <!– 全体ではエラー出力のみログ出力 –>
    <root>
        <level value="error" />
        <appender-ref ref="stderr" />
    </root>

</log4j:configuration>

javaプログラムの標準出力先、標準エラー出力先を指定するには(Windowsの場合)

(java 実行クラス名 2 > stderr.txt) > stdout.txt

のように指定すればよい。

Androidケータイ触った

一般的には「Androidケータイ」ではなくて「Googleケータイ」というのでしょうか。
��OSにこだわる呼称は、技術者だけ?)

会社で、開発テスト用のAndroidケータイを購入してもらいました。
触った感じ、ですが、キーボードが無いからか、思っていたより軽くて小さいです。手に持った感じでは、普通の携帯電話として使うのにそれほど違和感が無い大きさです。
WillcomのZERO3とか、携帯電話としては違和感ありまくりの大きさだったのを考えると、HT-03Aは、PDAとしてではなく、携帯電話として製品デザインされたんだなぁ、と思いました。

ハードウェアボタンが付いてますが、小さいので押しにくいです。でも、iPhoneみたくハードウェアボタンが全然無いよりは使いやすいかも。

Android端末が欲しい(第三回Androidセミナ in 大阪の感想)

先週末、大阪で開かれたAndroidセミナに参加してきましたので、その感想です。
えっと、レポートではありません。

ハンズオンセミナということで、セットアップしたノートPCを持って行ったのですが、画面解像度が600しかなかったため、ウィザードの必須項目を埋められず、速攻でドロップアウト…結果、見て聞いてきただけとなってしまいました。

とはいえ、実際の開発で使われるツールを目の当たりにし、初心者が陥りがちな落とし穴について解説を聞き、実機を(遠目にですが)見ることができたのは、それなりに収穫だったと思います。端末欲しいけど、携帯回線の契約しないと使えないしなぁ…。夫婦で使っているWillcomはohaに加盟していないので、作ってくれそうにないのが残念。


第一回 京都プログラマ読書会 無事完了、そして第二回のお知らせ

またまた先々週の話…振り返りモードがもうしばらく続きます…。

2/10 KPRC「増補改訂版JAVA言語で学ぶデザインパターン入門」第一回は、Iterator, Adapter, TemplateMethodをやりました。

TemplateMethodは私が一番好きなデザインパターンです。
超絶便利です。使う人が慣れるのは面倒ですが、コード量も激減できるし。フレームワークと呼ばれるものはほとんど、このパターンで実現されているのではないでしょうか。匿名クラスで実装するヤツがJavaっぽくて特に気に入ってます。
でも、もう終わってしまった…

あとは、Compositeと、Commandが好きですが、その話はまたいつか書きます。

次回はFactoryMethodからです。第二回は2/24(火)です。
参加をご希望の方は、こちらからどうぞ。

期待を裏切らなかったフレームワーク : Wicket

安心感だと思う。

Javaでプログラムを書いているとき、私が重視している"気持ち"は、安心感だ。

Wicketフレームワークについてのエントリを書こうとして最初、その「Javaらしさ」を褒め称えようと考えた。でも、Java"らしい"とはどういうことか? というのを書こうとすると、XMLを書かなくていいからだ、とか、そういう他のフレームワークをけなすような書き方になってしまう。それはしたくなかった(書いちゃったけど)。

そこで、自分の感情に注目してみた。つまり、Javaらしいプログラムを書いていると、どんな気持ちがするのか?

Javaはコンパイラ言語で、少しのプリミティブを除いた全てがClassとして表現される。変数の参照型は厳密にチェックされ、やろうと思えば、かなりのエラーをコンパイル時に検知することができる。実行時に付きまとう不安感を減らせる。これはプログラミング時の安心感につながっている。これが"Javaらしさ"だと思う。

WicketほどJavaで書けるWEBアプリフレームワークというのを、他には知らない。

Wicketでは、XMLに書かないといけないのは、サーブレットマッピングくらいだ。それ以外の設定事項は全部、Javaに書く。

JSPだって書かなくて良い。JSPほとんどJavaみたいなもんだけど(コンパイルもできるし)…。MVCモデルだからViewModelクラスを作って…なんて当たり前のようにしていたけど、その冗長さが今では鼻につく。Wicketでは、JSPどころかテンプレートですらない。XHTMLで十分だ。wicketネームスペースのid属性だけは必要だけれど、本当にそれだけだ。JSPならjavascriptでやっていたことも、Wicketなら大体Javaで書けてしまう。
MVCアーキテクチャをStrutsで知った、なんて言う人が多いと思うけど、そのStrutsでも、Vのところはせいぜい半分くらいしかJavaじゃなかった。Wicketでは少なくとも80%くらいはJavaだ。

私がWicketフレームワークのことを知ったのは、2年くらい前だと思う。どんどん立ち上がるJavaのWEBアプリ向フレームワークを追いかけるのが少し食傷気味になっていた頃だ。
その時から色々なところで「WicketはJavaらしいフレームワークだ」という話を読んだいた。私は"Javaらしい"フレームワークがきっと性に合うだろうと思っていたけれど、なかなか実際に触ることをしなかった。雑誌でチラっと読んだりしただけだ。
他のフレームワークでは、ちょっとがっかりすることが多かったから、どうせまた期待を裏切られるのだろうな…という諦めのようなものがあったのかもしれない(単に面倒だっただけかもしれないけど)。

でも、触ってみたら、ビビっと来た!

こんなに「かぶせたくなるところが少ない」フレームワークは始めてだ。拡張したくない、というのとは違う。むしろ、拡張はしたい。でもそれは、あくまでも拡張するのであって「隠す」のとは違う。これまで、特に、業務で使っていたフレームワークでは、隠したくなるところが本当に多かった。何でこんなに変なモデルなのか? 中途半端な拡張ポイントばかりあるのか? 無駄に自由度が高そうに見せるのか? 気に入らないところが沢山あった。

Wicketには、そういうところが無い。まだ見えていないだけかもしれないけれど、かなり惚れこんでいる事は確かだ。

AmazonWEBサービスAPIが前より使いやすくなっていた

昨日久しぶりに使おうとおもって公式サイトに行ったら、ちゃんと接続用のライブラリが、jarファイルで提供されていました。昔はwsdl(だっ
け?)ファイルをaxis(だっけ?)に入力してモデルやらXMLパーサやらを生成して、axisの不具合っぽいところを手直ししたりしてようやくAPI
を使える状態になる、という面倒くさい状態だったんだけど、今はちゃんとそこまでやったものが最初から配布されてます。こういう一手間、二手間で敷居が下
がって(Javaからの)利用者数が2倍3倍になるんだろうと思う。Amazonは、なんで今までやってなかったんだろう?

それと、AmazonWEBサービスAPIは、ときどきバージョンアップしてるらしくてインターフェイスのバージョン管理という視点から見ても面白そうだと思った。互換性をどうやって維持しているのか、とか。

匿名クラスの初期化でインスタンス初期化ブロックを使う

矢野勉さんのブログに良いことが書いてあったのでメモ。
匿名クラスに新しい(基底クラスに定義されていない)コンストラクタを定義することは出来ない(コンストラクタを書くにはクラス名が必要だが、匿名クラスには勿論クラス名が無いので)。
そのかわりに、インスタンス初期化ブロックを使って以下のように記述することが出来る。

List<String> list = new ArrayList<String>() {{add("a"); add("b"); add("c");}};

ちょっと便利な気がする。無いと困る場面はちょっと思いつかないけど…。

SRP, OCP, LSP

「アジャイルソフトウェア開発の奥義」の読書メモ。
「アレ、なんだっけな」となりそうなのでメモしておく。

単一責任の原則(SRP:Single Responsibility Principle)

クラスを変更する理由は1つ以上存在してはならない

1つの役割とか、1つの責務、とか言わずに、1つの変更理由としているところが運用のための工夫らしい。

オープン・クローズドの原則(OCP:The Open-Closed Principle)

ソフトウェアの構成要素(クラス、モジュール、関数など)は拡張に対して開いて(オープン:Open)いて、修正に対して閉じて(クローズド:Closed)いなければならない。

ポリモーフィズムを使いましょう、という話。

リスコフの置換原則(LSP:The Liskov Substitution Principle)

派生型はその基本型と置換可能でなければならない。

継承関係を用いるべき基準として、対象となるクラスがあらわす概念が「is-a」なことだけでは不十分。そのすべてのメソッドの振る舞いまで含めて同じ性質でなければ、クライアントを困らせるという意味。テンプレートメソッドパターン以外で継承を使うときは注意しないといけないなぁ、と思った。メソッドをオーバーライドをするときの注意事項も引用しておく。「ルーチンの再定義をする場合、事前条件についてはオリジナルと等しいか、それより弱い条件と置き換え、事後条件についてはオリジナルと等しいか、それより強い条件と置き換える

Enumまたはタイプセーフenumイディオムを使う – 定数を定義するためだけにインタフェースを使わない

時々、こういうコードを見かけないだろうか。



public interface XxxConst{

public static final String XXX_TYPE1 = "TYPE1";

public static final String XXX_TYPE2 = "TYPE2";

public static final String XXX_TYPE3 = "TYPE3";



public static final String AAA_ENABLED = "1";

public static final String AAA_DISABLED = "0";



//...つづく

}

このような「定数を定義するためだけのインタフェース」*1が私は嫌いだ。

理由は以下のとおり。

  • 最初に書いた人は良いけど、そこに何かが追加されるにしたがって、どこに何を追加すべきなのかを判断するのが簡単ではなくなっていく。使う方だってわかりにくい。そのinterfaceのメンバ数が100を越えて「XXX_TYPE1とXXX_TYPE1_CDって何が違うんだ? 僕はどっちを使えば良いんだ?」と皆に訊いてまわるのは嫌だ。(そして誰も答えられなかったりするし!)
  • こういうコードは、たいがいは片付けが貧弱で、せいぜいStringとintを使い分けてるだけっていうレベルだ。そんなコードを、コンパイルが必要なJavaでわざわざ書くというのは、なんか勿体ない感じがする。
  • 各定数に振る舞いを定義できないから、定数ごとに異なる振る舞いが必要になった場合は、その数だけ長い長いif,elseを書く必要がある。コードベースのあちこちに段々と増えていくそれを、全部もれなくメンテナンスするなんてウンザリする…。

「interface XxxConst方式は定義するのが簡単」という意見があるけれど、それは最初のうちだけだ。小さな書き捨てのプログラム以外では、すぐに今書いたような混乱が生じる。

では、どういう風に書けば良いのだろう?

Java5では、Enumが使えるようになった。それJ2SE1.4以前のバージョンでは、タイプセーフenumと呼ばれるイディオムを使って記述できる*2。このイディオムを正しく書くのはちょっと面倒だけど、EclipseのJETなどを使えばそれほどでもない。見返りのほうが断然大きい。

*1:標準ライブラリのBigDecimalクラスには似たような方法で丸め方法に紐付けられた定数が定義されている。あれは、丸め処理を書く必要にせまられた世界中のプログラマをイライラさせているのではないだろうか?

*2:Effective Java 98ページを参照