<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>ウノウラボ Unoh Labs</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/" />
    <link rel="self" type="application/atom+xml" href="http://labs.unoh.net/atom.xml" />
    <id>tag:labs.unoh.net,2006://2</id>
    <link rel="service.post" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2" title="ウノウラボ Unoh Labs" />
    <updated>2008-05-13T09:06:18Z</updated>
    <subtitle>ウノウ株式会社のデモ版サービスやTIPSなどの情報</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type  3.36</generator>
 
<entry>
    <title>ソーシャルスクラップブック「clipp」とImageFlow</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2008/05/clippimageflow.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1106" title="ソーシャルスクラップブック「clipp」とImageFlow" />
    <id>tag:labs.unoh.net,2008://2.1106</id>
    
    <published>2008-05-13T09:04:17Z</published>
    <updated>2008-05-13T09:06:18Z</updated>
    
    <summary><![CDATA[五十川です。 ウノウではただいま「clipp（クリップ）」と名付けた新しいサービスを試験的に公開しています。これはソーシャルブックマーク＋ミニブログといった体のもので、ページのURLやタイトルに加えて、文章の抜粋や画像のサムネイルなどに、自分のコメントを添えて登録できるというもので、気になったページを&ldquo;切り貼りして&rdquo;保存し、他者と共有する、&ldquo;ソーシャルスクラップブック&rdquo;といった趣のサービスです。 ※ clippは試験公開ということで現在は招待制とさせていただいておりますが、興味をお持ちいただいたかたは、clippのユーザ登録ページからメアドを登録しておいていただくと、招待状を送付させていただけると思いますので、是非どうぞ。 さて、clippでは画像を扱えるという特徴を活かして、画像をiTunes/iPodのCoverFlow風に表示する機能を...]]></summary>
    <author>
        <name>unoh</name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[<p>五十川です。</p>

<p>ウノウではただいま「<a href="http://clipp.in/">clipp</a>（クリップ）」と名付けた新しいサービスを試験的に公開しています。これはソーシャルブックマーク＋ミニブログといった体のもので、ページのURLやタイトルに加えて、文章の抜粋や画像のサムネイルなどに、自分のコメントを添えて登録できるというもので、気になったページを&ldquo;切り貼りして&rdquo;保存し、他者と共有する、&ldquo;ソーシャルスクラップブック&rdquo;といった趣のサービスです。</p>

<p style="padding:.5em;border-style:solid">※ clippは試験公開ということで現在は招待制とさせていただいておりますが、興味をお持ちいただいたかたは、<a href="http://clipp.in/account/register">clippのユーザ登録ページ</a>からメアドを登録しておいていただくと、招待状を送付させていただけると思いますので、是非どうぞ。</p>

<p>さて、clippでは画像を扱えるという特徴を活かして、画像をiTunes/iPodのCoverFlow風に表示する機能を用意してみました。</p>

<p>clippの各ユーザ毎のページには、サイドバーなどに「ImageFlow」というリンクがあるのですが、これをクリックすると、下図のように、そのユーザが登録している最新のサムネイル画像が一覧表示され、マウスのホイールやキーボードの矢印キーなどを使って、画像を次々「めくって」表示することができます。</p>

<div><a href="http://photozou.jp/photo/show/784/9261591"><img src="http://art2.photozou.jp/pub/784/784/photo/9261591.png" alt="ImageFlow JavaScript for clipp" width="450" height="217" style="border:0" /></a></div>
<div><a href="http://photozou.jp/photo/show/784/9261591">ImageFlow JavaScript for clipp</a> posted by <a href="http://photozou.jp/mypage/top/784">(C)フォト蔵</a></div>

<p>この「ImageFlow」はオリジナルのものではなく、既によく知られている<a href="http://www.finnrudolph.de/">Finn Rudolph</a>さん作の<a href="http://imageflow.finnrudolph.de/">ImageFlow JavaScript</a>を若干改変し、Ajaxによる処理などclippで必要な機能を追加したものです。</p>

<p>Finn RudolphさんのImageFlowの原型は、Michael L. Perryさんが、スクラップブックのコンサルタントである夫人の作品を紹介するために作られた<a href="http://myscraproom.net/">Cover flow in Javascript</a>だそうです。Finn Rudolphさんのものはこれに、Adomas Paltanaviciusさんの<a href="http://adomas.org/javascript-mouse-wheel/">Mouse wheel programming in JavaScript</a>を利用したマウスホイールの制御をはじめとしたさまざまな改良を施されたものです。</p>

<p>ImageFlowはプレインのJavaScriptで他のライブラリなどに依存しないので、改変が比較的容易で、Finn Rudolphさん自身による<a href="http://194.95.111.244/~countzero/scripts/_myImageFlowLightbox2/">Hacked version for Lightbox2</a>や<a href="http://194.95.111.244/~countzero/scripts/_myImageFlowHighSlide/">Hacked version for Highslide JS</a>などの画像エフェクトライブラリとの組み合わせや、Tobias Wetzelさんによるmootoolsフレームワーク用の<a href="http://www.outcut.de/MooFlow/">MooFlow</a>など、さまざまなバリエーションが作られています。</p>

<p>clippのウェブサイトで配信されるJavaScriptはYUI Compressorでminifyしたものなので、以下にminify前のソースを掲載しておきます。</p>

<ul>
<li><a href="http://labs.unoh.net/download/imageflow_clipp.tar.gz">ImageFlow JavaScript for clipp</a></li>
</ul>

<p>※ これはあくまでclipp用で、汎用のものではないので、そのまま利用いただけるわけではありませんが、なんらかの参考になるようでしたら幸いです。</p>

<h3>おまけ: リフレクション画像（鏡像）について</h3>

<p>iTunes/iPodのCoverFlow風表示にはリフレクション画像が必須ですが、Finn RudolphさんのImageFlowではこれを、GD2を使った、Richard Daveyさんの<a href="http://reflection.corephp.co.uk/">Easy PHP Reflections</a>で動的に作成しており、これは配布パッケージにも同梱されてます。一方Imagick PHPを使ってリフレクション画像を作成する手順は、Imagick PHPの開発者Mikko Koppanenさんのブログの記事、<a href="http://valokuva.org/?p=82">Creating a reflection</a>に掲載されています。またMooFlowでは、リフレクション画像をCanvas要素などを使ってクライアント側で描画するように改良されています。</p>]]>
        
    </content>
</entry>
<entry>
    <title>Mercurialでバージョン管理</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2008/05/mercurial.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1105" title="Mercurialでバージョン管理" />
    <id>tag:labs.unoh.net,2008://2.1105</id>
    
    <published>2008-05-12T07:50:51Z</published>
    <updated>2008-05-12T08:53:43Z</updated>
    
    <summary>stoplightで最大化したターミナル上でzshとscreenとEmacsを立ち上げ、 明朝体フォントでプログラミングするbokkoです。 今回はバージョン管理システムの1つであるMercurialについて紹介します。 ウノウではSubversionとTracを組み合わせて開発を行っていますが、 僕個人では今年の春ぐらいからEmacsやzsh、screenなどの各種設定ファイルをMercurialでバージョン管理しています。 Mercurialとは？ Mercurialは分散型のバージョン管理システムです。 これに対して、CVSやSubversion(以下SVN)は集中型のバージョン管理システムにあたります。 分散型と聞くと難しそうなイメージがわくかもしれませんが、 CVSやSVNに比べてると、より手軽にバージョン管理を行うことができるというのが、 Mercurialに対する僕の印象です...</summary>
    <author>
        <name>unoh</name>
        
    </author>
            <category term="Tips" />
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[<p>stoplightで最大化したターミナル上でzshとscreenとEmacsを立ち上げ、
明朝体フォントでプログラミングするbokkoです。
</p>

<p>今回はバージョン管理システムの1つであるMercurialについて紹介します。</p>

<p>
ウノウではSubversionとTracを組み合わせて開発を行っていますが、
僕個人では今年の春ぐらいからEmacsやzsh、screenなどの各種設定ファイルをMercurialでバージョン管理しています。
</p>

<h2><strong>Mercurialとは？</strong></h2>

<p>
Mercurialは分散型のバージョン管理システムです。
これに対して、CVSやSubversion(以下SVN)は集中型のバージョン管理システムにあたります。
分散型と聞くと難しそうなイメージがわくかもしれませんが、
CVSやSVNに比べてると、より手軽にバージョン管理を行うことができるというのが、
Mercurialに対する僕の印象です。というのもCVSやSVNでは、まず単一のリポジトリを作成した後、
バージョン管理したいファイルをリポジトリにimportして、コピーをチェックアウトし、
コピーを編集してからその差分をリポジトリにコミットします。
これに対して、Mercurialではバージョン管理の対象そのものがリポジトリになります。
このため、単に1つのマシン上で編集の履歴を保持したりするだけの場合、
集中型よりも手軽に扱うことができます。もちろん、複数のマシンでファイルの同期を取るといったことも可能です。
</p>
]]>
        <![CDATA[<h2><strong>とりあえず使ってみる</strong></h2>

<p>
概要だけではあまりピンとこないと思いますので、実際に使ってみましょう。
使用しているMercurialのバージョンは1.0です。
例えば、以下のディレクトリでバージョン管理を行いたいとします。
</p>

<pre class="code">$ pwd
/Users/username/mercurialSample
$ ls
test.txt
$ cat test.txt
test
$
</pre>

<h2><strong>リポジトリの初期化</strong></h2>

<p>
リポジトリの初期化は下記のコマンドを実行するだけです。
</p>

<pre class="code">$ hg init
$</pre>

<p>
何も表示されませんが成功すれば.hgというディレクトリができているはずです。
バージョン管理をやめたくなったらこのディレクトリを削除するだけでOKです。
</p>

<pre class="code">$ ls -a
.               ..              .hg             test.txt
</pre>

<p>
また、initコマンドで初期化しただけでは、test.txtはリポジトリには追加されていません。
</p>

<pre class="code">$ hg status
? test.txt
$
</pre>

<p>
addとcommitでリポジトリにtest.txtを追加します。
</p>

<pre class="code">$ hg add test.txt
$ hg status
A test.txt
$ hg commit -m &quot;test&quot; test.txt
$ hg status
$
</pre>

<h2><strong>基本的なコマンド</strong></h2>

<p>
ファイルの追加や削除、差分の更新やコミットはCVSやSubversionとほとんど同じなので、
CVSやSVNを使ったことのある人なら特に困ることなく、使えるでしょう。
</p>

<pre class="code">$ hg add test.txt
$ hg remove test.txt
$ hg update test.txt
$ hg commit test.txt
$ hg diff test.txt
</pre>

<h2><strong>リポジトリの複製</strong></h2>

<p>
上記のように特に分散型というのを意識せずに単純に個人でローカルだけで
手軽に差分を保持するということができるのも僕がMercurialを気に入っている理由の一つですが、
もちろんCVSやSVNのようにネットワークを介した複数のマシンの間で同期を取ることもできます。
ここでmacというホストとubuntuというホストの間でさっきのリポジトリを共有することを考えてみましょう。
何故macとubuntuかと言うと、実際に僕がMacとParallesDesktopにインストールしたUbuntuとの間で、
Mercurialを使って設定ファイル等の同期を取っているからです。
まず、mac上にある先程のリポジトリをubuntu側から複製してみましょう。
リポジトリを複製するにはcloneコマンドを使います。
</p>

<pre class="code">
$ pwd
/home/username
$ hg clone ssh://username@mac//Users/username/mercurialSample mercurialSample
</pre>

<p>
macがホスト名、/を一つ挟んだ後の文字列がリポジトリのルートディレクトリへのパス、
その次が複製側で作成するリポジトリのルートディレクトリの名前です。
問題がなければ、これで上記コマンドを実行したubuntu側のディレクトリに
リポジトリができます。また、このリポジトリの.hgにあるhgrcというファイルに
どこからリポジトリを複製したのかが記録されています。
</p>

<pre class="code">[paths]
default = ssh://username@mac//Users/username/mercurialSample</pre>

<p>
pathsコマンドで確認することも可能です。
</p>

<pre class="code">$ hg paths
default = ssh://username@mac//Users/username/mercurialSample

</pre>

<h2><strong>ローカルリポジトリの内容をリモートリポジトリに反映</strong></h2>

<p>
CVSやSVNではチェックアウトしたコピーから単一のリポジトリに対してコミットを行いますが、
Mercurialでは通常、コミットはローカルのリポジトリに対してのみ行います。
単にコミットしただけでは別のマシンのリポジトリに変更内容は反映されません。
前者のリポジトリをローカルリポジトリ、後者のリポジトリをリモートリポジトリと言います。
</p>

<p>
例えば、さっき複製したubuntu側のリポジトリの内容を変更してみます。
</p>

<pre class="code">$ cat test.txt
test
ubuntu
$ hg status test.txt
M test.txt
$ hg commit -m &quot;add ubuntu&quot; test.txt
$</pre>

<p>
これでubuntu側のリポジトリの内容が変更されました。
これをmac側のリポジトリにubuntu側から反映させるにはpushコマンドを使用します。
</p>

<pre class="code">$ hg push ssh://username@mac//Users/username/mercurialSample
</pre>

<p>
pushコマンドが成功したら、mac側のリポジトリでupdateコマンドを使用します。
</p>

<pre class="code">$ hg update
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cat test.txt
test
ubuntu
$
</pre>

<h2><strong>リモートリポジトリの内容をローカルリポジトリに反映</strong></h2>

<p>
逆に別のマシンで変更されたリポジトリの内容を自分のリポジトリに反映させるには
pullコマンドを使用します。ubuntu側で変更された内容をmac側から取り込んで見ましょう。
</p>

<pre class="code">$ hostname
ubunutu
$ cat test.txt
test
ubuntu
more ubuntu
$ hg status
M test.txt
$ hg commit -m &quot;add more ubuntu&quot; test.txt
$
</pre>

<pre class="code">$ hostname
mac
$ pwd
/Users/username/mercurialSample
$ hg pull ssh://username@ubuntu//home/username/mercrurialSample
</pre>

<p>
pullコマンドが成功したら、updateコマンドを実行します。
</p>

<pre class="code">$ hg update
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cat test.txt
test
ubuntu
more ubuntu
$
</pre>

<h2><strong>ファイル無視の設定</strong></h2>

<p>
ソースコードなどのバージョン管理をしていると、
一部例外としてバージョン管理の対象に含めたくないファイルが出てきます。
例えば、makeコマンドで生成される実行ファイル、etagsで生成されるTAGS、またEmacsが生成する
一時ファイル(末尾に~が付いたファイルや各種拡張が生成する一時ファイル)などがあります。
Mercurialでは.hgignoreというファイルをリポジトリのルートディレクトリに作成して、
ファイル無視に関する設定を記述することができます。
僕の環境では以下のような設定をしています。
</p>

<h3>.hgignore</h3>

<pre class="code">syntax: glob
*~
.semantic.cache
.DS_Store
TAGS
</pre>

<p>
また、僕は使っていませんが、正規表現による指定もできます。
</p>

<pre class="code">syntax: regexp
^t
</pre>

<h2><strong>.hgignoreの設定を共有する</strong></h2>

<p>
ただ、上記のやり方だと新しいリポジトリを作成する度に設定ファイルを用意する必要があります。
すべてのリポジトリで.hginoreの設定を共有するには、
ホームディレクトリに以下の内容の.hgrcとさっきの.hgignoreを作成します。
</p>

<h3>.hgrc</h3>

<pre class="code">[ui]
ignore=~/.hgignore
</pre>

<p>
.hgrcにはほかにもいろいろな設定を記述することができるので、
興味のある方は<a href="http://www.selenic.com/mercurial/wiki/index.cgi/Tutorial">本家のチュートリアル</a>を読んでみるとよいでしょう。
<a href="http://www.selenic.com/mercurial/wiki/index.cgi/JapaneseTutorial">日本語版</a>もあります。
</p>


]]>
    </content>
