メイン | 2006年2月 »

2006年1月27日

ソースコードは設計情報

『米マイクロソフト、ウィンドウズの設計情報の一部を公開へ』という記事が新聞に出ていました。

新聞のいう設計情報とは何だろうと思って読んでみると、それは仕様書ではなくユースケース図やらクラス図やらシーケンス図でもなく、ソースコードのことです。

なんだ、新聞正しく認識してるじゃん。というか「ソースコード」を専門用語を使わずに説明しようとすると、ソフトウェアの「設計情報」という言葉を使わざるを得ないわけです。ソースコードは製造物そのものではないのですから当然ですね。

それにもかかわらず、ソースコードを書くこと(=プログラミング)はものづくりでいうところの製造工程にあたる、という誤解はソフトウェアを作る業界では一般的です。

製造工程であるから、完全な設計図があれば人件費が安いところに外注に出してコストダウンができるはずという風に思われてしまうわけです。そして「スキルが必要ない単純労働」と認識されてしまうのです。とある雑誌で「プログラマの年収は明らかにSEよりも低い。それはプログラマは単純労働であり要求されるスキルが低いからである」と書いてあってがっかりしました。

もし誰にも誤読されない(だから安く外注に出せる)ほど厳密で完全な設計図があるとすれば、それはコンパイルして実行できるでしょう。つまりその設計図はソースコードです。

ソースコードは製造されたモノではなく、製造するのに必要十分な情報なのです。設計図と製造工程の指示を一緒にしたようなものでしょうか。ソフトウェアにおける製造工程とは、たとえばCDをプレスする工程になるでしょう。

ソフトウェアの恐ろしいところは、ものすごくいい加減な設計であってもメカニカルな機械と違ってそれなりに動いてしまうことです。欠陥がすぐには表面化しないのですね。

2006年1月26日

C++プログラマから見たRuby

わたしは仕事ではずっとC++を使ってきたので基本的にC++アタマです。その観点からRubyをみるといろいろ面白いですね。Rubyに比べると、Javaは随分C++に近い言語だなあとも感じます。

Abstractなメソッドを定義できない

ちょっとコードを書いてみてまず目につくのは、Rubyには仮想関数がないってことです。JavaやC#のインタフェースに相当するものもありません。

GoFのパターンでいうAbstractFactoryやらStateやらStrategyでは

  1. インタフェースを定義して、
  2. 同じインタフェースを備えているけど振る舞いが異なる複数の実装クラスを用意

します。C++はインタフェースはないけれども、全てのメソッドが純粋仮想であるようなクラスを書けばよいですな。でもRubyではどうすればいいんだ?

Rubyでは型チェックが行われない

型チェックが行われない、というとウソになりますね。実行前(コンパイル時、パース時)にはチェックされないというのが正しいでしょう。

しかしC++プログラマから見ると、感覚的には「Rubyは型チェックが行われない」ように見えます。ほとんどの場面では型よりも、そのオブジェクトがどんなメッセージに反応できるかってことのほうが重要です。

Duck Typing

全く型に関連がなくても同じメソッドを備えていれば、それは事実上同じ型として扱えると考えるのがDuckTypingです。「アヒルのように鳴き、アヒルのように歩くものはアヒルに違いない」といわけです。

StateパターンをRubyで実現しようと思ったら自然とDuckTypingになります。ConcreteState同士は型的には無関係だけど、そのStateに要求されるメソッドを用意しておけばよいわけです。

Rubyなひと(や、Smalltalkなひと)からすれば自然なんでしょうが、C++ばっかりだった私には新鮮な考え方でした。

C++では無理だよなあ...。と思っていたらやり方がありました。テンプレートを使うときはDuckTypingになってますね。

template <T>
class DoSomethingExecutor {
      public execute(T obj) {
            obj.doSomething();
      }
}

Tに要求されるのは、引数のないdoSomething()というメソッドが存在することだけで、型はなんでもOKですね。とはいえテンプレートを駆使して例えばConcreteStateの型がお互い関連のないStateパターンを実現するのは非常に困難ですね。

宣言不要

Rubyでは変数の型宣言が不要、メソッドの引数にも型が不要ですし、インスタンス変数ですら必要になったときに登場させればよいのです。インスタンス変数は@で始まるというルールは潔いです。コードコンベンションでインスタンス変数は小文字mではじめる、なんて決めるよりいいですよね。

