ラベル programming の投稿を表示しています。 すべての投稿を表示
ラベル programming の投稿を表示しています。 すべての投稿を表示

2009年8月31日月曜日

民主党マニフェストのテストコード

プログラミングの世界ではコードの動作を確認するために「テストコード」を書きます。仕様の変更などでコードを大幅に修正する機会は多いのですが、テストコードがあれば重要な機能が動かなくなった場合でも、すぐに確認できます。政治の世界でも、マニフェストの実現度合いを確認するための「テストコード」が必要ではないでしょうか。

テストコードを動かしてみると以下のようになります。今はマニフェストの実装(実現)段階なので、もちろん真っ赤(すべて動いていない状態)です。



テストをすべてパスすると、表示は緑になるはずです。



このようなテストコードがあると、政治の解釈、問題点がゆがめられていないかを、その都度確認していくことができます。一票を投じることも大切ですが、一般に分かりやすい部分しか報道しないマスコミに頼らず、各々が持つ専門的な知識(育児、教育、研究、経済などなど)を活用して、自らの目で政治が行われる様を監視していくことが大事だと思います。

このブログを読んでくれている皆さまも、自分が政治に期待するものを「テストコード」の形でメモしていってはいかがでしょうか?

ソースコードはこちら:

import static org.junit.Assert.*;
import org.junit.Test;

public class ManifestoTest
{
@Test
public void 子ども手当・出産支援() {
fail("保育所の確保など、職を失わずに子育てできるようにはなってない");
}

@Test
public void 公立高校の無償化() {
fail("本当は大学まで親の所得に関わらず通える仕組みが必要");
}

@Test
public void 年金制度改革() {
fail("無責任がまかり通った原因と責任の追求、再発防止の仕組みが必要");
}

@Test
public void 医療・介護の再生() {
fail("過剰労働・安給料で勤務医や介護を担うのは無理です");
}

@Test
public void 農業の個別所得保障() {
fail("国内農家を優遇して、国外の安くて安全な食べ物を輸入できなくなると、消費者にとってはマイナス");
}

@Test
public void 暫定税率の廃止() {
fail("省庁の聖域である特別会計に本当にメスを入れてくれるのか?");
}

@Test
public void 高速道路の無料化() {
fail("報道ステーションでは、民主よりの無料化提唱者より、猪瀬氏の方がまともだった。。。");
}

// 個人的な願い
@Test
public void 選択的夫婦別姓() {
fail("何年待たせるのか");
}
}

(上のコードは適当に書いていますが、実は、この「テストコード」の中身をどう実装していくかも大きな問題)

2009年7月30日木曜日

未来を予測する一番よい方法は、自ら未来を創ることだ

石井先生の基調講演で紹介されていた言葉:
The best way to predict the future is to invent it. - Alan Kay
(未来を予測する一番よい方法は、自ら未来を創ることだ)
Alan Kayは、今や常識となったオブジェクト指向プログラミング(1960-1970年代ごろ)や、ウィンドウを重ねるGUI、ノートブック型のコンピュータ(Dynabook, 1968)など、現在のパソコンの基となるアイデアを考案してきました。それらの功績から2003年にはACM Turing賞(いわば、Computer Scienceのノーベル賞)を受賞しています。

彼がこれらのアイデアを考案して40年後の今、僕の目の前にはウィンドウがあり、オブジェクト指向の考え方を使ってプログラムを書いています。彼の言葉は、まことにむべなるかなと思わざるをえません。

2009年4月24日金曜日

ごめんなさいごめんなさいごめんなさい


机の上にごちゃごちゃ物を置いているやつは総じて能力のないプログラマー

新人プログラマーがプロのプログラマーとして独り立ちするための7つの条件 - ハックルベリーに会いに行く

ごめんなさい

ごめんなさい - 西尾泰和のはてなダイアリー

ごめんなさいごめんなさい (IT戦記)


もひとつ、ごめんなさい

2009年3月26日木曜日

プログラマは世界をこう視る

プログラマが普段どのように問題と向き合あっているかを知るのに、これはうってつけ。



今回、縁があってこの本の出版のお手伝いをさせていただきました。内容はやや難し目のパズル問題集。すべての問題に目を通して、紙と鉛筆で解けるものもあれば、実際に手を動かしてプログラムを書いてみたり。前半は、プログラマでない人でも取り組めるようになっていますが、お勧めは実際にプログラムを使って解く後半。

プログラミングコンテストに挑んだことのある人には、もうおなじみの考え方だと思います。普通の人間ならやらないけれど、コンピュータというお供がいると、すべての可能性を調べ上げるような愚直な方法でも着実に実行してくれる。その様子を見て、人間がより良いアルゴリズムを思いつく、というサイクルが問題を通して学べます。

例えば「数独」。日本では、紙と鉛筆で解くパズルの代表例になっていますが、プログラマの手にかかると、コンピューターを使った答えの探索問題に早変わりです。

原著者のDennis Shasha先生も以下のように述べています。
授業中、私は、いわゆる“講義” をほとんどしない。その代わり、パズルを解くテクニックを披露する。問題の“解答” ではなく、“解法” を紹介するのだ。(中略)面白いことに、学生たちはその週の授業を終えると、自分の問題解決能力が向上していることに驚く。授業を通して得られた体験が、現実問題への取り組み方の一部なのだ。
現実の問題にどう取り組むかを、パズルを通して学ぶ。そのような「プログラマの視点」を垣間見られる例を挙げるとするなら、たとえば、Googleが膨大なデータを扱うために開発したMap-Reduceという計算フレームワーク。その仕組みは説明するととても簡単(問題を分割して解いて、後でまとめるだけ)ですが、それを生みだしたベースとなる物事の見方が、まさに「プログラマの視点」なのです。

こればかりは考え方(Shasha先生の言う「解法」)を知らないと、なかなか0からは出てこないものなので、既にプログラマの人にも、これからプログラミングを始める人にも、お勧めの1冊です。

(補足)
すでにこういった考え方に親しみのあるプログラマにとっては、後半より、前半のパズル問題の方が難しくて手ごたえがあると思います。腕に覚えがある方は、頭のトレーニング用にもどうぞ。

関連:

2009年2月9日月曜日

Pondering Bug Tracking Systems

As a programmer, I have many things to hack, but unfortunately I am not smart enough to remember everything to code after I slept. In the next morning, I usually forget some features to code. Bug Tracking System (BTS) is useful to keep remembering these tasks.  Joel Spolsky also  wrote an article about Bug Tracking Systems, and I totally agree with what he said; Bug tracking system is necessary to ship high quality code. 

I am using Bug Tracking Systems, such as Bugzilla, Trac, etc. (and also their Eclipse plug-ins). Once they are properly installed in a server machine, they works correctly, and I know many projects use these tools to share bug & new feature lists. 