</entry>
<entry>
    <title>コマンドラインから使うBitTorrentクライアント</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2008/05/bittorrent.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1101" title="コマンドラインから使うBitTorrentクライアント" />
    <id>tag:labs.unoh.net,2008://2.1101</id>
    
    <published>2008-05-01T04:05:29Z</published>
    <updated>2008-05-01T06:17:53Z</updated>
    
    <summary>yukiです。 唐突ですが、BitTorrentクライアントは何をお使いでしょうか？これまで私はずっとBitComet を使ってきましたが、私の非力な自宅マシンだとどうしても負荷が高く、その間は何も出来ないような状態に陥っていました。GUIから使おうとすると、見やすさや使いやすさはさすがに良いのですが、あまりの負荷とその間何も出来ない状況はあまりよろしくないと考え、今回はUNIX系でCLIから操作できるクライアントはないだろうか、と探していて見つかったEnhanced CTorrentをご紹介することにします。 Enhanced CTorrentは、C++で書かれたCtorrentをベースにしたBitTorrentクライアントです。Ctorrentからバグフィックスや改良・軽量化を重ねており、現在のバージョンは3.3.1になっています。 Enhanced Ctorrentは現在はSorce...</summary>
    <author>
        <name>unoh</name>
        
    </author>
            <category term="ネタ" />
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[<p>yukiです。</p>

<p>唐突ですが、BitTorrentクライアントは何をお使いでしょうか？これまで私はずっと<a title="BitComet" href="http://jp.bitcomet.com/" >BitComet</a> を使ってきましたが、私の非力な自宅マシンだとどうしても負荷が高く、その間は何も出来ないような状態に陥っていました。GUIから使おうとすると、見やすさや使いやすさはさすがに良いのですが、あまりの負荷とその間何も出来ない状況はあまりよろしくないと考え、今回はUNIX系でCLIから操作できるクライアントはないだろうか、と探していて見つかった<a title="Enhanced CTorrent" href="http://www.rahul.net/dholmes/ctorrent/">Enhanced CTorrent</a>をご紹介することにします。</p>

<p><a title="Enhanced CTorrent" href="http://www.rahul.net/dholmes/ctorrent/">Enhanced CTorrent</a>は、C++で書かれた<a title="Ctorrent" href="http://ctorrent.sourceforge.net/">Ctorrent</a>をベースにしたBitTorrentクライアントです。Ctorrentからバグフィックスや改良・軽量化を重ねており、現在のバージョンは3.3.1になっています。</p>

<p>Enhanced Ctorrentは現在は<a title="Sorceforge" href="http://sourceforge.net/projects/dtorrent/">Sorceforge</a>でバグレポートやダウンロードができますので、早速使ってみました。</p>

<h3>インストール</h3>

<p>インストールは非常に簡単で、普通にwgetで落としてきて展開し、configureしてmake installします。</p>

<pre class="code"><code>% wget http://jaist.dl.sourceforge.net/sourceforge/dtorrent/ctorrent-dnh3.3.1.tar.gz
% tar zxvf ctorrent-dnh3.3.1.tar.gz
% cd ctorrent-dnh3.3.1
% ./configure
% make
% sudo make install
</code></pre>

<h3>torrentファイルからダウンロードする</h3>

<p>早速torrentファイルをダウンロードして、ダウンロードしてみましょう。
やり方は非常に簡単で、これだけです。</p>

<pre class="code"><code>ctorrent [torrent.file]</code></pre>

<p>これだけで同じディレクトリ内にダウンロードが開始されます。<br>
注意点としては、デフォルトだと2706-2106番ポートを使うようになっていますが、オプションでポートを指定することが出来ます。とても簡単なうえ、デーモンとして起動することも出来ますのでバックグラウンドで動作させたい場合にも非常に便利です。</p>
]]>
        
    </content>
</entry>
<entry>
    <title>Javaコードのバグを発見するFindBugs</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2008/04/javafindbugs.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1100" title="Javaコードのバグを発見するFindBugs" />
    <id>tag:labs.unoh.net,2008://2.1100</id>
    
    <published>2008-04-30T08:26:11Z</published>
    <updated>2008-04-30T08:31:59Z</updated>
    
    <summary><![CDATA[こんにちは。中村です。 Javaコードをコンパイルしたクラスファイルからバグを見つけ出すFindBugsというツールを使ってみました。 FindBugsは単体で動作しますが、IDEのプラグインとしても提供されています。今回はEclipseのプラグインを試してみました。 プラグインの導入 SourceForgeのダウンロードページからedu.umd.cs.findbugs.plugin.eclipse_1.3.3.20080401.zipを取得して 解凍、Eclipseディレクトリのpluginsに置くだけといういつも通りな感じです。 使い方 プロジェクトのプロパティから通知する問題を選択したりと色々設定が出来ますが、単純に使うにはJavaプロジェクトのところで右クリック -&gt; Find Bugs -&gt; Find Bugsをクリックすると プロジェクトを調べて問題箇所にマーカーを...]]></summary>
    <author>
        <name>unoh</name>
        
    </author>
            <category term="Tips" />
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[<p>こんにちは。中村です。</p>
<p>Javaコードをコンパイルしたクラスファイルからバグを見つけ出す<a href="http://findbugs.sourceforge.net/">FindBugs</a>というツールを使ってみました。</p>
<p>FindBugsは単体で動作しますが、IDEのプラグインとしても提供されています。今回はEclipseのプラグインを試してみました。</p>
<h3>プラグインの導入</h3>
<p><a href="http://sourceforge.net/project/showfiles.php?group_id=96405&package_id=118233">SourceForgeのダウンロードページ</a>からedu.umd.cs.findbugs.plugin.eclipse_1.3.3.20080401.zipを取得して
解凍、Eclipseディレクトリのpluginsに置くだけといういつも通りな感じです。</p>
<h3>使い方</h3>
<p>プロジェクトのプロパティから通知する問題を選択したりと色々設定が出来ますが、単純に使うにはJavaプロジェクトのところで右クリック -&gt; Find Bugs -&gt; Find Bugsをクリックすると
プロジェクトを調べて問題箇所にマーカーを付けてくれます。</p>

<h3>使ってみる</h3>
<p>早速無茶なコードを書いてみました。</p>
<a href="http://photozou.jp/photo/show/784/8859976"><img src="http://art2.photozou.jp/pub/784/784/photo/8859976_org.v1209543730.png" alt="FindBugs" width="390" height="494" style="border:0" /></a><br /><a href="http://photozou.jp/photo/show/784/8859976">FindBugs</a> posted by <a href="http://photozou.jp/mypage/top/784">(C)フォト蔵</a>
<p>すると、このようにバッチリと問題点が指摘されました。実行してNullPointerExceptionの発生箇所の行数を見るよりはこちらの方が一目瞭然で判りやすいと思います。</p>
<p>次に書いてはいけないコードの類をやってみました。</p>
<pre class="code"><code>package net.unoh.findbugstest;

public class FindBugsTest {

    public static void main(String[] args) {
        Thread thread = new Thread();
        thread.run();
    }

}</code></pre>
<p>すると次のように問題点が指摘されました。</p>
<pre class="code"><code>[Ru] スレッドの中で run を実行しています。(本当は startを代わりに呼び出すべきではないのですか？)。 [RU_INVOKE_RUN]

このメソッドは、オブジェクトのrun()メソッドを明示的に呼び出しています。一般にRunnableを実装したクラスは、新しいスレッドがrun()メソッドを呼び出す事を期待しており、この場合、Thread.start()を呼び出すのが正しいやり方です。
</code></pre>
<p>こうした説明文がしっかりと表示される（しかも日本語で）点からすると、教育目的で使うのも良いかもしれません。</p>
<p>他に同じようなことをするものに<a href="http://www.jutils.com/index.html">Lint4j</a>などがあるようなので、今度比較をしてみたいなと思います。</p>]]>
        
    </content>