attr_accessorは宣言ぽいですが、一行書くだけでC#でいうところのget/setを備えたプロパティが用意されると思うと楽するための宣言と思えます。普通はattr_accessorとかattr_readerを用意すれば十分で、排他とか値変換とかややこしいことがしたくなったらはじめて、C#でいうプロパティっぽいメソッドを用意すればいいわけです。

書いてみてどうよ?

楽です。速いです。モデルを考えるときには抽象クラス(あるいはインタフェース)があるほうが考えやすいですが、実装時に抽象クラスを書く作業は苦痛です。なんの仕事もしないけど型を定義するためだけに書くのですから。

宣言不要なのも楽な要素です。「この引数はどんな型にしよう?」とか悩む前にかけちゃいます。書いてから悩んでもいいわけです。

上にあげた以外でも、Rubyは短く簡潔に書けることが多いです。一番よく使うのがコレクションクラスのeachやらallやらmapにクロージャを渡す書き方です。


convertedArray = anArray.map { | x | MyConverter.convert(x) } 

なんてやると、anArrayの各要素をconvertした結果の配列がconvertedArrayに入ります。イテレータを作ってそれに対して云々、ってやり方がものすごくまどろっこしくなります。

デメリットは?

動的型チェックはC++プログラマには不安です。モジュール内部で使っているメソッドの引数を変更しよう、ってなときはコンパイラのエラーに頼って修正することもありますし。しかしUnitTestが正しく書かれていれば、型の問題はほとんどチェックできるようにも思います。UnitTestが失敗したときに、それが型の問題によるものだ、というのが即座に分からないことはありそうに思いますが。

チーム開発だと他に問題があるかもしれません。どのようなデメリットがあるのか(あるいはないのか)を実感するためには実際に経験をつまないとわからなさそうです。

2006年1月 8日

R言語

前のエントリでグラフ作るのをいったんあきらめましたが、それもつまらないので簡単にグラフ作ってみました。(クリックで拡大します)。

縦軸が1日にdel.icio.usにポストしたブックマーク数、横軸が日付で、期間は昨年1/18日から今日(1/8)までです。横方向に間隔があいているときはdel.icio.usにポストしていない日があることを意味しています。使いはじめてから3日は面白がって遊び、夏ごろは飽きていて、昨年末ぐらいからまた激しく使っている、という感じでしょうか。

グラフつくるのにはR言語をつかってみました。エクセル使ってもいいんだけど、それじゃつまらない。

R言語は統計用言語といわれるS言語のクローンです。学生のとき統計の授業でS言語習ってからは、レポートのグラフはなんでもかんでもSを使って作ってたのですが、もうすっかり言語を忘れてしまっていました。あんなに使ってたのにな。

いろいろググったりして思い出しつつ、なんとかかいたのが次のコード。

d <- read.table("c:\\tmp\m.txt", colClasses=c("Date", "integer"))
plot(d, xlab="date", ylab="count")
lines(d, col="blue")
title("skoji's del.icio.us bookmark count")

m.txtの中身はこのrubyスクリプトの出力です。さっき書いたやつで月ごとに集計しないだけ。

require 'rubygems'
require 'date'
require_gem 'Rubilicious'

user = 'skoji'
pass = 'xxxx'

r = Rubilicious.new(user, pass)
e = r.dates
h = Hash.new
e.sort.each { | date, count |
  puts "#{date}, #{count}"
}

かっこ悪いグラフですけど、4行のコードでここまでできちゃうのがR便利です。Rは統計処理の関数が大量にあるだけじゃなくて、プログラミング言語的にも確かおもしろい特徴があったようなかすかな記憶があります。R勉強しなおして、会社でもグラフ書きにつかってみたりしようかな。

そういえばRで直接webサービスを叩く方法あるのでしょうか。どなたか知っていたらおしえてください。

情報収集

昨年は情報収集の環境が整った年でした。

個人的に一番大きいのがソーシャルブックマークであるdel.icio.usの存在です。

本家ブログで話題にしたのがほぼ一年前。そのときは「タグがつけられるブックマークって便利だなー♪」くらいの気持ちでした。

しばらく使っているうちに、「同じものをブックマークしているひと」が気になり始めました。こーいうのがソーシャルフィルタリングの動機なのかな? 教えて偉い人。