However, their web interfaces are not fun to use; I have to input many things to post a bug or feature, such as priority of the bug, current program version, who to assign the task, etc. Almost all of them are unnecessary for writing code, and sometime I do not want share tribal tasks merely saying 'implement SomethingReader class', but without posting it, I might forget it due to some interruption of my work.

Because of these frustrations, I have recently switched to the Remember the Mlik (RTM) service to manage my bug & feature lists. RTM's AJAX-based rich web interface have some nice shortcut keys (e.g, 't' for a new task, 1, 2, 3 ... for selecting priorities), and with Google Gears installed on your browser, you can edit tasks while you are offline. As the name 'Remember the Mlik' indicates, RTM can be used to manage quite tribal tasks; you can simply post 'write this code and that' to RTM, while this message does not make sense for the other people, it is quite informative for 'me'. 


Free from explaining what to do for other people has a great effect on accelerating daily programming productivity.  I'm not saying 'BTS is unnecessary', rather I'm saying BTS is necessary for sharing bugs and features, but not for personal work management. Well-known BTSes have too rich features for the personal use. What I want to do is to take a memo at online using web interfaces I open every day, and Remember the Milk completely meets this demand. 

2009年1月27日火曜日

正規表現に見切りをつけるとき

Perl, Rubyなど手軽に使えるプログラミング言語に慣れてくると、あらゆるテキストデータの処理に正規表現(regular expression)を使ってしまいがちです。

けれど実は、正規表現の処理能力を超えるフォーマットというのが存在します。その典型的な例が、XMLやJSONのように、入れ子になったデータフォーマットです。

例えば、
(a, b, (c, d))
(a, b, (c, (d, e)))
というように、括弧がどんどん入れ子になっていく構造は、括弧のネストの深さを数えないと正しく解釈できません 。正規表現でも、一番外側の括弧の対応をとらえるために、/\(.*\)/、/\([^)]*\)/ などとはは書けますが、常に正しい括弧の対応をとっているとは限りませんし、もしうまくいったとしても、さらに内部の括弧をとらえるために、外側の括弧を取り除き、また同様の正規表現を内部の文字列に対して繰り返して適用する必要があります。

そして問題なのが、
(a, (b, c)), d, (e, f)
という文字列の場合。/\(.*\)/という正規表現では、以下のように色のついた範囲を拾ってしまいます。
(a, (b, c)), d, (e, f)

正規表現では、このようにちょっとしたデータ構造すら上手く構文解析できません。したがって、正規表現だけで文字列を処理する場合は、何らかの方法で括弧が2重、3重にならないように工夫する必要があります。(あるいは括弧内を再帰的に処理するプログラムを書くなど。)バイオ系のデータフォーマットでも、この正規表現の能力の限界を知らないがために、正規表現で処理できない入れ子になったデータを平気で書いてしまう人が多いので、手軽に処理したい場合は要注意です。(他にも2重引用符で囲まれた文字列の扱いも、正規表現では面倒な例です)



構文解析

では、正規表現の能力を超えるデータはどう扱えばいいのか?一番のお勧めは、ANTLRを使って字句解析(lexer)、構文解析(parser)するプログラムを生成する方法です。一昔前なら、lex/yacc、flex/bison, JavaCCなどしか選択肢がなかったのですが、今は断然ANTLRが便利です。ここでは、JSONを例にとって説明します。以下は、JSONで書かれた配列の中に配列がある構造です。
[0, [1, 2]]
字句解析では、これを、
LBracket([), Number(0), Comma(,), LBracket([), Number(1), Comma(,), Number(2), RBracket(]), RBracket(])
というようにトークン(文字列の単位, lexer ruleとして記述)に分解していきます。そして、これらのトークンにマッチする文法(parser rule)を定義します(以下の例は、説明のために他のデータ型については省いて簡潔に書きました)
array: LBracket Value (Comma Value)* RBracket;
value: Number | array;
ここでは、括弧 [ ] の中に、ValueをComma(,)でつなげて複数個書けるルールを定義しています。Valueとしては、数字(Number)以外に配列(array)も使えるので、配列の中に配列があるような入れ子になったデータ構造もこれで解析できます。

参考までに、僕がANTLRで作成したJSONの文法を紹介します。ANTLRの記述を覚えるコストはかかりますが、1ページ分の記述量でJSONのように構文が複雑なものも処理できるようになります。以下に挙げるのは、ANTLRのリファレンス(英語)と、その背景にある理論の教科書で、コンピューターサイエンスの学科では講義によく使われていてどれもお勧めです。Aho, Ullman先生らのドラゴンブック第2版(Ullman先生の息子さんがCGで表紙を作ったとか)は読みごたえ十分ですし、Apel先生の本ではVisitorパターンの使いどころのような、実装に近い話題にも触れられていて読みやすいです。稲葉君絶賛のParsing Techniquesなどもあります。




構文解析の実践としては、ANTLRをダウンロードするとサンプルの文法がたくさん付いてくるので、それを真似して書くのも習得への早道かと思います。一度ANTLRで文法を書くと、Perl/Ruby/C/C#/Javaなどの言語用のlexer/parserを生成できるようになるので、どの言語を使っている人にもお勧めです。しかし、まだ日本語のリファレンスがないのが構文解析の敷居を高くしている原因でしょう。この記事が素晴らしき構文解析の世界への足がかりになればいいなと思います。


(実用上の補足)

正規表現の中に自己を含めて循環定義できるRubyやPerlなどの処理系なら、入れ子もなんとか処理できるみたいです。以下はPerlのコード例。(「詳細 正規表現 第3版」を参考にしました)

$str = "(a (b, c)), (d), (e, f)";
$paren = qr/\([^()]*(?:(??{$paren})[^()]*)*\)/;
while ($str =~ /($paren)/g) {
print $1, "\n";
}
実行結果
(a (b, c))
(d)
(e, f)
括弧のパターンにマッチすると、その都度中身の正規表現がlazyに変わっていくというトリッキーな技です。このような正規表現は以下に述べるような形式言語理論上の正規表現の定義には含まれないのでご注意あれ。ただ、Perlで処理できるとしても、二重引用符とか、様々な括弧の種類に対応するように再帰型正規表現を書いていくと、ANTLRのparser ruleを書くのと似た状況になるとは思います。(追記)Perl6のRulesという機能では、ANTLRのような文法定義を書けるとか! 入れ子が必要なときは、これを使いましょう、ということですね。

(コンピューターサイエンス的な補足)