</entry>
<entry>
    <title>MacPorts の使い方と開発方法について</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2008/04/macports.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1099" title="MacPorts の使い方と開発方法について" />
    <id>tag:labs.unoh.net,2008://2.1099</id>
    
    <published>2008-04-28T02:29:11Z</published>
    <updated>2008-04-28T02:45:20Z</updated>
    
    <summary>こんにちは、naoya です。 先日、社内の勉強会で MacPorts の使い方から Ports の追加方法まで幅広く紹介しました。MacPorts は、FreeBSD の ports が元になっていると聞いていましたが、バイナリバッケージまで作れるとは知りませんでした。 詳しくは、資料を参照してください。 なお、資料の中で Ports で追加している bat というプログラムは、Global standard programming with GNU Autotoolsで紹介されているプログラムです。 document.write(&apos;&apos;);                 Read this doc on Scribd: MacPorts   var scribd_doc = new scribd.Document(2674173, &apos;key-lj2b9kntskcxvqvici1&apos;);...</summary>
    <author>
        <name>unoh</name>
        
    </author>
            <category term="Mac" />
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[<p>こんにちは、naoya です。</p>
<p>先日、社内の勉強会で MacPorts の使い方から Ports の追加方法まで幅広く紹介しました。MacPorts は、FreeBSD の ports が元になっていると聞いていましたが、バイナリバッケージまで作れるとは知りませんでした。</p>
<p>詳しくは、資料を参照してください。</p>
<p>なお、資料の中で Ports で追加している bat というプログラムは、<a href="http://labs.unoh.net/2006/10/global_standard_programming_wi.html">Global standard programming with GNU Autotools</a>で紹介されているプログラムです。</p>

<div style="display:none"><script>document.write('<noscript>');</script></div> <object codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" id="embedded_flash_2674173_1lddfw_object" name="embedded_flash_2674173_1lddfw_object" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" align="middle" height="500" width="450"> <param name="movie" value="http://documents.scribd.com/ScribdViewer.swf?document_id=2674173&access_key=key-lj2b9kntskcxvqvici1&page=1&version=1"> <param name="quality" value="high"> <param name="play" value="true"> <param name="loop" value="true"> <param name="scale" value="showall"> <param name="wmode" value="opaque"> <param name="devicefont" value="false"> <param name="bgcolor" value="#ffffff"> <param name="menu" value="true"> <param name="allowFullScreen" value="true"> <param name="allowScriptAccess" value="always"> <param name="salign" value=""> <embed src="http://documents.scribd.com/ScribdViewer.swf?document_id=2674173&access_key=key-lj2b9kntskcxvqvici1&page=1&version=1" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" play="true" loop="true" scale="showall" wmode="opaque" devicefont="false" bgcolor="#ffffff" name="embedded_flash_2674173_1lddfw_object" menu="true" allowfullscreen="true" allowscriptaccess="always" salign="" type="application/x-shockwave-flash" align="middle" height="500" width="450"></embed> </object><div style="display:none"> </noscript> <script type="text/javascript" src='http://www.scribd.com/javascripts/view.js'></script></div><div id='embedded_flash_2674173_1lddfw' style="width:100%;height:100%"><span style="display:none">Read this doc on Scribd: <a href="http://www.scribd.com/doc/2674173/MacPorts">MacPorts</a></span> </div> <div style="display:none"><script type="text/javascript"> var scribd_doc = new scribd.Document(2674173, 'key-lj2b9kntskcxvqvici1'); scribd_doc.addParam('height', 500); scribd_doc.addParam('width', 450); scribd_doc.addParam('page', 1); scribd_doc.addParam('mode', 'slideshow'); scribd_doc.write('embedded_flash_2674173_1lddfw');</script></div>

<p></p>]]>
        
    </content>
</entry>
<entry>
    <title>PHPでDocTest</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2008/04/doctest-for-php.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1098" title="PHPでDocTest" />
    <id>tag:labs.unoh.net,2008://2.1098</id>
    
    <published>2008-04-25T02:52:56Z</published>
    <updated>2008-04-25T02:57:53Z</updated>
    
    <summary>yamaokaです。 何かソースコードを書いた場合、皆さんはどのようにテストをしていますか？ 　PHPの場合、PHPUnitやSimpleTestを使ってユニットテストをすることが多いと思います。でも、ユニットテストのために新しいファイルを作ってメソッドを実装したりするの、面倒くさくないですか？ Pythonには標準でDocTestという仕組みが付いています。詳細はPythonのドキュメント（日本語）を参照してもらうことにして、簡単に言うと、実際のソースコードの中にコメントとしてテストケースを書いてしまおうというアイデアです。 「実際のソースコード＝テストケース」になるのですから、メソッドを修整したからテストケースも修整して…という手間が少なくて済みますよね。そうしたDocTestの仕組みを、PHPに移植しようとする試みを紹介します。 rhacoのDocTest rhacoは「PHPのライ...</summary>
    <author>
        <name>unoh</name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[<p>yamaokaです。</p>

<p>
何かソースコードを書いた場合、皆さんはどのようにテストをしていますか？
　PHPの場合、<a href="http://www.phpunit.de/">PHPUnit</a>や<a href="http://simpletest.org/">SimpleTest</a>を使ってユニットテストをすることが多いと思います。でも、ユニットテストのために新しいファイルを作ってメソッドを実装したりするの、面倒くさくないですか？
</p>

<p>
Pythonには標準でDocTestという仕組みが付いています。詳細は<a href="http://docs.python.org/lib/module-doctest.html">Pythonのドキュメント</a>（<a href="http://www.python.jp/doc/2.4/lib/module-doctest.html">日本語</a>）を参照してもらうことにして、簡単に言うと、実際のソースコードの中にコメントとしてテストケースを書いてしまおうというアイデアです。
</p>

<p>
「実際のソースコード＝テストケース」になるのですから、メソッドを修整したからテストケースも修整して…という手間が少なくて済みますよね。そうしたDocTestの仕組みを、PHPに移植しようとする試みを紹介します。
</p>

<h3>rhacoのDocTest</h3>

<p>
<a href="http://rhaco.org/">rhaco</a>は「PHPのライブラリパッケージ／ セットアップアプリケーション」です（公式サイトより）。rhacoのソースコード自体にDocTestが記述されているので、サンプルとして見るにはちょうどいいでしょう。webアプリケーションフレームワークとして利用する以外に単にライブラリとして利用することもできるので、rhacoを利用していないソースコードのDocTestをrhacoを使って行うことも可能です。
</p>

<p>
さっそくDocTestを試してみましょう。次のようなFooクラスを用意します。
<pre class="code"><code>&lt;?php
class Foo
{
    function bar()
    {
        <span style="color:#F00;">/*** eq('bar', Foo::bar()); */</span>
        return 'bar';
    }
    function baz()
    {
        <span style="color:#F00;">/*** #pass */</span>
    }
}
</code></pre>
「<code><span style="color:#F00;">/*** … */</span></code>」で囲まれた箇所がDocTestのテストケースとして処理されることになります。今はテストしないとか、テストコードをまだ書いていない場合は「#pass」と書いておけばスキップされます。
</p>

<p>
次に、テストを実行するためのtest.phpを準備します。
<pre class="code"><code>&lt;?php
require_once 'path/to/rhaco/Rhaco.php';
Rhaco::import('util.DocTest');
DocTest::execute('Foo.php');
</code></pre>
</p>

<p>
そして、test.phpを実行してみます。
<pre class="code"><code>$ php -q test.php
success: 1 / fail: 0 / pass: 1 / none: 0 / all: 2

(Foo::baz:line. 9)PASS Foo.php</code></pre>
テストが実行されましたね！　試しにFoo::barのテストコードを「<code>/*** eq('barrrr', Foo::bar()); */</code>」に書き換えて実行しなおすと、次のようにきちんとエラーになります。
<pre class="code"><code>$ php -q test.php
success: 0 / fail: 1 / pass: 1 / none: 0 / all: 2

(Foo::bar:line. 4)FAIL expectation [string(6) "barrrr"
] : Result [string(3) "bar"
]
(Foo::baz:line. 9)PASS Foo.php</code></pre>
</p>

<p>
値の一致をテストする「eq」コマンド以外にもテスト用のコマンドが用意されているので、詳しくはrhacoのソースかドキュメントを参照してください。
</p>

<h3>その他のDocTest</h3>

<p>
その他のDocTestの試みとしては、現在次のバージョンが開発されているwebアプリケーションフレームワーク、<a href="http://kunit.jp/maple/">Maple</a>の<a href="http://d.hatena.ne.jp/kunit/20080205#1202142580">DocTest導入の試み</a>があげられます。また、同じくwebアプリケーションフレームワークの<a href="http://www.symfony-project.org/">symfony</a>でも、<a href="http://blog.symfony.jp/2008/03/05/sfdoctestplugin/">sfDocTestPluginが開発されています</a>。
</p>

<p>
PHPのライブラリ集、PEARでは、まだアルファ版ですが<a href="http://pear.php.net/package/Testing_DocTest/">Testing_DocTest</a>がリリースされています。
</p>

<h3>最後に</h3>

<p>
rhacoのDocTestを中心に紹介しましたが、いかがでしょうか。テストコードを記述する負担をできるだけ軽くする試みとして、DocTestは面白いと思います。反面、ソースコード中にテストコードが混在するので、ソースコードが見づらくなるといった欠点もあります。そうした場合、従来のユニットテストと併用するのも手ですね（rhacoの場合、DocTestからユニットテストを実行できます）。いろいろなテストコードの書き方がありますが、選択肢の一つとして考えてもよいのではないでしょうか。
</p>
]]>
        
    </content>