まずは、コメントが気になります。del.icio.usでは(はてなブックマークでも)ブックマークに短いコメントがつけられるのです。それを読んで、なるほどこんな見方をしてるのかと感心してみたり。さらにそのひとのブックマークを辿ると、どれも興味深いことがあります。そういうひとのブックマークはRSSリーダ(わたしはBloglinesを使っています)に登録して、日々ブックマーク更新を観察します。面白いのがあればわたしも横取りしてブックマーク。そしてブックマーク先がブログでかつ面白そうであれば、それもBloglinesに登録。

一年たった今、わたしがdel.icio.usでブックマークしている項目は284項目。意外に少ないですが、きっとどんどん使う頻度が増えているに違いありません。月ごとにどのくらいブックマークをポストしてたか、たどたどしいrubyスクリプトで簡単に調べてみました。del.icio.us APIを叩くのにRubiliciousを使ってます。

require 'rubygems'
require 'date'
require_gem 'Rubilicious'

# del.icio.usのユーザ名とパスワード
user = 'skoji' 
pass = 'xxxxx'

r = Rubilicious.new(user, pass)
e = r.dates
h = Hash.new
e.each { | date, count |
  d = Date.parse(date)
  key = "#{d.year}-#{sprintf("%02d",d.month)}"
  h[key] = count + ((h[key] == nil) ? 0 : h[key])
}

h.sort.each { |month,count| puts "#{month}, #{count}" }

結果はこのとおり

2005-01, 44
2005-02, 22
2005-03, 28
2005-04, 11
2005-05, 65
2005-06, 20
2005-07, 24
2005-09, 16
2005-10, 9
2005-11, 47
2005-12, 155
2006-01, 29

あれー。思ったような結果になりませんでした。先月がすごい多いけど。グラフ化しようという意欲が失せました:)

激しく話がそれましたが、こんなわけでdel.icio.usとBloglinesの組みあわせで、日々いろんな情報が簡単を得られるようになったのが昨年でした(ソフトウェアに関する情報に限られていますが)。

一年たってあらためて振り返ると、多量の情報をそこそこの質で簡単に得られるので、情報収集に没頭してしまう危険を感じます。そのままただただ情報を収集しているだけだと何の役にもたたないタイプの批評家になりさがってしまうだろうなということがひしひしと感じられます。

情報を消費するだけじゃなくて自分でも手を動かさないとね。ありきたりな結論ですみません。

.NET remotingとdRuby

最近.NET Frameworkをいじり始めました。

.NETはVisualStudio .NETがなくても、無料の.NET Framework SDK(と適当なエディタ)だけで開発できるのな。不覚にも知らなかったです。とある事情で、まずは.NET remotingまわりを調査してます。

MSDNだとこのへんから辿れば必要な情報にたどり着けるでしょう。


.NET remoting概要


.NET remotingは、アプリケーション境界・マシン境界を超えた先にあるオブジェクトを透過的に使う仕組みです。C#で.NET remotingは、ちょっと試す分にはとても簡単です。

MarshalByRefObjectを継承したクラスを定義する

これでこのオブジェクトは、アプリケーションドメインを超えて参照渡しできるようになります。
(.NET CLRにはアプリケーションドメインとコンテキストって概念があるみたいだけどまだよく理解してない)

サーバ側とクライアント側に、XMLっぽい構成ファイルを置く

サーバ側は公開するオブジェクト名と公開するURL、クライアント側はアクセスするオブジェクトとそのURLを書きます。通信方法(tcpでバイナリデータ、httpでSOAP)やリモートオブジェクトの生成方法も指定できます(「アクティベーションの方法」という用語が使われてます)。

サーバ側は構成ファイルを読み込んで、ただ起動してればよい

構成ファイルを読み込むメソッドを呼び出して、ただwaitしていれば、リモートオブジェクトへの要求を受け付けるサーバのできあがり。

クライアント側は構成ファイルを読み込んで、リモートオブジェクトをnewする

newするだけでリモートオブジェクトが使えるようになるのだ。実際にリモートオブジェクトが生成されるのは、インスタンスメソッドが呼び出されたときのようです。

とまあこんな感じで、とっかかりは簡単です。

参照渡しと値渡し

さて、起動できるだけじゃだめで、リモートオブジェクトとクライアントの間ではなんらかの情報をやりとりしないといけません。それはメソッドの引数だったり戻り値だったりするわけです。