細かい話をすると、正規表現は文脈自由文法というクラスのサブセットで、入れ子の構造をもった文法は、文脈自由だけれど正規表現ではありません。これは、pumping lemmaを使って証明できます。情報系の学科なら、計算量理論などの講義で習うはず。オートマトンにスタックをつけたプッシュダウンオートマトン(文脈自由文法と同じ表現能力を持つ)なら、このような入れ子をうまく処理できます。このあたりの話は「計算理論の基礎」という教科書に丁寧に書かれてあって(大学院入試の勉強のときにかなりお世話になりました)、コンピュータサイエンスの基礎のうち、オートマトン、NP完全問題など計算量にかかわる部分について学ぶのに優れた本です。(最近は第2版もでているようですが、3冊に分かれてしまって少々買いにくくなってしまいました。分けた方が持ちやすいのかな?)

2008年11月15日土曜日

21歳からのハローワーク (プログラマ編)

これからプログラミングの仕事に就く人のために、「13歳のハローワーク」よりもう一段深く分類してみました。

プログラマ
プログラムを書く人。

ハッカー
作ったプログラムの価値を認めてもらえるプログラマ。他のプログラマに評価されるほど格が高い。

良いプログラマ
作ったプログラム、コードの品質を、仕事仲間、他の技術者に認めてもらえた人。

良い開発者 (developer)
作ったプログラムの価値を、一般の人に認めてもらえた人。使う人にとって便利なものを作れるなら、ソースコードの汚さは問われない。

ギーク
プログラム、コンピュータ関連の知識に通じている人。ただし、実際に物を作らずとも、オタクっぽい発言を続けることでもなれる。

2008年10月28日火曜日

優秀なプログラマは空気を読んで空気を描く

まず、3つのポイントをおさらい。
  1. 変数のスコープは小さく抑える
  2. Do Not Repeat Yourself (DRYの原則) 同じコードは2度書くな
  3. 言語を極めよ

この1と2は、まったく違うようで、とても似た問題を扱っていることにお気づきでしょうか。それは「依存関係」を減らすか増やすか。


矛盾を抱えるプログラマ 変数のスコープを短くすると、コードで必要なデータを近くにまとめて依存関係を減らすことができます。要するに、コードを

inputから、output(+副作用)を作る

というメソッドと同じparadigm(パラダイム: 枠組み)にまとめたいわけです。この形にすると、コードをメソッドの形に書き直して、再利用することが簡単になります。グローバル変数を多く使っているコードは、依存関係を即座に判断するのが難しく、メソッドに纏め上げるのが大変なので忌み嫌われています。

一方、DRYの原則に従ってメソッドやクラスとして一箇所にまとめられたロジックは、使うユーザーや使われる場所が増えるため、依存関係を増やします。使う場所が増えないなら、メソッドやクラスにまとめる理由は、コードにわかりやすい名前(alias)をつけるくらいの意味しかありません。例えば、あちこちで頻繁に使われる文字列型(string)の最初の文字のindexが0ではなく1に変更されたら、大惨事になるでしょう。

プログラマって、依存関係を減らそうと努力しているかと思えば、一方で依存関係を増やそうと一生懸命になる、とても不思議な生き物です。入力から出力を作る枠組みでしか物事を考えられない、可哀想な生き物でもあります。

変数のスコープを最小に抑えると、リソースを解放するタイミングを明確にできる利点がありますが、GC(garbage collection) を搭載した現代的な言語実装では、不要になったらメモリを即解放というわけにはいかないので、スコープが多少ずれていても、さほど深刻ではありません。

プログラマは空気を読む 学生向けにプログラミングの講義をしていたときに学んだのは、ソースコードを追う能力の乏しい段階の学生さんは、抽象化されたコードの「意味」ではなく、「動作」を追ってしまう、ということ。

例えば、SQLなどは高度に抽象化されたコードの典型例でしょう。(これを宣言型という人も多いですが、抽象化の度合いの違いにすぎません)。以下のSQL文、

SELECT * FROM t1, t2 WHERE t1.id = t2.id

を見て、「2つのテーブルt1とt2でidが同じ値の行を結合する」、と読み取れたなら、おめでとう! もうあなたは立派に優秀なプログラマです。

例え内部で、lexer, parserからなるSQLコンパイラが動いていて、テーブルとクエリの静的型チェックをし、問い合わせスケジュールを組み立て、テーブルのデータ分布に基づいてスケジュールを最適化し、B+-treeとsequentialレコードを、ページロックを取得しながらserializabilityが保証されるようなプロトコルに従って検索して、必要ならライトウェイトロックで管理されたキャッシュにディスクページを保存しつつ、テーブルの結合にディスクを介したhash joinやexternal merge sortを実行していたとしても、そんなことは気にしてはいけません。SQLという入力から得られる結果の意味、つまり空気を読むことが大事です。

プログラミング言語は空気を描くもの どのプログラム言語を極めたらいいかって? 空気を読みやすくて、自分の空気を描けるもの。できなければ拡張するか、作る。これが言語を極めるということでしょう。作るのは割に合わない? 使いやすいプログラミング言語とその実装・ライブラリが出来上がるのを待つリスクが割に合うなら、のほほんと偶然の産物を待つのも一興でしょう。

(追記 10月29日)

考えることを減らせるように書く

長くなったのですが、同じラボにいた川中君がきれいにまとめてくれました。


メソッド(関数)によるコードの整理や、オブジェクト指向による実装の隠蔽、プログラミング言語のなりたちなど、プログラミングのすべてはこの動機から始まります。すばらしい。

2008年10月16日木曜日

優秀なウェブ開発者の見極め方

「Webアプリケーション技術者の見極め方(Java)」 こんな記事を見かけましたが、使えるツールやフレームワークの種類云々を聞くより、単刀直入に欲しい人材を見抜く質問はこれ。


「JavaでWebアプリケーションを開発する利害得失を述べよ」


2008年9月22日月曜日

学校でしか教えてくれないプログラミング言語のこと