</entry>
<entry>
    <title>rpmパッケージを作ろう</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2008/04/rpm.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1097" title="rpmパッケージを作ろう" />
    <id>tag:labs.unoh.net,2008://2.1097</id>
    
    <published>2008-04-24T08:07:49Z</published>
    <updated>2008-04-24T08:36:03Z</updated>
    
    <summary>尾藤正人(a.k.a BTO)です 先日社内勉強会でrpmパッケージの作り方についてやってみました。 資料を公開しておくのでよろしければご参照ください。 document.write(&apos;&apos;);			 		 				 				 				 				 		 							Read this doc on Scribd: rpm	  	var scribd_doc = new scribd.Document(2559467, &apos;key-1h2bnnas1ykcigsjw9uu&apos;); 						scribd_doc.write(&apos;embedded_flash_2559467_a55g5&apos;); 参考用に以前GNU Autotools用のサンプルプログラムで作ったbatのrpmパッケージを使いました。 次のようなコマンドでrpmパッケージを作成できます。 基本的な機能をある程度網羅したつもりなので、参...</summary>
    <author>
        <name>unoh</name>
        
    </author>
            <category term="ネタ" />
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[尾藤正人(a.k.a BTO)です

先日社内勉強会でrpmパッケージの作り方についてやってみました。
資料を公開しておくのでよろしければご参照ください。

<div style="display:none"><script>document.write('<noscript>');</script></div>	<object codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" id="embedded_flash_2559467_a55g5_object" name="embedded_flash_2559467_a55g5_object" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" align="middle"	height="500" width="100%">		<param name="movie"	value="http://documents.scribd.com/ScribdViewer.swf?document_id=2559467&access_key=key-1h2bnnas1ykcigsjw9uu&page=&version=1"> 		<param name="quality" value="high"> 		<param name="play" value="true">		<param name="loop" value="true"> 		<param name="scale" value="showall">		<param name="wmode" value="opaque"> 		<param name="devicefont" value="false">		<param name="bgcolor" value="#ffffff"> 		<param name="menu" value="true">		<param name="allowFullScreen" value="true"> 		<param name="allowScriptAccess" value="always"> 		<param name="salign" value="">		<embed src="http://documents.scribd.com/ScribdViewer.swf?document_id=2559467&access_key=key-1h2bnnas1ykcigsjw9uu&page=&version=1" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" play="true" loop="true" scale="showall" wmode="opaque" devicefont="false" bgcolor="#ffffff" name="embedded_flash_2559467_a55g5_object" menu="true" allowfullscreen="true" allowscriptaccess="always" salign="" type="application/x-shockwave-flash" align="middle" height="500" width="100%"></embed>	</object><div style="display:none">	</noscript>	<script type="text/javascript" src='http://www.scribd.com/javascripts/view.js'></script></div><div id='embedded_flash_2559467_a55g5' style="width:100%;height:100%"><span style="display:none">Read this doc on Scribd: <a href="http://www.scribd.com/doc/2559467/rpm">rpm</a></span>	</div> <div style="display:none"><script type="text/javascript"> 	var scribd_doc = new scribd.Document(2559467, 'key-1h2bnnas1ykcigsjw9uu'); 						scribd_doc.write('embedded_flash_2559467_a55g5');</script></div>

参考用に以前GNU Autotools用のサンプルプログラムで作ったbatのrpmパッケージを使いました。
次のようなコマンドでrpmパッケージを作成できます。
基本的な機能をある程度網羅したつもりなので、参考になれば幸いです。

<pre class="code">rpmbuild -ta bat-0.0.3.tar.gz</pre>

<a href="http://labs.unoh.net/download/bat-0.0.3.tar.gz">bat-0.0.3.tar.gz</a>]]>
        
    </content>
</entry>
<entry>
    <title>CSSによるデザインワークと相性のよいHTMLって？</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2008/04/csshtml.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1096" title="CSSによるデザインワークと相性のよいHTMLって？" />
    <id>tag:labs.unoh.net,2008://2.1096</id>
    
    <published>2008-04-22T08:37:06Z</published>
    <updated>2008-04-22T08:56:25Z</updated>
    
    <summary>yamazakiです。最近だいぶあたたかくなってきましたね。おかげで日中眠くて仕方ないわけですがいかがお過ごしでしょうか。 ウノウに入る以前も含めてそれなりに長いことHTMLとCSSを書いてきたわけですが、今回は試みに、「だいたいこういうところに気を使われたHTMLだと、CSSでのデザイン適用やレイアウトがやりやすいな」というこれまでの経験則を簡単ですがまとめてみたいと思います。 まあ、このあたりはCSS書く人とHTML書く人の間でちゃんとルールを決めておけばいいだけの話なので、そもそも何の役に立つのか疑問といえば疑問ですが（笑 たとえばユーザがCSSを書いてスキンを作れるようなサービスを作る際、どういったHTMLにするかを決める、みたいな時には少し参考になる、かもしれません。 ID、クラスを適切に割り振って、要素がCSS側から一意に特定できるように たとえばグローバルナビゲーションとカテ...</summary>
    <author>
        <name>unoh</name>
        
    </author>
            <category term="Tips" />
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[<p>yamazakiです。最近だいぶあたたかくなってきましたね。おかげで日中眠くて仕方ないわけですがいかがお過ごしでしょうか。</p>

<p>ウノウに入る以前も含めてそれなりに長いことHTMLとCSSを書いてきたわけですが、今回は試みに、「だいたいこういうところに気を使われたHTMLだと、CSSでのデザイン適用やレイアウトがやりやすいな」というこれまでの経験則を簡単ですがまとめてみたいと思います。</p>
<p>まあ、このあたりはCSS書く人とHTML書く人の間でちゃんとルールを決めておけばいいだけの話なので、そもそも何の役に立つのか疑問といえば疑問ですが（笑<br />
たとえばユーザがCSSを書いてスキンを作れるようなサービスを作る際、どういったHTMLにするかを決める、みたいな時には少し参考になる、かもしれません。</p>

<h3>ID、クラスを適切に割り振って、要素がCSS側から一意に特定できるように</h3>
<p>
たとえばグローバルナビゲーションとカテゴリー別のナビゲーションが同じulで書かれているとして、どちらがどちらかCSSで特定できないと、別の見た目にしようとしても難しいです。
</p>
<pre class="code">
&lt;ul&gt;
&lt;li&gt;グローバル&lt;/li&gt;
&lt;li&gt;グローバル&lt;/li&gt;
&lt;/ul&gt;

&lt;ul&gt;
&lt;li&gt;カテゴリ内&lt;/li&gt;
&lt;li&gt;カテゴリ内&lt;/li&gt;
&lt;/ul&gt;
</pre>
<p>なので可能な限り「表示される内容に共通項のない部分」にはそれぞれID割り振るなどして特定できるようにします。</p>

<pre class="code">&lt;ul id=&quot;gNavi&quot;&gt;
&lt;li&gt;グローバル&lt;/li&gt;
&lt;li&gt;グローバル&lt;/li&gt;
&lt;/ul&gt;

&lt;ul id=&quot;catNavi&quot;&gt;
&lt;li&gt;カテゴリ内&lt;/li&gt;
&lt;li&gt;カテゴリ内&lt;/li&gt;
&lt;/ul&gt;</pre>

<p>さらに、「同じ『ナビゲーション』なので」ということで、同じクラスを振っておくと、似たような見た目にしたい場合に便利。</p>

<pre class="code">&lt;div id=&quot;gNavi&quot; class=&quot;navigation&quot;&gt;
&lt;ul&gt;
&lt;li&gt;グローバル&lt;/li&gt;
&lt;li&gt;グローバル&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&quot;catNavi&quot; class=&quot;navigation&quot;&gt;
&lt;ul&gt;
&lt;li&gt;カテゴリ内&lt;/li&gt;
&lt;li&gt;カテゴリ内&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;</pre>

<p>もちろん、たとえば「ページ内にH1タグは一つしかない」というポリシーが全ページできちんと貫かれていれば、H1タグに余計なIDをつけたりしなくても問題ないと思います。<br />
大事なのは「ちゃんと別々のものだと区別できること」です。</p>


<h3>同じようなものには同じクラスを割り振る</h3>

<p>IDはその名の通り、ページ内に唯一のものに割り振っておくべきものです。一方で「クラス」は、同じようなものを「これとこれは同じようなものですよ」ということを表す場合に使います。<br />
似たものはやはり似たような見た目にしたい場合が多いので、似たような要素にはできるだけ同じクラスが割り振られているほうが好ましいと思います。<br />
逆に、たとえば同じような内容なんだけどちょっとだけ違うものに、全く別のクラスが指定されていると色々と面倒です。<br />
たとえば、ブログの新着記事のリストと人気記事のリストがあったとして、</p>
<pre class="code">
&lt;ul class=&quot;recentPostList&quot;&gt;
&lt;li&gt;記事1&lt;/li&gt;
&lt;li&gt;記事2&lt;/li&gt;
&lt;/ul&gt;

&lt;ul class=&quot;popularPostList&quot;&gt;
&lt;li&gt;記事i&lt;/li&gt;
&lt;li&gt;記事ii&lt;/li&gt;
&lt;/ul&gt;</pre>

<p>としてしまうと、二つのリストに同じ見た目を指定したいときに、</p>

<pre class="code">ul.recentPostList,
ul.popularPostList{}</pre>

<p>といちいち書かなくてはいけなくなります。※まあ２つくらいだったらいいのですが、これが多くなってくるとだいぶ残念な感じになっていきます。<br />
こういう場合は、クラスはスペースで区切って複数指定できますので、たとえば</p>

<pre class="code">&lt;ul class=&quot;postList recent&quot;&gt;
&lt;li&gt;記事1&lt;/li&gt;
&lt;li&gt;記事2&lt;/li&gt;
&lt;/ul&gt;

&lt;ul class=&quot;postList popular&quot;&gt;
&lt;li&gt;記事i&lt;/li&gt;
&lt;li&gt;記事ii&lt;/li&gt;
&lt;/ul&gt;</pre>

<p>とすると、CSSでは、共通のスタイルを「ul.postList」で指定し、それぞれちょっと別の見た目にしたければ「ul.recent/ul.popular」に指定、という形でスマートに書きやすくなりますし、メンテナンス性もよくなると思います。</p>

<h3>tableのtrごとに「odd」「even」</h3>

<p>テーブルは特に大きくなると見にくくなりがちです。<br />
1行おきに色などを変えられるようにする意味で、テーブルの行ごとにクラスをなにかしら交互に指定してあると、スタイル割り当てがしやすくなります。<br />
同じようにリスト系要素（li）など繰り返される要素にも割り当ててあると便利かも。
</p>

<h3>リスト系要素（ul,ol,dl)の最初と最後が特定できるようにしておく</h3>

<p>:first-childなどの擬似要素がすべてのブラウザでちゃんと使えればこんなものはあまり必要ないのですが、IE6などの対応状況を考えると現実問題としてまだまだ使えません。<br />
ので、リストなどの同じ要素の連続するものの場合は、できるだけ最初と最後に「これが最初の要素」「これが最後の要素」だということがわかるようにしておきます。</p>

<pre class="code">&lt;ul&gt;
&lt;li class=&quot;first&quot;&gt;xxxx&lt;/li&gt;
&lt;li&gt;xxxx&lt;/li&gt;
&lt;li&gt;xxxxx&lt;/li&gt;
&lt;li class=&quot;last&quot;&gt;xxxx&lt;/li&gt;
&lt;/ul&gt;</pre>

<p>なんでこういうことが必要になるかというと、</p>
<ul>
<li>最初の要素だけマージンを狭く/広くしたい</li>
<li>最後の要素だけマージンを狭く/広くしたい</li>
<li>最初の要素のところにだけ背景画像指定したい</li>
<li>インライン化して横並びのメニューにして、間に線を入れたいんだけど全部のli要素に線を割り当てると一本余計になるので消したい</li>
</ul>

<p>などなど、最初/最後の要素はちょっとだけ違うスタイルにしたいことが結構よくあるからです。</p>

<h3>h1～h6タグ直下には&lt;span&gt;か&lt;a&gt;タグが必ず入るようにしておく</h3>
<p>「見出し」はやはり「画像に差し替えたい」とか、「特別な装飾を施したい」とかいったことがよくあります。<br />
また、文字の書かれてる部分だけに装飾したい場合や、margin/paddingのコントロールの都合で子インライン要素があるほうが調整しやすくなります。<br />
といったわけで、直下に&lt;span&gt;もしくは&lt;a&gt;タグなどのインライン要素が入るようにしてあると、CSSでのデザインの幅がだいぶ広がると思います。