これらの値もアプリケーションドメイン境界を超えるわけですから、次のいずれかをしないといけません。

  1. MarshalByRefObjectを継承する
  2. serializableにしとく

1.であれば参照渡しになります。2.を行えば値渡しになります。どちらもやらないと、実行時例外になります。両方やると参照渡しになります(MarshalByRefObject自体はserializableになってます)。

とっかかりは簡単だったのに、この辺でもうめんどくさい感が漂ってきます。ぜんぜん透過的じゃないじゃん。リモートから使えるかどうか意識しなきゃだめじゃん。処理系がやってくれればいいじゃん。

まあこのくらいは、最小限のおまじないと思って我慢しないといけないのかな。もし構文上は完全にローカルなオブジェクトと同じように扱えても、リモートオブジェクトかどうかは結局意識しないといけない場面があるでしょうし。

インタフェース

次にひっかかるのが、サーバとなるリモートオブジェクトの型です。

これはクライアントとサーバのインタフェースですから、Interfaceで定義したくなっても不思議じゃありません。

ところがInterfaceで定義しても、クライアント側では具象型を指定しないとリモートオブジェクトを取り出せないみたいです。そのあとInterfaceにキャストして使ってもいいわけですが、そもそも取り出すときは型知らないとダメだってのがちょっといやです。

C#(とCLR)の仕様を考えれば仕方ないかな。

リモートオブジェクトをInterfaceで定義して、クライアント側ではオブジェクトの取り出しの時以外はInterfaceとして扱う、という実装はもちろんできますが。

dRubyだとどうなのさ

型がダイナミックなrubyでのリモート処理にはdRubyってのがあります。ちょっと調べてみたのですが、上記2点の問題については次のことがわかりました

値渡しと参照渡し

rubyそのものと同じく参照渡しのみ。どうしても値渡ししたかったら、オブジェクトをdupする(てかこれは値渡しじゃなくて、コピーの参照渡しですな)。実際に通信路にはどんなデータが乗ってるのかは未調査でよくわかりません。

インタフェース

そもそもrubyにはインタフェースがないです。というか型が動的です。サーバとなるリモートオブジェクトを使うクライアントにとって重要なのはその型ではなくて、送ったメッセージに反応できるかどうかってことだけ。

rubyなのでリモートの型とたとえば「リンク」しとく必要もなく、クライアント側をそのままでサーバ側オブジェクトをぜんぜん違う型にしちゃってもOK。同じメッセージに反応しさえすればいいのですな。

ようやく始めます

以前に宣言したブログをようやくはじめます。

ソフトウェア系技術屋サラリーマンとしてそれなりの時間がたちました。どう考えてももう「若者」の範疇にははいりません。会社の環境は恵まれていますし、それなりにちゃんと働いてきたと思いますが、振り返ってみると次のような反省点があります

会社の外にほとんど出ていない

社内にこもって仕事していてもまったく困りません。技術的な勉強は最小限でも仕事に困りません。中にいると少々技術書読んだだけで勉強した気になってしまうのです

技術系の好奇心を忘れていた(あるいは遠ざけていた)

仕事にする前は趣味だったのでいろんなことに手をだしてましたが、仕事になってからは半分くらいは意識的に遠ざけていました。仕事バカになりたくないという、今にして思えば浅はかな考え方からきてたんですな。

専門以外の分野に興味を持つのは悪いことばっかりじゃないですが、だからって専門分野をおろそかにするこたないですよね。そのうえPC使うときでもgeekっぽく手を動かすのをやめてしまって、パッケージソフトウェアに頼れるところは頼るようになってしまいました。

というわけで遅きに失した感もありますが、技術的なことで遊ぶという習慣をゆっくり復活させようとおもいます。Better late than neverですよ。

このブログについて

ここはこじまさとし(小嶋智)のブログです。ソフトウェア的な何かで遊んだ記録をつけていきます。

以下、架空のよくある質問です。

Q. なぜ「買い物ログ別館」?

A. 前から「買い物ログ」というブログをやっているからです。

Q. でも買い物の話題なんてないじゃん

A. 買い物の話題は「買い物ログ」へどうぞ。

Q. 「買い物ログ」はパンの話題ばっかりじゃん

A. 買い物もしてますよ。