Scheme(スキーム)というプログラミング言語について初めて知ったのは、大学2年生のときです。理学部情報科学科に進学し(東大には進学振り分け(通称:進振り)という制度があって、大学2年生の前半までは一般教養を学び、それ以降から専門課程に進みます)萩谷先生担当のプログラミング演習がSchemeとの出会いでした。(当時のものとは大分違いますが、参考までにSchemeの講義資料へのリンクです。http://www-ui.is.s.u-tokyo.ac.jp/~hara2001/scheme/)

おそらく、ここで学ばなかったらSchemeのように一般に知られていない言語には触れることもなかっただろうし、Emacs Lispのプログラム(Schemeと同様の構文です)を自分で書くこともなかったように思います。Emacsというテキストエディタは、自分好みの機能をLispを用いて実装することが醍醐味です。今でも、簡単な計算はLispで書いて、Emacsを電卓代わりにしています。(以下は、階乗の計算をちょこっとLispで書いてみた例。xのn乗を再帰で計算する関数pow(x, n)):
括弧が多くて「何だこれは?」と思われそうですが、括弧の対応付けはエディタが視覚的にサポートしてくれるので、式そのものの見た目ほど入力は大変ではありません。

実用性という意味では、Schemeは非常にマイナーな言語だと思います。けれど、再帰であったり、リスト構造であったり、環境(変数などの状態を運ぶもの。継続とかもそう)であったり、λ関数(クロージャと言ったほうが良いかな?)など、プログラミングで重要な概念を学ぶのには良い言語だと思います。型を学ぶにはOCamlなどML系の言語の方が適しているので、そちらを授業に使う大学も多いようです。


Schemeに関しては思い入れが深く、僕にとってはEmacs(Windows版はMeadow)を使い始めたきっかけでもあるし、情報科学科のCPU実験で、Scheme言語を使って、Scheme言語のコンパイラ(自分達で作るCPU用のアセンブリを生成します)を作ってしまうくらい深く関わった言語でもあります。言語の仕様書(当時はR5RS)もそれなりに読みました。

それを最後に、久しくSchemeから離れていたのですが、思い出させてくれたのが以下の公開質問
「プログラミングに詳しい人に質問です。大学でプログラミング経験の学部一年生向けにプログラミングを教えることを想定しています。週1コマ×半年程度の限られた時間で、プログラミングとはどういうものかという本質を教えたいのですが、どの言語を使うのが適切でしょうか。」
ここでは、プログラミング言語の種類をあまり知らない人を解答対象からはじくために、以下のような質問肢が用意されています。一般の人よりは僕はSchemeを知っていると踏んで、これを読んだときの僕の思考過程(赤文字)も併記しました。

* Schemeは1.5からオートボクシングの機能をサポートした
auto-boxingってJava…
* Schemeはインデントによってブロックを表現する
そんなわけない。括弧だよ
* Schemeは多くのレンタルサーバに標準でインストールされている
もしそうだったら凄い!
* Schemeでは関数がファーストクラスのオブジェクトである
Schemeで言うオブジェクトって何?単にデータという意味だとすると'A (文字を表すsymbol)とかあるし…。(cons 1 2)だと、関数が1と2のペア表すデータ型(オブジェクト)と捕らえることができるけど。。。
* Schemeの文の終わりはセミコロンである
違う違う。
* Schemeは純粋関数型言語であり、副作用はモナドでくるむ必要がある
副作用がない関数型言語って、関数の外側の変数を変更できないってことだよね。そんなことはなかったような、、そもそも、モナドって何?と焦りグーグル検索。。これHaskellに出てくるのか。。
* Schemeは型に厳格なため整数の加算と浮動小数点数の加算の演算子が異なる
そういえばSchemeで型を意識したことがない。。。
* Schemeは関数の呼び出し時に括弧を省略することが出来る
そんなsyntaxあったかなぁ。。。たぶんない。
* Schemeのマクロ定義には#defineを使う
C/C++だよ、それ。(define f (x) ...)はあるけど。
* Schemeの言語仕様はキューマシンとしての実装に適しているため並列化が容易である
キューマシン -> 並列化が容易というロジックにとっても飛躍を感じるなぁ。副作用無しの純粋関数型の範囲なら、Googleのmap-reduceの概念のベースになっているように簡単に分散できるけど。。。
* Schemeのブロックはbeginで始まりend.で終わる
これは違う。
* SchemeのコンパイラとしてはGHCが有名である
GHCって何?聞いたことない。Googleで検索…またHaskellですか。。。知らないよ(涙)
と、まぁ、大変でした。なぜって外部情報で補完しないと正解が出せない質問がたくさんあるから!「多くのレンタルサーバーに」って。。。「多くのレンタルサーバー」の現状を知らないとわからないし。本格的なSchemeの使用例が見当たらないって理由で推測はできるけれど。他にもSchemeにはまだ僕の知らない構文があるのかも…とか不安に思ったり。それでも、Googleで検索すればそれぞれ1分と経たずにわかる程度のことだと思います。とても懐かしく、かつ、知らないことも多くあったので知的な刺激になりました。

プログラミング教育用としての関数型言語

こと、教育のためのプログラミング言語の選択に関しては、ネットワークに接続したり、データベースを使ったプログラミングが必要なら、現時点では迷いなくJavaを選択します。動作させやすいこと、使っている人が多いためEclipseのような使いやすい開発環境が整っていることが選択の理由になります。

Scheme, Lispのような関数型言語の肝は、副作用がないという点だと思っているのですが。たとえば、Googleが超並列計算に使用しているMapReduceのフレームワークでは、

map(入力を2倍にする関数f, {1, 2, 3, 4, 5}) => {f(1), f(2), f(3), f(4), f(5)} = {2, 4, 6, 8, 10}
reduce(入力を足し合わせる関数h, {2, 4, 6, 8, 10}) => 30

というmap, reduceという2つの手続きで計算を行います。map部分をScheme(Lisp)的に書くと、
上のようになります。map関数では、入力リストの先頭(car)から順に関数fを適用していきます。たとえば、以下のような式

の結果は、{2, 4, 6, 8, 10} になります。関数の引数に関数f(lambda文を使ってxを2倍する関数を定義している)を渡して、内部では{(* 1 2), (* 2 2), (* 3 2), ... }を計算しています(+演算は前置記法)。ここで大切なのが、map関数内で、関数fの実行順に制約がないということです。つまり、個々の関数fの実行では副作用がない(!)ので、どの順番で実行してもよく、この部分を言語の実装次第で並列化することができます。

GoogleのMapReduceではこのような副作用がないというプログラムの意味(semantics)を活用して、個々のmap操作を別々のノードに計算させて超並列化を可能にしています。関数型言語を用いるとこの副作用のない部分を明確に記述できますし、驚くほど多くの計算がmap-reduceの組で書けるようです。例えば、forループで先頭から順に辿らなくても良い場合が見つけやすいと思います。Googleは並列化を促進するために、入力listのコピーをいつくかのノードに分散して配置する工夫も行っています。検索エンジン用の索引構築なども、このMapReduceのフレームワークで再実装したとMapReduceの論文には書かれています。

再帰の概念は他言語でもよく見かけますが、関数型言語の特徴である副作用がない(データすら関数で表現されている)コードの書き方というのは、手続き型言語であるJava, C/C++など、実際の開発現場でよく使われるプログラムの書き方から入った人には、とても気付きにくいものだと思います。関数に関数を渡すという概念も、何十年も前の関数型言語の研究から、他に移殖されたものです。

これらの通常では気付きにくい概念や、既に一般に当たり前のように使われていることの裏にある理論を教えるのが大学のあるべき姿であると考えます。特に、簡潔な記述で速く動くことに主眼に置くcomputer scienceの分野では、プログラミングの授業も、言語を問わず、一般の技術者向けの勉強本では深く触れられていないような、本質の部分をカバーすべきでしょう。そうすることで、近い将来、新しいプログラミング言語が出てきても、プログラミングの歴史と比較して、新しい部分、重要な技術などをはっきりと認識できるようになり、言語を使いこなす能力をもったプログラマを育てることにつながるのではないでしょうか。

(追記)

そもそもプログラミングの本質って?

プログラミングの本質をどこに据えるかで言語の選択は変わりますね。省メモリ・並列化が主眼なら副作用、同期などが重要なのでアセンブリ、C/C++などlow levelに近いもの。オブジェクト指向ならJavaなどデザインパターンの威力が見せられる言語が良いと思う。簡潔さ、手軽さが大切ならPerl, Rubyとか。関数型という意味では、Scheme, Lispも面白いけれど、Ocamlも良さそう。Python, Haskellとかは詳しくないので…。

教育で大切なこと

実際、講義の中や在学中に本質を理解しきる必要はないと思うのです。僕自身、関数型言語とMapReduceの関係なんて、卒業した後に初めて理解したものです。気付く人もいれば、数学と同じでまったく使わない人もいる。ただ後になってもう一度学習しようと思ったときに、入り口の部分を見せてもらっているのとそうでないのとでは、学習効率(学ぶことへの抵抗感)が相当違います。だから、1から10までを教えるのではなくて、1を見せることが「教育」で本当に大切な事だと感じています。

2008年9月9日火曜日

Google Web Toolkitを本格的に使う

昨日、Google Web Toolkit (GWT)に触れたので、備忘録という意味も含めて、もう少し詳細を書いてみます。僕自身、GWTを使って、ゲノムブラウザを作ってみたり、講義のレポート提出用サイトを作成するなど、ここ数年大活躍しているツールで、GWTによるWebインターフェースで、5万行は優に超えるだけのコードを書いています。

Google Web Toolkitは、JavaからJavaScriptに変換するコンパイラと、ブラウザで表示するHTMLを生成するWidgetクラスを含んでいます。Javaの構文でプログラムを記述すれば、Webブラウザで動くJavaScritpコードを作成してくれるというものです。

実際の開発ではHTMLを書くことはなく、FlexTable, Buttonなど、HTMLでよく使うtableやformタグをクラスとして表現してくれているので、再利用可能な形でHTML要素を設計しやすくなっています。GUIインターフェースのプログラミングと似た感覚でウェブアプリケーションの開発ができる、と考えるとよいかもしれません。Perl、PHP、Ruby on RailsなどHTMLのテンプレート中心の開発と趣が異なるので、テンプレートに慣れた人にとっては最初のうちはコードを組みにくいかもしれませんが、HTML生成のまどろっこしい部分を気にせず開発できることに真価があります。

コンパイル後の最終的なコードはJavaScriptになるのですが、GWTではJavaの標準的なライブラリをエミュレーションすることで、JavaのArrayList, HashMapなどよく使うデータ構造を使えるようにしてくれています。GWT1.5からは、JavaのGenericsの構文や、forループの簡略記法を使えるようになったので、ますます開発が簡単になりました。

3種類のJAR   GWTにおける開発では、3種類のJARファイルを使います。
  • gwt-user.jar  GWTでは、client(ブラウザ上で実行されるコード)と、sever(サーバー上で実行されるservletなどのコード)の2種類のフォルダ(Javaのパッケージ)を使って開発します。サーバーとの通信に必要なservlet周りのパッケージ(javax.servlet)がgwt-user.jarに同梱されていて、自分でTomcatをインストールしてこれらのライブラリをclasspathに設定する手間が省けます。gwt-user.jarは開発時のみに使うものです。
  • gwt-servlet.jar  一方、こちらは、TomcatなどのWebサーバーに作成したWebアプリケーションを設置するときに、WEB-INF/libフォルダに含めておくものです。gwt-user.jarから、javax.servletのパッケージを取り除いたものです(javax.servletはTomcatに標準装備されているパッケージです)。deploy時には、gwt-servlet.jarのみを使います。
  • gwt-dev-windows.jar, gwt-dev-mac.jar, gwt-dev-linux.jar  これらのJARファイルには、GWTのコンパイラが含まれており、JavaコードをJavascriptに変換するときに使います。また、GWTのコードをコンパイルせずにJavaコードのまま実行するための、GWT Shellが含まれています。GWT ShellはTomcatサーバーをローカルに立ち上げるGUIプログラムなので、OS毎に必要なJARファイルが異なり、gwtの配布パッケージに含まれている.dll、.jnilib、.soなどが実行するのに必要になります。デバッグ時には、クラスパスの先頭にgwt-dev-*.jarを追加しておきます。(gwt-user.jarなどはJavaScriptコードを含んでいるので、Javaとしては動作しません)
GWTのアプリケーションをデバッグしたり、コンパイルするには、ソースコードのフォルダ(srcとか、src/main/javaなど)と、Javaのソースコードクラスが含まれているフォルダ(binとか、target/classesなど)がクラスパスに含まれている必要があります。これはJavaのソースコードそのものがコンパイルなどに必要なためです。

GWTのためのJAR作成 したがって、GWTのコードをJARのライブラリにして再利用するときも、ソースコード(*.java)もclassファイルと同じ位置に含めて作成する必要があります。普段から、ソースコード同梱のJARを作っておくと、EclipseでJARのソースコードがすぐ参照できるというメリットもあります。

GWTによる開発を即座に始める  こう並べてGWT開発の注意事項を並べて書くと、はまりどころが多くて、設定もとても面倒なのですが、僕はこれらの設定を含めて、GWTによる開発を数秒で始めることができるようにしています。

現在開発中の、UTGB Shellというゲノムブラウザを作るためのツールでは、utgb create, utgb gwtのコマンド2つで、GWT、データベース、サーブレット機能を含めたプロジェクトの雛形を作成します。埋め込み型Tomcatサーバーを立ち上げることで、Tomcatなどのインストールなしに、ローカルマシン上でJavaによるWebアプリケーション開発ができるようにもなっています。現在は、生物系の研究者が、面倒なしにゲノムブラウザを作れるようにする趣旨のツールなのですが、僕自身、ゲノム関係以外の一般のWebアプリケーション開発にも使っています。

UTGB Shellの舞台裏ではMaven(パッケージ管理ツール)が動いています。そのインストール作業を省くために、Maven自身もUTGB Shellに埋め込まれています。また、gwt-dev-*.jarのライブラリも、本家で配布されているものとは違って、dllなどのライブラリも同梱させています。これによって、OSごとに1つのJARファイルをダウンロードするだけで済むのですが、これらのライブラリをOSの種類に応じてダウンロードしたり、展開したり、GWTのコンパイラを起動するなどもすべてMavenのスクリプトとしてまとめているので、ユーザー、開発者が、詳細を気にする必要がありません。本番用サーバー上のTomcatへのdeployもコマンド一つでできるようになっています。

このような複雑なプロジェクト管理ができるようになったのも、Javaの魅力の1つ。C++などバイナリのOS・コンパイラ間の互換性が乏しい言語の場合は、ソースコードの最新版をネットからダウンロードして、dllをコンパイルする必要があります。コンパイルエラーがでる、実行時にリンクエラー、multi-threadライブラリのタイプが一致していなくてメモリリークが起こるなど、など、慣れていない人には解決しようのない、はまりどころもたくさんでてきます。

Javaではこのような面倒が軽減され、Mavenのようなパッケージ管理ツールのおかげで、典型的な作業を繰り返さずにすむようにできるようになったのが嬉しいですね。

2008年9月8日月曜日

Google Web Toolkitでcanvasを使って画像を描く方法

Google Web Toolkit(GWT)は、Java言語からJavaScriptのコードを生成するものです。ブラウザ間のJavaScriptの動作の違いを吸収してくれるなど、ウェブアプリケーション開発の苦労をかなり軽減してくれます。GWTはもう十分実用的なのですが、まだまだ成長途中でgwt本体のtrunkに正式に組み込まれる前の機能などは、Google Web Toolkit Incubatorというプロジェクトで開発されています。

gwt-incubatorの中で目玉なのが、GWTCanvasというライブラリ。これは、次期HTML5には標準搭載されるはずのcanvasタグの機能を使って、ブラウザ自身に画像を描画させるというものです。こちらのデモを見てもらえれば、意外と複雑な図が描けたり、アニメーションが作れるなど、そのすごさがよくわかると思います。Flashプラグインなどを使わない限り、今まで画像をブラウザで見せるにはサーバーから画像データを直接送る以外に方法がありませんでしたが、今後は描画のために必要な座標、色などの情報をサーバーが送るだけで、画像を描くなどサーバーにとって重い処理はブラウザ側に任せてしまえるようになります。

実はこのcanvasという機能、IEはサポートしていません。けれど、IEにはVMLという独自の画像を描くための仕様があります。GWTCanvasは、IEのときはVMLを使って画像を描き、canvas機能が既に使えるFirefox, Google Chrome, Safari, OperaなどのWeb標準を大事にするブラウザでは、canvasを直接使う、というトリックを使って、ほとんどのブラウザで画像を描くことを可能にしています。ただし、IEのVMLを使った描画は動作が重いのでご注意。

厳しく言えば、IEがWeb標準を追おうとしてないから、こんなライブラリが必要になっている節があります。どのOS・ブラウザでも動くことを大事にするWeb Developerにとって、IEは本当に憎らしい存在。Webアプリケーションを作る動機って「どこでも動くアプリケーション」を作ることに尽きますから。IEのためだけに必要なwork aroundのなんと多いことか。

ソースコードからjarファイルを作るにはこちらを参照して、ant distとすればいいですが、僕がJARパッケージにしたものもこちらからダウンロードできます(GWT1.5.2用です)canvasで遺伝子構造を描いてみたりしています。ブラウザで画像を描き始めるとGoogle ChromeのJavaScriptの動作が本当に速いことがよく実感できます。


2008年8月27日水曜日

プログラマとして生きるということ

はてなを眺めるようになってから、「IT土方(どかた)」という言葉を知りました。IT土方とは、

システムエンジニアプログラマーなどにおける過酷な労働条件を自嘲的に表現したもの。「土方」は差別用語及び放送禁止用語として扱われているため、使用の際には留意すること。

という意味だそうです。僕は研究者だけれど、プログラマでもあるので、プログラマが世間でこう呼ばれているのは非常に悲しいことです。プログラマというのは、本当はとても魅力的な仕事です。土方で甘んじているのは、きっと「プログラマ」として生きていないのだとも思います。(例えば、矢野勉さんのエントリにも挙げられているような状況の人達です)


プログラムをデザインする、ということ プログラムの場合、通常の土木工事と比べて顕著に違うのが、一度作ったコードを「一から作り直さないようにデザインできる」ということ。たとえば、コマンドライン引数を処理するプログラムを一度作ると、それをクラスの形に整理して(OptionParserクラスなどと名づけて)ライブラ リにしておきます。ライブラリを作る作業は、Windowsならdllを作る、JavaならJARファイルにまとめることに相当します。

書いたプログラムが自動的に再利用可能になるわけではなく、そうなるように「デザインできる」ということで、この間は結構違いがあります。二度目からは、ライブラリにリンクして使うので必要な仕事の量は格段に減りますし、使い道にあわせてライブラリの修正をしなくてはいけないことも多いですが、機能を改善し、使い勝手を向上できるというメリットがあります。修正に費やす時間は、今直すか、後で必要になってから取り掛かるか、という違い。Ruby on Railsのフレームワークも、Webアプリケーションで頻繁に書くようなコードをうまくライブラリ、モジュールにしていると思います。

プログラミングが肉体労働になりやすいのは、おそらく、このライブラリにまとめるという経験が不足している場合。Visual Studioでdllを作っておくだけで、ビルド時間や開発時間は短縮できるし、Javaならmavenを使えば、細かな修正を施したjarを頻繁にreleaseする作業が苦ではなくなります。PerlだったらCPAN用のモジュールを作るとか、RubyならRuby gems用モジュールを作るというところでしょうか。

他に考えられるのは、プログラマ自身が今書いているコードが二度目のコード(重複がある)と思っていない可能性。オブジェクト指向の考え方や、デザインパターン(クラスの組み方の過去の知見)を知らなくて、コードを再利用可能な形でまとめることに考えが及ばない、ということがありえます。Subversionやgitなどのソースコード管理ツールの存在を知らないと、再利用といっても、常にコピー&ペーストするという最悪な方法を採っている人も多いかと思います。これでは単純労働となっても仕方がない。


ハッカーと画家 ここで紹介したいのが、「ハッカーと画家」という話です。ソースコードを書くのは、絵画を描くのと非常に似ています。僕自身もそうですが、新しいものを創ることだけでなく、良いコード、簡潔でわかりやすいコードをデザインすることに魅力を感じます。本文中には以下のように書かれています:
ハッカーと画家に共通することは、どちらもものを創る人間だということだ。作曲家や建築家や作家と同じように、ハッカーと画家がやろうとしているのは、良いものを創るということだ。良いものを創ろうとする過程で新しいテクニックを発見することがあり、それはそれで良いことだが、いわゆる研究活動とはちょっと違う。
コードをデザインする能力が、画家の画力と同じように、良いプログラマたる条件でしょう。良いデザインを考えることはかなり高度な知的活動になります。ただ、ビジネスモデルの中で、プログラマが良いデザインをすることと売れることが直接結びつくケースは少なく、プログラマが労働過多になるのは、以下のような事情によるものかと推察します:
Yahooに入ってみたら、彼らにとってハックするということはソフトウェアを実装するということで、デザインするということではないということがわかった。プログラマは、プロダクトマネージャのビジョンとかいったものをコードへと翻訳する技師とみなされていたのだ。

究極のプログラミング - コンパイラを作る- コードをデザインする時間・許可が与えられない場合、たとえば、コンパイラを作る、なんてことは到底認められないでしょう。けれど、コードを書くというのは、人が考えていることを機械が実行できるようにすること。この意味から考えると、究極のプログラミングはコンパイラを作ることにあります(お絵かきソフトなど人の入力を画像データにするのも、ある意味コンパイラですね)。簡単な記述で、素敵な仕事をしてくれるのがコンパイラです。コンパイラを作る時間、そのために必要な技術を習得するコストが大きいので、通常は、他人が作った言語やフレームワークを使ってコードを書いているだけです。

Webアプリケーションのように、どのOS、どのブラウザでも動くコードを書くのは大変です(主にIEが他とケンカしてしまう悪い子なので…)。だから、その作業を軽減するために、Google Web ToolkitではJava言語からJavascriptコードを生成するコンパイラを作るという、とても良い仕事をしてくれました。けれど、コンパイラを作るのだって、そんなに大変なわけじゃないですよ?以下は、Joel on Softwareより引用
Most people don't realize that writing a compiler like this is only about 2 months work for one talented person who read the Dragon book. Since the compiler only has one body of code to compile, it is much easier to write. It doesn't have to be a general-purpose compiler. It doesn't have a math library, for example. (多くの人が、コンパイラを書くのはドラゴンブックを読んだ優秀な人が2ヶ月くらいでやる仕事だってことをわかってない。コンパイラには、コンパイルするコードしかないので書くのは簡単だし、一般的なコンパイラなんて書く必要はないんだ。数学ライブラリなんてものもいらない。)
ドラゴンブックはコンパイラの教科書としてとても有名ですが、隅から隅まで読む必要はなくて、字句解析、構文解析の概要を知って、Lex/Yacc/Bison, ANTLR、JavaCCなどどれか1つのツールの使い方を学べば、コンパイラはすぐにでも作り始めることができます。

開発するプログラムが同程度のものなら、フレームワークなり、コンパイラがあるだけで相当仕事が短縮されるはずです。ここで負荷が減らないなら、コンパイラで仕事が簡単になったから、あれこれ追加機能を実装しようと欲張るなど、開発すべき仕事が単純に増えているのでしょう。逆に、コンパイルコマンド1つで製品ができても、それを1分、1秒の時間単価や人月で見積もられてはいけないのだと思います。

プログラミング+αの時代  インターフェースのデザインなどは、上記の「ハッカーと画家」の例のような比較とは違って、本当に「画家」とか「デザイナー」の能力を要する分野に踏み込んでいるので、プログラマの仕事としては過負荷になっているのだと思います。

僕は、デザインすることは昔から好きだし、コミック、油絵とかも良く描いていたので、ウェブデザインをするのは時間はかかって大変なことだけれど、楽しい部分として受け入れることができます。まだまだ未熟だけれど、デザイン+コーディングの両方できるというのは僕自身の専売特許だと思います。データベースが専門でシステムを作れるというのも、プログラマとして持っている僕の付加価値です。プログラマは、コードをデザインするだけでなく、+α(アルファ)の部分で、自身のブランドを作れる存在だと僕は思っています。売れないブランドだって当然でてくるわけで、オープンソースのApacheブランドだって、よくよく見てみるといいコードばかりではありません。

プログラムをデザインする能力を習得した上で表現すべき「+α」の部分が、まだまだ未開拓のように感じています。コンピュータ専攻の人だけでなく、もっといろいろな人にプログラムを学んで欲しいと思うのです。自分の魅力である「+α」をアピールするためにプログラムを作ってみる、知識が足りなければプログラミングを学ぶ、この繰り返しをするのがレベルアップへの近道でしょう。

プログラムやコンパイラを作るというのは大変なことですが、「魅力的なものを創る」ためには欠かせないことです。コンピュータ、インターネット内だけの話ではなくて、コンピューターでデザインして、現実の作品を作るなんてこともできます。せっかくプログラミングという応用分野が広く、すばらしい技術を学んだのに、人に言われたものだけ黙々と作るというのでは、面白くないのは当然。

プログラマが「+α」を作るという意味で、作ったものが売れないことがあるのも、飛ぶように売れる(有名になる)ことがあるのも、作家や画家と似たものを感じます。それはプログラマという職そのものの性質ではなくて、ビジネスとしてブランドの宣伝であったり、市場があるかどうかなど問題だと感じます。プログラマも、作りたいものだけを作る、と小説家や芸術家くらいわがままであってもいいと思います(これは偏見ですが)。わがままを通して「食える」ようになるというのは、プログラマに限らずまたどこか別の次元の話です。

プログラマとして生きるということ プログラマとして生きていくというのは、ビジネスを含めて、自身のブランドとして独立する覚悟が必要ですし、そうしない道を選ぶなら、他で生活の糧を得る必要があります。これは、プログラマとして能力が劣ることを意味するわけでも、恥ずかしいことでもありません。Googleだって広告収入が安定しているからこそ、Google Web Toolkitなどの開発に注力できているのです。

開発をしていて労働過多で見合った収入が得られていないと感じたときに、「プログラマだから」と結びつけるのは、誤った思い込みであるように思います。「プログラマ」とはそんなひとくくりにできるような言葉ではありません。「プログラマ」は好きなものを思いのままに作れる夢のような職業である一方、製造・出版業のような既存のレールがない分、ものをつくる職業として確立できていない難しさもあるでしょう。

けれど、そんな時代の荒波を生きていくのが「プログラマ」です。数年で技術が変わり、新しいツールも次々に出てくる。そんな中、目指すものを創るために、自ら学ぶことを止めず、成長し続ける人が、真の「プログラマ」と呼ばれるべきです。3年前にも同様のことを書きましたが、プログラマやハッカーという言葉に対するこの思いは今でも変わっていません。

2008年8月26日火曜日

JARファイルの中にJARを埋め込む

以前、「Leo's Chronicle: Fat Jar: Jarファイルの中にJarを埋め込む」で、JavaでFatJar plug-inを使って、Jarファイルの中にJarを埋め込む使う方法を紹介したのですが、最近は事情が変わってきています。

たとえば、Eclipse3.4からは、Runnable Jarの作成がサポートされ、依存関係にあるすべてのJARファイルの中身を展開して、1つのJARにまとめてくれる機能が標準装備だったり、Mavenユーザーなら、assembly pluginを使って、jar-with-dependenciesを指定する方法もあります。

ぱっと試したいなら、Runnable Jarを作成するのが速くて楽。このようなJARを頻繁に作成するなら、Mavenのassemblyで書いてしまうのが良いです。

関連記事:JARファイルの作成方法

2008年2月12日火曜日

grepでマッチした行だけ取り除くスクリプト

SubversionのDateタグって、意図しない文字コードの日付に置換されてしまい、予測不能な問題を生じてしまうことが多かった取り除くことにしました。

そこで、一行プログラミング。
for f in $(grep -n  "\$Date" src/**/*.java | cut -d ':' -f 1);
  do echo $f; grep -v "\$Date" $f > $f.tmp; mv $f.tmp $f; done;

もっと賢い方法や、こういう時に便利なコマンドがあったら教えてくださいな。

2007年9月20日木曜日

Emacsキーバインドの天国と地獄

Emacsキーバインドを覚えて以来、あらゆるエディタでCtrl+N, P, A, Eなどのキーでカーソル移動をしています。Ctrl+X, Ctrl+Sで、ファイル保存とか、Ctrl+\で、日本語入力切り替え。Ctrl+I, O, J, K, Lのあたりも漢字変換のときに便利です。

キーボードによっては、Aの横のキーがCaps Lockなのですが、Emacsキーバインドのために、AltIMEなどのソフトで、Ctrlキーに変更しています。

この操作を覚えると、通常のプログラミング速度が倍以上になりますし(ホームポジションがから手が離れないので、テキストの編集が速くなります)、シェルなどでも同様のキー操作が使えるので、作業効率も上がります。こう書くと、いいこと尽くめなのですが、悪い点が一つ。

Ctrlキーを押す左手小指にダメージがあるのです。Ctrlキー押すと痛くなってしまいました。大した痛みではないのですが、普段よく使うキーなだけに、キーを押すときに少しでも違和感があると、他の作業にすべて影響します。

普通にプログラミングをしている限りは、痛くなるようなことはほとんどないのですが。。。。先週から今週にかけては、朝から晩まで毎日のようにコードを書いていたために、小指に相当な負担がかかっていたようです。

小指の代わりにCtrlキーを押せるものはないかと、手のひらを使ってみたりしましたが、どうにも打ちにくい。

ネットを検索してみると同じような悩みをもつ人はわりといるんですよね。そこで見かけた面白いアイデアはフットスイッチを使う!というもの。確かに、パソコンに向かっているとき、足は空いています。ピアノにもペダルはありますし、エレクトーンのように足が絶え間なく動く操作には慣れっこなので、Ctrlを足で押して、Emacsキーバインドを使うくらいどうってことはなさそうです。

問題なのは、そんなフットスイッチは売っていない、ということ。レーシングゲーム用とおぼしきデバイスはあるのですが、価格が高い上、踏み込むタイプらしく頻繁に押したり離したりという操作には向いてなさそう。


あれこれ考えてみたものの、そういうときは、プログラミング以外のことをすればいい、というのが結論。経験上、小指の痛みも時間が経てば治りますし。

でも、フットスイッチを巧みに駆使しながらキーボード操作ができるとすると、すごいことができそうな気がするんだけど。。。フットスイッチを押しながらだと、アプリケーションをすべてキーボードから操作できてしまうとか。楽器だって楽しく弾けるようになるまでは時間がかかるんだから、キー操作も、それくらいの壁があってもいいんだけどなぁ。

2007年2月20日火曜日

Fat Jar: Jarファイルの中にJarを埋め込む

Fat Jar Eclipse Plug-In

Javaで開発していて、他のライブラリのアーカイブ(Jar)を使っている場合、自分のプログラムもJarとして配布するときに、manifestファイルに適切に外部のJarへのreferenceを書いておかないと正しく動作しません。

通常は、classpathの設定を含めた実行スクリプトを一緒に配布することが多いみたいです。でも、スクリプトを用意するのは面倒ですよね。

そんな煩わしさを取り除くのが、Fat Jar。Jarの中にJarファイルを埋め込んでプロジェクト全体を1つのファイルとすることができます。

Fat Jarは、通常は、外部で参照しているJarを展開してJarの中に埋め込むのですが、One-Jarオプションを選ぶと、jarファイルを展開せずにそのままjarの中に埋め込みます。こちらの方が、構成内容がよくわかります。

Fat Jarを使うと、今まで、
java -cp lib/somelibrary.jar -jar myprogram.jar
などとしていたところを、

java -jar myprogram.jar

と実行するだけでよくなります。意外と知らない人がいると思うので、紹介しました。おすすめです。

最近はJARの作り方も事情が変わっています。2008年8月 http://leoclock.blogspot.com/2008/08/jarjar.html

2007年2月17日土曜日

プログラム開発でよくある失敗

Visual Studio 2003 (vc7.1)から、Visual Studio 2005 (vc8)に乗り換えました。

ただ、この2つで使われるマルチスレッドのライブラリのversionが違っていて、vc7.1でビルドしたマルチスレッドを使うライブラリ(dll)を実行時に使ってしまうと、原因とは脈絡もないところでメモリ関連のエラーが出てデバッグに苦しみます。

そういうときは、
> dumpbin /dependents (dllのファイル)
で調べます。
Dump of file xerces-c_2_7D.dll

File Type: DLL

Image has the following dependencies:

WS2_32.dll
ADVAPI32.dll
KERNEL32.dll
MSVCR80D.dll

MSVCR80D.dll が、MSVCR71D.dllなどになっていたら危険信号。結局、普段良く使っている、BerkeleyDBとか、Xerces-C++とかを再コンパイル。

その点BoostライブラリのWindows版はよくできていて、対応するコンパイラでビルドされたライブラリがない場合はちゃんとこのライブラリがない、と実行時に指摘してくれます。dllを動的に読み込んでるからこそできる技。

でも、こんなの慣れた開発者じゃないとわからないよなぁ。。。。C++の教科書読んだって書いてないもの。xercesだって、BerkeleyDBだって、vc7.1でbuildされたdllを注意書きもなくしれっと配布しているし。。。やれやれ。

License

Creative Commons LicenseLeo's Chronicle by Taro L. Saito is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 2.1 Japan License.