<pre class="code">&lt;h1&gt;hogehoge&lt;/h1&gt;</pre>
<p>ではなく</p>
<pre class="code">&lt;h1&gt;&lt;span&gt;hogehoge&lt;/span&gt;&lt;/h1&gt;</pre>

<p>その他にもCSSの猛者の皆様的に「こうなっていると嬉しい」という例あると思いますので、もし何かあればぜひ教えてください！</p>]]>
        
    </content>
</entry>
<entry>
    <title>PythonのORMを研究してみる(1)</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2008/04/pythonorm1.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1095" title="PythonのORMを研究してみる(1)" />
    <id>tag:labs.unoh.net,2008://2.1095</id>
    
    <published>2008-04-21T07:40:16Z</published>
    <updated>2008-04-21T07:41:40Z</updated>
    
    <summary>PythonのORMのご紹介</summary>
    <author>
        <name>unoh</name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[			<p>Pythonで利用できるORMをざっと列挙してみると、次のようなものがあげられます。</p>
			<ul>
				<li> <a href="http://www.sqlalchemy.org/">SQLAlchemy</a></li>

				<li> <a href="http://www.sqlobject.org/">SQLObject</a></li>
				<li> <a href="http://www.djangoproject.com/">Django</a></li>
				<li> <a href="https://storm.canonical.com/FrontPage">Storm</a></li>
				<li> <a href="http://www.dbmother.org/">Mother</a></li>
				<li> <a href="http://www.aminus.net/dejavu">Dejavu</a></li>

				<li> <a href="http://www.aminus.net/geniusql">GeniuSQL</a></li>
			</ul>
			<p>実際に利用するとなると、ドキュメントの充実度とユーザ数でSQLAlchemyに一日の長があり、すでにPythonのORMの標準になったという感があります。</p>
			<p>また、Djangoアプリケーションという点に限れば、Djangoに含まれるORM(django.db)を使うということになるでしょう。</p>
			<p>しかしながら、必要とする機能や実行速度、生成するSQL、APIの好みといった点で、SQLAlchemyとDjango以外のライブラリを選択することもありうるでしょう。</p>
			<p>実行速度という観点からみると、少し古い記事になりますが、下記のURLの記事が参考になります。</p>

			<ul>
				<li> <a href="http://www.aminus.org/blogs/index.php/2007/08/18/storm_sqlalchemy_and_geniusql?blog=2">Storm,SQLAlchemy,GeniuSQLの実行速度の比較</a>
				<ul>
					<li> <a href="http://techspot.zzzeek.org/?p=15">それに対するSQLAlchemyの作者からの反論</a></li>
				</ul>
				</li>
			</ul>

			<p>各ORMの特徴や実装、またそのORMを採用する理由というのは非常に興味深いものがあるので、今後何回かに分けて、上記のORMを紹介していきたいと思います。</p>
			<p>というわけで、次回は<a href="http://pypi.python.org/pypi/mailman/">Mailmanの次期バージョン</a>で採用されるらしい、Stormを紹介する予定です。</p>
]]>
        
    </content>
</entry>
<entry>
    <title>テスト担当者のモチベーション</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2008/04/post_119.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1090" title="テスト担当者のモチベーション" />
    <id>tag:labs.unoh.net,2008://2.1090</id>
    
    <published>2008-04-09T06:21:08Z</published>
    <updated>2008-04-09T07:03:49Z</updated>
    
    <summary>こんにちは！やまもと＠テスト番長です。 一般人に向かって自己紹介するとき、 「一応サラリーマンです。WEBサイト作ったりとかしてます。」「専門はテストです。」というと 「出来栄えをチェックする人だから、エライ人なんですねー」 と若干良い方に誤解されがちですが、 同業者に「専門はテストです。」というと「あー、大変っすよねー」と必ず同情されます。 テストというのはどうもモチベーションが上がりにくいお仕事のようです。 今回は来るべき五月病シーズンに向けて、特に新人に近い立場の方がモチベーションを失わずに居られる方法を幾つか考えてみましょう。 テスト担当を押し付けられたとき 新人を安易にテスト業務に割り当てるケースがあります。 新人はまだ経験と信頼性が足りない故に他の作業で使いづらく、そうなりがちです。 もしプログラミングの方に興味があるなら、そういう意向をアピールしておくべきです。 いつ頃プログ...</summary>
    <author>
        <name>unoh</name>
        
    </author>
            <category term="Tips" />
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[こんにちは！やまもと＠テスト番長です。

一般人に向かって自己紹介するとき、
「一応サラリーマンです。WEBサイト作ったりとかしてます。」「専門はテストです。」というと
「出来栄えをチェックする人だから、エライ人なんですねー」
と若干良い方に誤解されがちですが、
同業者に「専門はテストです。」というと「あー、大変っすよねー」と必ず同情されます。

テストというのはどうもモチベーションが上がりにくいお仕事のようです。
今回は来るべき五月病シーズンに向けて、特に新人に近い立場の方がモチベーションを失わずに居られる方法を幾つか考えてみましょう。

<h3>テスト担当を押し付けられたとき</h3>
新人を安易にテスト業務に割り当てるケースがあります。
新人はまだ経験と信頼性が足りない故に他の作業で使いづらく、そうなりがちです。

もしプログラミングの方に興味があるなら、そういう意向をアピールしておくべきです。
いつ頃プログラミングをさせてもらえるか、見通しを上司と話し合っておきましょう。

その上で今は経験を積むためだと割り切ってしまうのがいいでしょう。
テストのやり方を覚えるのも相当大事なことですし、テストしていても仕様書もコードも見られるし、決して退屈はしないハズ。
＃いきなりプロジェクトが炎上してて退屈どころじゃないかもしれませんが。

<h3>要領良くこなすとスッキリ。</h3>
テストケースの出来具合によっては、まとめてチェック出来る項目が大量にあったりします。
要領良くテストを実施する方法を常に考えましょう。単純作業はなるべく排除しましょう。
やりがいのあるテスト項目に己の時間と精神力を集中させましょう。

<h3>攻めの姿勢に出る</h3>
用意されたテストケースをただ大量にこなしているだけだと飽きることもあるでしょうが、ここは一つ攻めの姿勢でいきましょう。
テストケースは抜けがあったりするものです。普通あります。
実施しながら穴を探しましょう。穴を見つけたらフィードバックしましょう。
レアなバグを見つけたら、周りの人に見せて褒めてもらうのがいいですね。
チームから頼りにされるようになりましょう。

<h3>スキルアップを考える</h3>
同じようなテスト作業ばっかり日々繰り返していると、成長できていないことに気づき、人生このままでいいのか悩みだします。スキルアップを心掛けましょう。
テスト関連の良い書籍や資格制度も出てきていますので、手を伸ばしてみましょう。
仲間がいれば一緒にやるといいですね。

<h3>休める時に積極的に休暇を取る</h3>
テストに関わる（廻される）人は真面目な人が多いので、休むことを積極的に考えましょう。
神経を使う仕事なのでリフレッシュは重要です。
体を動かしたり、趣味の時間を確保するのもいいですね。

<h3>たまにはコーディングする</h3>
たまにコーディングすると気分転換になります。
プログラムを（ある程度は）組めないとテストも出来ないので、離れてしまわないようにしましょう。
テスト用のツールなどを作れば仕事も楽になりますよ。

<h3>会社でのテスト業務の地位が低くて萎えるなら</h3>
テストの重要性を理解してもらえない環境だと、テンションのあがりようがありません。
テストを軽視するような人は所詮素人なので、そんな人達が何を言おうと気にすることはありませんが、心が乾いてしまう前に次の展開を考えましょう。


とにかく、状況に流されて何もしないのは一番よくありませんね。
なんだかテストに限らない気もしてきましたが、よかったら試してみてください。

他にも良い方法があればぜひ教えてください！





]]>
        
    </content>
</entry>
<entry>
    <title>LD_PRELOADを使って任意の関数呼び出しにフックしてみる</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2008/04/ld_preload.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1086" title="LD_PRELOADを使って任意の関数呼び出しにフックしてみる" />
    <id>tag:labs.unoh.net,2008://2.1086</id>
    
    <published>2008-04-07T03:12:58Z</published>
    <updated>2008-04-07T03:23:22Z</updated>
    
    <summary>尾藤正人(a.k.a BTO)です 先日の社内勉強会のLTでLD_PRELOADについて簡単にやってみました。 LD_PRELOADって? 環境変数$LD_PRELOADを使うと他のライブラリの読み込みの前に任意のライブラリを先に読み込ませることができます。 実行プログラムの形式にELF形式を採用しているOSで使うことができます。 Linuxであれば問題なく使用できるはずです。 何ができるのか プログラムを変更することなく、任意の関数を上書きしたり、任意の関数にフックすることができます。 libhookwriteを作ってみた 簡単なサンプルプログラムとしてlibhookwriteというのを作ってみました。 libhookwriteはその名の通りwrite(2)にフックをかけることができます。 といってもできることは限られていてファイルのタイムスタンプの更新か、任意のプログラムをsh経由で実...</summary>
    <author>
        <name>unoh</name>
        
    </author>
            <category term="ネタ" />
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[尾藤正人(a.k.a BTO)です

先日の社内勉強会のLTでLD_PRELOADについて簡単にやってみました。

<h2>LD_PRELOADって?</h2>

環境変数$LD_PRELOADを使うと他のライブラリの読み込みの前に任意のライブラリを先に読み込ませることができます。
実行プログラムの形式にELF形式を採用しているOSで使うことができます。
Linuxであれば問題なく使用できるはずです。

<h2>何ができるのか</h2>

プログラムを変更することなく、任意の関数を上書きしたり、任意の関数にフックすることができます。

<h2>libhookwriteを作ってみた</h2>

簡単なサンプルプログラムとしてlibhookwriteというのを作ってみました。
libhookwriteはその名の通りwrite(2)にフックをかけることができます。
といってもできることは限られていてファイルのタイムスタンプの更新か、任意のプログラムをsh経由で実行することしかできません。

<h2>ダウンロード</h2>

<a href="http://labs.unoh.net/download/libhookwrite-0.0.1.tar.gz">libhookwrite-0.0.1.tar.gz</a>

<h2>インストール</h2>

お約束通り

<pre class="code">
tar zxvf libhookwrite-0.0.1.tar.gz
cd libhookwrite-0.0.1
./configure
make
sudo make install
</pre>

rpmでもいけます。

<pre class="code">
rpmbuild -ta libhookwrite-0.0.1.tar.gz
sudo rpm -ivh libhookwrite-0.0.1-1.i386.rpm
</pre>

<h2>使い方</h2>

環境変数$LD_PRELOADにlibhookwrite.soを指定します。
さらに環境変数$HOOKWRITE_UPDATE_FILEか$HOOKWRITE_COMMANDを指定します。

HOOKWRITE_UPDATE_FILEにファイル名を指定すると、write(2)が呼ばれたときに指定されたファイルのタイムスタンプを現在時刻に更新します。

HOOKWRITE_COMMANDに任意のコマンドを指定すると、write(2)が呼ばれたときに指定されたコマンドを/bin/sh経由で実行します。

例えば、次のようなシェルスクリプトcat.shを実行すると、write(2)が呼ばれた時点で$HOME/tmp/catというファイルのタイムスタンプを現在の時刻に更新して、"hoge"と出力します。

<pre class="code">
#!/bin/sh
HOOKWRITE_UPDATE_FILE=$HOME/tmp/cat ¥
  HOOKWRITE_COMMAND='echo hoge' ¥
  LD_PRELOAD=/usr/lib/libhookwrite.so ¥
  /bin/cat $@
</pre>

<h2>使い道</h2>

例えばエディタがファイルを保存したときに、何らかのアクションを起こしたい場合に使えるかもしれません。
プログラムに依存しないので、vimだろうがemacsだろうが何でもいけるはず。
ただ、スワップファイルの書き出しにも反応してしまいますが。(^^;

vimを使ってsymfonyプロジェクトの開発をやってて、ファイルを保存したい瞬間にsymfony ccを走らせてキャッシュクリアしたい場合はこんな感じのaliasを作ればいいでしょうか。

<pre class="code">
alias vim="LD_PRELOAD=/usr/lib/libhookwrite.so HOOKWRITE_COMMAND='/symfony/project/symfony cc' /usr/bin/vim"
</pre>

<h2>プログラム</h2>

プログラム自体は非常に簡単です。

<pre class="code">
static ssize_t (*write_org) (int fd, const void *buf, size_t count) = NULL;
</pre>

write(2)と同じプロトタイプ宣言を持つ関数ポインタwrite_orgを定義しています。
オリジナルのwriteを保存するのに使います。

<pre class="code">
__attribute__((constructor))
void
_save_original_functions()
{
    write_org = (ssize_t(*)(int, const void *, size_t)) dlsym(RTLD_NEXT, "write");
}
</pre>

dlsym(3)を使ってwriteのアドレスを取り出して、write_orgに保存しています。
__attribute__((constructor))というのはgccの拡張になってて、これを指定しておくとmain関数が呼ばれる前に実行してくれます。

後は単純にwrite関数を改めて定義して、その中に任意の処理を書いておきます。
最後に    return write_org(fd, buf, count);でオリジナルの処理を呼び出して終わりです。

<h2>参考</h2>

<a href="https://www.linux.or.jp/JM/html/LDP_man-pages/man8/ld.so.8.html">man ld.so</a>でマニュアルが読めます。
LD_PRELOADの他にもいろいろな機能がありますので、一度読んでおくといいかもしれません。

<h2>fakechroot</h2>

LD_PRELOADを使った面白いソフトウェアで<a href="https://fakechroot.alioth.debian.org/">fakechroot</a>というのがあります。
chroot(2)の実行にはroot権限が必要ですが、fakechrootでは擬似的に一般ユーザ権限でchrootを実現しています。
LD_PRELOADを使って、ファイル操作に関わる部分にすべてフックをかけて擬似的にchroot環境を提供しているんでしょうね。

<h2>Mac OS Xだと</h2>

実行プログラムの形式がELFではなくMach-Oが採用されています。
なので、LD_PRELOADは使えないはず。
代わりにDYLD_INSERT_LIBRARIESというのが使えます。

<a href="https://developer.apple.com/documentation/Darwin/Reference/ManPages/man1/dyld.1.html">man dyld
</a>

詳しく検証してないので、詳細はよくわかってません。

<h2>まとめ</h2>

LD_PRELOADを使うとプログラムに直接手を加えることなく、外から挙動をコントロールすることができます。
応用範囲は無限大です。]]>
        
    </content>
</entry>
<entry>
    <title>gdbの使い方</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2008/04/gdb.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1085" title="gdbの使い方" />
    <id>tag:labs.unoh.net,2008://2.1085</id>
    
    <published>2008-04-04T10:22:50Z</published>
    <updated>2008-04-07T02:33:42Z</updated>
    
    <summary>今年の2月にマカーになったbokkoです。どうも僕の使っているフォントがほかの人には見づらいらしく、「そのフォントはねぇよw」と言われたり、外付けのキーボードを使っているせいか、「MacBookの意味なし!」と社内で言われてたりしています。 今日はgdbのお話です。gdbは非常に広く使われているデバッガで、特にC、C++のプログラムをデバッグするのによく使われています。  デバッガの使い方 プログラムをデバッグする際、例えば以下の方法が挙げられます。 1. ソースコードを読む 2. ソースコードに出力関数を仕込む(例えばprintf) 3. ソースコードを書き換えて実行してみる これで十分な場合もありますが、そうでない場合もあります。これらの方法ではプログラムを実行している最中にこちらからソースコードレベルでのアクションを起こすことが難しいので、例えば、プログラムをある時点で止めて変数の内...</summary>
    <author>
        <name>unoh</name>
        
    </author>
            <category term="Tips" />
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[今年の2月にマカーになったbokkoです。どうも僕の使っているフォントがほかの人には見づらいらしく、「そのフォントはねぇよw」と言われたり、外付けのキーボードを使っているせいか、「MacBookの意味なし!」と社内で言われてたりしています。

今日はgdbのお話です。gdbは非常に広く使われているデバッガで、特にC、C++のプログラムをデバッグするのによく使われています。

<h3> デバッガの使い方</h3>

プログラムをデバッグする際、例えば以下の方法が挙げられます。

1. ソースコードを読む
2. ソースコードに出力関数を仕込む(例えばprintf)
3. ソースコードを書き換えて実行してみる

これで十分な場合もありますが、そうでない場合もあります。これらの方法ではプログラムを実行している最中にこちらからソースコードレベルでのアクションを起こすことが難しいので、例えば、プログラムをある時点で止めて変数の内容を確認するといったことが困難です。2と3でもできないことはないですが、CやC++だと何か別のことをやろうとする度にコンパイルし直す必要があります。そこでデバッガの出番です。デバッガを使えばプログラムを1行ずつ実行しながら変数の内容を確認したり、あるループ内の処理がどう実行されてどのようにそのループを抜けたのか確認するのがやりやすくなります。
]]>
        <![CDATA[<h3>プログラムにデバッグ情報を持たせる</h3>

例えば、以下のように(ものすごく単純に)配列をランダムにソートするCのプログラムがあるとします。

<pre class="code">
/* random_sort.c */
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;time.h&gt;
#define COUNT(arr) (sizeof(arr)/sizeof(arr[0]))
void random_sort(int arr[], int n);
void random_sort(int arr[], int n){
  int i, rnd, temp;
  srand(time(NULL));
  for(i=0;i&lt;n;i++){
    rnd = rand() % n;
    temp = arr[i];
    arr[i] = arr[rnd];
    arr[rnd] = temp;
  }
}
int main(int argc, char *argv[]){
  int i, n;
  int nums[] = {1, 2, 3, 4, 5};
  n = COUNT(nums);
  random_sort(nums, n);
  for(i=0;i&lt;n;i++){
    printf(&quot;%d &quot;, nums[i]);
  }
  printf(&quot;\n&quot;);
  return 0;
}
<br />
</pre>

このプログラムをgccでコンパイルしてgdbで実行するためには例えば、

<pre class="code">
$ gcc -g random_sort.c -o random_sort
</pre>

とします。-gはプログラムにデバッグ情報を含ませるためのオプションです。(実際にはCでプログラムを書く際は警告を見逃さないように、もっとオプションを付け足したりするのですが、ここでは割愛します)。作成した実行プログラムをgdbに引数で渡してやります。

<pre class="code">$ gdb ./random_sort                         7165 (c/tips/random_sort)
GNU gdb 6.3.50-20050815 (Apple version gdb-768) (Tue Oct  2 04:07:49 UTC 2007)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type &quot;show copying&quot; to see the conditions.
There is absolutely no warranty for GDB.  Type &quot;show warranty&quot; for details.
This GDB was configured as &quot;i386-apple-darwin&quot;...Reading symbols for shared libraries ... done
(gdb)</pre>

これでgdbを使う準備ができました。次はよく使うコマンドについて解説します。

<h3> プログラムを実行する</h3>

プログラムを実行するにはrunコマンドを使います。

<pre class="code">(gdb) run
Starting program: /Users/bokkko/programming/c/tips/random_sort/random_sort
Reading symbols for shared libraries ++. done
4 3 2 5 1
Program exited normally.
(gdb)
</pre>

ただ単にrunコマンドを実行してもプログラムが正常、もしくは異常終了したり、ユーザからの入力待ちになったりするだけなので、この後は自分が挙動を調べたい関数にブレークポイントを設定したりします。

<h3>ブレークポイントを設定する</h3>

ブレークポイントを設定するにはbreakコマンドを使います。

<pre class="code">(gdb) break random_sort
Breakpoint 1 at 0x1ef0: file random_sort.c, line 13.
(gdb)
</pre>

関数だけでなく、行単位で設定することもできます。

<pre class="code">(gdb) b 15
Breakpoint 1 at 0x1f04: file random_sort.c, line 15.
(gdb) r
Starting program: /Users/bokkko/programming/c/tips/random_sort/random_sort
Reading symbols for shared libraries ++. done
Breakpoint 1, random_sort (arr=0xbfffed24, n=5) at random_sort.c:15
15        for(i=0;i&lt;n;i++){
(gdb)</pre>

<h3>プログラムを1行ずつ実行する</h3>

プログラムを1行ずつ実行するにはnextコマンドを使います。

<pre class="code">(gdb) b main
Breakpoint 1 at 0x1f77: file random_sort.c, line 26.
(gdb) r
Starting program: /Users/bokkko/programming/c/tips/random_sort/random_sort
Reading symbols for shared libraries ++. done
Breakpoint 1, main (argc=1, argv=0xbfffed74) at random_sort.c:26
26        int nums[] = {1, 2, 3, 4, 5};
(gdb) next
27        n = COUNT(nums);
(gdb) next
28        random_sort(nums, n);
(gdb) next
30        for(i=0;&lt;n;i++){
(gdb)</pre>

<h3>ソースコードを表示する</h3>

listコマンドを使うと一部のソースコードを表示することができます。
引数なしで実行した場合、現在の行の前後合わせて10行を表示します。

<pre class="code">
(gdb) b main
Breakpoint 1 at 0x1f77: file random_sort.c, line 26.
(gdb) r
Starting program: /Users/bokkko/programming/c/tips/random_sort/random_sort
Reading symbols for shared libraries ++. done
Breakpoint 1, main (argc=1, argv=0xbfffed74) at random_sort.c:26
26        int nums[] = {1, 2, 3, 4, 5};
(gdb) l
21      }
22
23      int main(int argc, char *argv[]){
24       
25        int i, n;
26        int nums[] = {1, 2, 3, 4, 5};
27        n = COUNT(nums);
28        random_sort(nums, n);
29
30        for(i=0;i&lt;n;i++){
(gdb)
</pre>

引数には関数や行番号を指定することもできます。

<h3>変数の内容を表示する</h3>

変数の内容を表示するにはprintコマンドを使います。

<pre class="code">(gdb) print i
$5 = 0
(gdb)</pre>

また、単に変数を表示するだけでなく、計算もできます。

<pre class="code">(gdb) pirnt i + 10
$5 = 10
(gdb)</pre>

配列の中身も以下のように表示できます。

<pre class="code">(gdb) print nums
$1 = {1, 2, 3, 4, 5}
(gdb)</pre>

上記のソースコードにはありませんが、構造体の内容を表示することもできます。例えば、以下のような構造体とソースコードがあった場合、

<pre class="code">typedef struct list {
  struct list *next;
  int data;
} List;</pre>

<pre class="code">       ・
       ・
       ・
  List *l;
  l = (List *)malloc(sizeof(List));
  l->next = NULL;
  l->data = (int)NULL;
> return l;
       ・
       ・
       ・
</pre>

<pre class="code">//>で↓を実行
(gdb) p *l
  $1 = {
  next = 0x0,
  data = 0
}
(gdb)</pre>

pはprintのエイリアスです。gdbでは長かったり、よく使うコマンドにはエイリアスが用意されています。

また、環境によっては構造体の内容が上記のように改行されず、1行で表示されてしまっているかもしれません。この場合、ホームディレクトリに.gdbinitというファイルを作成して、

<pre class="code">
set print pretty on
</pre>

と記述すれば幸せになれるかもしれません。ただ、構造体のメンバの数が多い場合、画面からはみ出ししまうことがあります。上記の設定はgdbを実行している途中で切り替えることもできるので、状況にあった表示を選択するといいでしょう。

<pre class="code">
(gdb) set print pretty off
(gdb) p *l
$1 = {next = 0x0, data = 0}
(gdb) set print pretty on
(gdb) p *l
$2 = {
  next = 0x0,
  data = 0
}
(gdb) 
</pre>

<h3>バックトレースを表示する</h3>

自分が今、プログラムのどの関数を実行しているのか知りたい場合、backtraceコマンドを使います。以下はステップ実行してrandom_sort関数に入ってbacktraceを実行した様子です。

<pre class="code">(gdb) backtrace
#0  random_sort (arr=0xbfffed24, n=5) at random_sort.c:15
#1  0x00001fb3 in main (argc=1, argv=0xbfffed74) at random_sort.c:28
(gdb)</pre>

このように自分が実行している関数がどこから呼び出されているのかもわかります。

<h3>変数の内容を監視する</h3>

変数の内容を表示するには先述したprintコマンドが使えますが、nextコマンドなどでプログラムをステップ実行しながら毎回指定した変数の内容を表示するにはdisplayコマンドを使います。

以下はforループ内でrand関数で生成した数値を監視している様子です。

<pre class="code">(gdb) b random_sort
Breakpoint 1 at 0x1ef0: file random_sort.c, line 13.
(gdb) r
Starting program: /Users/bokkko/programming/c/tips/random_sort/random_sort
Reading symbols for shared libraries ++. done
Breakpoint 1, random_sort (arr=0xbfffed24, n=5) at random_sort.c:13
13        srand(time(NULL));
(gdb) display rnd
1: rnd = 0
(gdb) n
15        for(i=0;i&lt;n;i++){
1: rnd = 0
(gdb)
16          rnd = rand() % n;
1: rnd = 0
(gdb)
17          temp = arr[i];
1: rnd = 4
(gdb)
18          arr[i] = arr[rnd];
1: rnd = 4
(gdb)
19          arr[rnd] = temp;
1: rnd = 4
(gdb)
15        for(i=0;i&lt;n;i++){
1: rnd = 4
(gdb)
16          rnd = rand() % n;
1: rnd = 4
(gdb)
17          temp = arr[i];
1: rnd = 2
(gdb)</pre>

このように変数の内容がどこでどう変更されたかがわかります。nはnextコマンドのエイリアスで、プログラムの次の行を実行します。

<h3>Emacs上でgdbを使う</h3>


gdbはコマンドラインで使っていると不便に思うことがあります。例えば、実際のコードのどこが実行されているかわかりにくいですし、listコマンドは使う度に頭の中でコンテキストスイッチをしているようなもので、あまりいいものではありません。なので僕は普段、gdbはEmacs上で使っています。Emacs上でgdbを起動するにはM-x gdbを実行します。実行している様子は以下のような感じです。

<img alt="gdb.png" src="http://labs.unoh.net/download/gdb.png" width="550" height="344" />


このようにlistコマンドを使うことなく、ソースコードを見ながらデバッグできます。Visual StudioやEclipseのデバッグ機能を利用したことがある人はこっちの方がなじみやすいかもしれません。プログラム書く時はvi(m)だけど、「gdb使う時はEmacs上で」という人もいるそうです。

<h3>参考文献</h3>

<div class="amazlet-box" style="margin-bottom:0px;"><div class="amazlet-image" style="float:left;"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/475613016X/unoh-22/ref=nosim/" name="amazletlink" target="_blank"><img src="http://ecx.images-amazon.com/images/I/21TSY3KCTJL.jpg" alt="GDBデバッギング入門" style="border: none;" /></a></div><div class="amazlet-info" style="float:left;margin-left:15px;line-height:120%"><div class="amazlet-name" style="margin-bottom:10px;line-height:120%"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/475613016X/unoh-22/ref=nosim/" name="amazletlink" target="_blank">GDBデバッギング入門</a><div class="amazlet-powered-date" style="font-size:7pt;margin-top:5px;font-family:verdana;line-height:120%">posted with <a href="http://www.amazlet.com/browse/ASIN/475613016X/unoh-22/ref=nosim/" title="GDBデバッギング入門" target="_blank">amazlet</a> at 08.04.04</div></div><div class="amazlet-detail">リチャード ストールマン ローランド ペシュ <br />アスキー <br />売り上げランキング: 42902<br /></div><div class="amazlet-review" style="margin-top:10px; margin-bottom:10px"><div class="amazlet-review-average" style="margin-bottom:5px">おすすめ度の平均: <img src="http://images-jp.amazon.com/images/G/09/x-locale/common/customer-reviews/stars-4-0.gif" alt="4.0" /></div><img src="http://images-jp.amazon.com/images/G/09/x-locale/common/customer-reviews/stars-5-0.gif" alt="5" /> Debugging with GDB<br /><img src="http://images-jp.amazon.com/images/G/09/x-locale/common/customer-reviews/stars-3-0.gif" alt="3" /> 入門書ではありません<br /></div><div class="amazlet-link" style="margin-top: 5px"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/475613016X/unoh-22/ref=nosim/" name="amazletlink" target="_blank">Amazon.co.jp で詳細を見る</a></div></div><div class="amazlet-footer" style="clear: left"></div></div>


<div class="amazlet-box" style="margin-bottom:0px;"><div class="amazlet-image" style="float:left;"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/487311246X/unoh-22/ref=nosim/" name="amazletlink" target="_blank"><img src="http://ecx.images-amazon.com/images/I/31WWRYDQ1YL.jpg" alt="GDBハンドブック" style="border: none;" /></a></div><div class="amazlet-info" style="float:left;margin-left:15px;line-height:120%"><div class="amazlet-name" style="margin-bottom:10px;line-height:120%"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/487311246X/unoh-22/ref=nosim/" name="amazletlink" target="_blank">GDBハンドブック</a><div class="amazlet-powered-date" style="font-size:7pt;margin-top:5px;font-family:verdana;line-height:120%">posted with <a href="http://www.amazlet.com/browse/ASIN/487311246X/unoh-22/ref=nosim/" title="GDBハンドブック" target="_blank">amazlet</a> at 08.04.04</div></div><div class="amazlet-detail">アーノルド ロビンス <br />オライリージャパン <br />売り上げランキング: 55079<br /></div><div class="amazlet-review" style="margin-top:10px; margin-bottom:10px"><div class="amazlet-review-average" style="margin-bottom:5px">おすすめ度の平均: <img src="http://images-jp.amazon.com/images/G/09/x-locale/common/customer-reviews/stars-4-0.gif" alt="4.0" /></div><img src="http://images-jp.amazon.com/images/G/09/x-locale/common/customer-reviews/stars-5-0.gif" alt="5" /> 単なるリファレンスとして使うもの<br /><img src="http://images-jp.amazon.com/images/G/09/x-locale/common/customer-reviews/stars-3-0.gif" alt="3" /> 開発慣れしてる人でGDB忘れた人．お勧めです<br /></div><div class="amazlet-link" style="margin-top: 5px"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/487311246X/unoh-22/ref=nosim/" name="amazletlink" target="_blank">Amazon.co.jp で詳細を見る</a></div></div><div class="amazlet-footer" style="clear: left"></div></div>





追記:(2008/04/07)


上記の配列をランダムに並び替えるプログラムですが、ある方から上記のコードでは均等にランダムにならない、とのご指摘を頂きました。均等にランダムになるには関数random_sortの↓の部分を、

<pre class="code">
  for(i=0;i&lt;n;i++){                                                                            
    rnd = rand() % n;                                                                          
    temp = arr[i];                                                                             
    arr[i] = arr[rnd];                                                                         
    arr[rnd] = temp;                                                                           
  }                                                                                            
</pre>

↓のようにするのが正しいです。すみませんでした。

<pre class="code">
  for(i=0;i&lt;n-1;i++){
    rnd = rand() % (n - i) + i;
    temp = arr[i];
    arr[i] = arr[rnd];
    arr[rnd] = temp;
  }
</pre>

また、修正にあたり、<a href="http://www.hyuki.com/d/200510.html#i20051020190000">こちら</a>を参考にさせて頂きました。


この場を借りて御二方に感謝します。ありがとうございました。
]]>
    </content>
</entry>
<entry>
    <title>プチプチAPI に機能追加を行いました</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2008/04/api.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1084" title="プチプチAPI に機能追加を行いました" />
    <id>tag:labs.unoh.net,2008://2.1084</id>
    
    <published>2008-03-31T15:00:00Z</published>
    <updated>2008-03-31T15:58:46Z</updated>
    
    <summary>Keitaです。 去年、公開いたしましたプチプチＡＰＩですが、長い間動作していなかったので修正を行い、さらに機能追加を行いました。 去年は、世の中でもプチプチのおもちゃが発売などが発売され空前のプチプチブームになり、さらにツンデレボイスもついたりして、われわれも負けてられないと、ツンデレヴォイスをつけてみました。 残念ながら、プロの声優さんをゲットするには時間がなかったので、僕が一人で会議室で録音してみました。 サービスに人気が出たら、音声を追加しようと思います。 2008/04/01 API用のバインディングを作成された方があらわれました。わずかAPI公開10分後のことでした。 というわけでうれしくなったのでいくつか僕のものではない音声も追加せていただきました。...</summary>
    <author>
        <name>unoh</name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[Keitaです。
去年、公開いたしました<a href="http://m.unoh.net/">プチプチＡＰＩ</a>ですが、長い間動作していなかったので修正を行い、さらに機能追加を行いました。

去年は、世の中でもプチプチのおもちゃが発売などが発売され空前のプチプチブームになり、さらにツンデレボイスもついたりして、われわれも負けてられないと、ツンデレヴォイスをつけてみました。

残念ながら、プロの声優さんをゲットするには時間がなかったので、僕が一人で会議室で録音してみました。

サービスに人気が出たら、音声を追加しようと思います。

2008/04/01
<a href="http://coderepos.org/share/browser/lang/php/Diggin_Service_Munoh">API用のバインディング</a>を作成された方があらわれました。わずかAPI公開10分後のことでした。

というわけでうれしくなったのでいくつか僕のものではない音声も追加せていただきました。]]>
        
    </content>
</entry>
<entry>
    <title>JavaでPowerPointファイルを読み込む</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2008/03/javapowerpoint.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1082" title="JavaでPowerPointファイルを読み込む" />
    <id>tag:labs.unoh.net,2008://2.1082</id>
    
    <published>2008-03-27T02:59:02Z</published>
    <updated>2008-03-27T03:08:00Z</updated>
    
    <summary>こんにちは。中村です。 JavaからMicrosoft Officeのファイルを読み書きするのには、100%Javaで実装されているApache POIを利用することができます。 昔はPowerPointファイルを読み書きするAPI群であるHSLFはなかったので、POIで検索するとEXCELファイルを読み書きするHSSFが中心に紹介されているようです。 今回はHSLFを使ってPowerPointファイルの中にある文字列を出力する簡単なサンプルを書いてみました。 package net.unoh.ppt2text; import java.io.FileNotFoundException; import java.io.IOException; import org.apache.poi.hslf.HSLFSlideShow; import org.apache.poi.hslf.model...</summary>
    <author>
        <name>unoh</name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[<p>こんにちは。中村です。</p>
<p>JavaからMicrosoft Officeのファイルを読み書きするのには、100%Javaで実装されている<a href="http://poi.apache.org/">Apache POI</a>を利用することができます。</p>
<p>昔はPowerPointファイルを読み書きするAPI群である<a href="http://poi.apache.org/hslf/index.html">HSLF</a>はなかったので、POIで検索するとEXCELファイルを読み書きする<a href="http://poi.apache.org/hssf/index.html">HSSF</a>が中心に紹介されているようです。</p>
<p>今回はHSLFを使ってPowerPointファイルの中にある文字列を出力する簡単なサンプルを書いてみました。</p>
<pre class="code"><code>package net.unoh.ppt2text;

import java.io.FileNotFoundException;
import java.io.IOException;

import org.apache.poi.hslf.HSLFSlideShow;
import org.apache.poi.hslf.model.Shape;
import org.apache.poi.hslf.model.Slide;
import org.apache.poi.hslf.model.TextBox;
import org.apache.poi.hslf.usermodel.SlideShow;

public class PPT2Text {

    public static void main(String[] args) {

        if (args.length != 1) {
            printUsage();
            System.exit(1);
        }

        try {

            SlideShow slideShow = new SlideShow(new HSLFSlideShow(args[0]));
            Slide[] slides = slideShow.getSlides();

            for (int i = 0; i &lt; slides.length; i++) {

                Shape[] shapes = slides[i].getShapes();

                for (int j = 0; j &lt; shapes.length; j++) {

                    if (shapes[j] instanceof TextBox) {
                        TextBox shape = (TextBox)shapes[j];
                        String text = shape.getText();
                        if (text != null) {
                            System.out.println(text);
                        }
                    }

                }
            
            }

        } catch (FileNotFoundException e) {
            System.err.println("File not found");
        } catch (IOException e) {
            System.err.println("IO error");
        }

    }
    
    public static void printUsage() {
        System.out.println("Usage: ppt2text filename");
    }

}</code></pre>
<p>POIのクラスファイルを<a href="http://www.apache.org/dyn/closer.cgi/poi/">ダウンロードページ</a>から取得してビルドしています。</p>
<p>これで例えばLinuxのコンソール上からPowerPointファイルを読むというニッチなことも、以下のようにjarファイルを実行するだけで可能です。</p>
<a href="http://photozou.jp/photo/show/784/8045948"><img src="http://art7.photozou.jp/pub/784/784/photo/8045948.png" alt="ppt2text" width="401" height="181" style="border:0" /></a><br /><a href="http://photozou.jp/photo/show/784/8045948">ppt2text</a> posted by <a href="http://photozou.jp/mypage/top/784">(C)フォト蔵</a>
<p><a href="http://poi.apache.org/hslf/how-to-shapes.html">Busy Developers' Guide to HSLF drawing layer</a>にサンプルコードがまとまっていて参考になります。</p>
<p>Microsoft Officeのファイルを扱う実装はJava以外にもありますが、POIも良い選択肢の一つになるのではないでしょうか。</p>]]>
        
    </content>
</entry>
<entry>
    <title>Amazonの商品個別ページのURLからASINを取得する</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2008/03/amazonurlasin.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1080" title="Amazonの商品個別ページのURLからASINを取得する" />
    <id>tag:labs.unoh.net,2008://2.1080</id>
    
    <published>2008-03-24T15:08:18Z</published>
    <updated>2008-03-24T15:11:20Z</updated>
    
    <summary>isogawaです。 題名のままのコードを書く用事があったので、できたものを晒します。とはいえ、ググれば多くの先達が既にさまざまなコードを書いておられ、目新しいものではないんですが。ついでなんで、大昔の「ISBN=～」を含めて、自分の知ってるURLのパターンを洗いなおしてみました（それでも、まだ他のパターンがありそうな気がしますが…）。 例えば、「The Elements of Style」という書籍の個別商品URLとして思いつくものには、以下のようなパターンがあります（細かいバリエーションは適宜省略）。 http://www.amazon.co.jp/exec/obidos/ASIN/020530902X http://www.amazon.co.jp/o/ASIN/020530902X http://www.amazon.co.jp/exec/obidos/ISBN=020530902...</summary>
    <author>
        <name>unoh</name>
        
    </author>
            <category term="Tips" />
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[<p>isogawaです。</p>

<p>題名のままのコードを書く用事があったので、できたものを晒します。とはいえ、ググれば多くの先達が既にさまざまなコードを書いておられ、目新しいものではないんですが。ついでなんで、大昔の「ISBN=～」を含めて、自分の知ってるURLのパターンを洗いなおしてみました（それでも、まだ他のパターンがありそうな気がしますが…）。</p>

<p>例えば、「The Elements of Style」という書籍の個別商品URLとして思いつくものには、以下のようなパターンがあります（細かいバリエーションは適宜省略）。</p>

<ul>
<li><a href="http://www.amazon.co.jp/exec/obidos/ASIN/020530902X">http://www.amazon.co.jp/exec/obidos/ASIN/020530902X</a></li>
<li><a href="http://www.amazon.co.jp/o/ASIN/020530902X">http://www.amazon.co.jp/o/ASIN/020530902X</a></li>
<li><a href="http://www.amazon.co.jp/exec/obidos/ISBN=020530902X">http://www.amazon.co.jp/exec/obidos/ISBN=020530902X</a></li>
<li><a href="http://www.amazon.co.jp/exec/obidos/ISBN%3D020530902X">http://www.amazon.co.jp/exec/obidos/ISBN%3D020530902X</a></li>
<li><a href="http://www.amazon.co.jp/o/ISBN=020530902X">http://www.amazon.co.jp/o/ISBN=020530902X</a></li>
<li><a href="http://www.amazon.co.jp/exec/obidos/tg/detail/-/020530902X">http://www.amazon.co.jp/exec/obidos/tg/detail/-/020530902X</a></li>
<li><a href="http://www.amazon.co.jp/exec/obidos/tg/detail/-/Elements-Style/020530902X">http://www.amazon.co.jp/exec/obidos/tg/detail/-/Elements-Style/020530902X</a></li>
<li><a href="http://www.amazon.co.jp/o/tg/detail/-/020530902X">http://www.amazon.co.jp/o/tg/detail/-/020530902X</a></li>
<li><a href="http://www.amazon.co.jp/o/tg/detail/-/Elements-Style/020530902X">http://www.amazon.co.jp/o/tg/detail/-/Elements-Style/020530902X</a></li>
<li><a href="http://www.amazon.co.jp/gp/product/020530902X">http://www.amazon.co.jp/gp/product/020530902X</a></li>
<li><a href="http://www.amazon.co.jp/gp/product/product-description/020530902X">http://www.amazon.co.jp/gp/product/product-description/020530902X</a></li>
<li><a href="http://www.amazon.co.jp/dp/020530902X">http://www.amazon.co.jp/dp/020530902X</a></li>
<li><a href="http://www.amazon.co.jp/Elements-Style/dp/020530902X">http://www.amazon.co.jp/Elements-Style/dp/020530902X</a></li>
<li><a href="http://www.amazon.co.jp/Elements-Style/dp/product-description/020530902X">http://www.amazon.co.jp/Elements-Style/dp/product-description/020530902X</a></li>
</ul>

<p>スキームがhttpの場合とhttpsの場合、ホストの「www.」の有無、及び日本のサイトについては「.co.jp」と「.jp」の両ドメイン名で、表示内容に違いは見られないようです。</p>

<p>なお、ASIN以降スラッシュに続けて、アソシエイトIDを初めとした各種パラメータが付与されますが、必ずASIN以降であるようなので、ここでは無視します。</p>

<p>というわけでコードですが。以下はJavaScriptですが、やってることはパスをバラして正規表現で評価してるだけなので、他の言語にもサクっと置き換えられるかなと。</p>]]>
        <![CDATA[<pre class="code"><code>/**
 * Retrieves ASIN value from the given Amazon product page URL.
 *
 * @param  string   url   Amazon product page URL
 * @return string         ASIN value contained in the given URL
 *                        Returns empty string if no match
 */
function getAsinFromUrl(url) {
  if (!/^https?:\/\/(?:www\.)?amazon\.(?:com|ca|co\.uk|de|co\.jp|jp|fr|cn)\/(.+)$/.test(url)) {
    return '';
  }
  var path = RegExp.$1;
  var paths = path.split('/');
  if (paths[0].toLowerCase() == 'exec') {
    paths = paths.slice(1);
  }
  if (paths.length &lt;= 1 || paths[1] == '') {
    return '';
  }
  switch (paths[0]) {
  case 'OBIDOS':
  case 'obidos':
  case 'o':
    /**
     * May match the following examples:
     * - http://www.amazon.co.jp/exec/obidos/ASIN/020530902X
     * - http://www.amazon.co.jp/o/ASIN/020530902X
     */
    if (paths[1].toLowerCase() == 'asin' &amp;&amp; paths.length &gt;= 3 &amp;&amp; paths[2] != '') {
      return paths[2];
    /**
     * May match the following examples:
     * - http://www.amazon.co.jp/exec/obidos/ISBN=020530902X
     * - http://www.amazon.co.jp/exec/obidos/ISBN%3D020530902X
     * - http://www.amazon.co.jp/o/ISBN=020530902X
     */
    } else if (/^isbn(?:=|%3d)(.+)$/i.test(paths[1])) {
      return RegExp.$1;
    /**
     * May match the following examples:
     * - http://www.amazon.co.jp/exec/obidos/tg/detail/-/020530902X
     * - http://www.amazon.co.jp/exec/obidos/tg/detail/-/Elements-Style/020530902X
     * - http://www.amazon.co.jp/o/tg/detail/-/020530902X
     * - http://www.amazon.co.jp/o/tg/detail/-/Elements-Style/020530902X
     */
    } else if (paths[1].toLowerCase() == 'tg'
      &amp;&amp; paths.length &gt;= 5
      &amp;&amp; paths[2].toLowerCase() == 'detail'
      &amp;&amp; paths[3] == '-') {
      if (/^[0-9a-zA-Z]{10}$/.test(paths[4])) {
        return paths[4];
      } else if (paths.length &gt;= 6 &amp;&amp; paths[5] != '') {
        return paths[5];
      }
    }
    break;
  /**
   * May match the following examples:
   * - http://www.amazon.co.jp/gp/product/020530902X
   * - http://www.amazon.co.jp/gp/product/product-description/020530902X
   */
  case 'gp':
    if (/^gp\/product(?:\/product-description)?\/([0-9a-zA-Z]{10})/.test(path)) {
      return RegExp.$1;
    }
    break;
  /**
   * May match the following examples:
   * - http://www.amazon.co.jp/dp/020530902X
   * - http://www.amazon.co.jp/Elements-Style/dp/020530902X
   * - http://www.amazon.co.jp/Elements-Style/dp/product-description/020530902X
   */
  default:
    if (/\/?dp(?:\/product-description)?\/([0-9a-zA-Z]{10})/.test(path)) {
      return RegExp.$1;
    }
  }
  return '';
}</code></pre>

<p>なお、個別商品ページを表示した状態でブックマークレットとかでASINを拾うとか、ページのDOMが利用できる状況なら、URLをいぢくるよりdocument.getElementById('ASIN')のほうが確実なのは、これもググればさまざまなに述べられている通りなので、念のため。</p>]]>
    </content>
</entry>

</feed> 

