『東京市制概要』

東京市制概要 表紙

ふらりと立ち寄った古書店で昭和十年版『東京市制概要』というのを見つけて買ってきた。結構役に立ちそうだ。

アメリカ系の会社で地図をやっていると「なんでTokyo Cityってないの?」みたいな知識がたまに必要になる。なんでかというと戦時体制がどうたらという話になるけど、この辺の知識は全部二次、三次の資料に基づく受け売りだ。実際のところ府市統合以前がどうで、その後どうなってという正確な知識には欠けている。その辺きちんと知りたいよなーと思っていたところにこの本との出会いである。これだから古書店巡りはやめられない。ぼちぼち読んでいこうと思う。

ぐんまRuby会議01で発表した

ぐんまRuby会議01 で発表してきた。

講演依頼では、「Rubyを通じて見てきた世界、ソフトウェア開発者としての世界観を語ってほしい」とのことであった。そうすると、私がRubyに関わっている理由は2つだ。

  • 個人的にRubyが好きで手に馴染んでいて、これからも継続してほしいから
  • 私が望む世界が実現されるための手段としてRubyは有効であり、Rubyに発展してほしいから

上についていえば好きなものを好きなのにそんなに理由はない。たぶん「プログラマのあるサブセットにとって自然で親しみやすく」というMatzの言語デザイン意図にうまくはめられたというだけだろう。 下についていうと、Rubyはあくまでも手段であり話題の主役ではない。が、Matzの意図についてはMatzがすでに多くを語っているし、私は下について話すことにした。内容は 過去の記事 +α。

ある人の世界観を共有する手段としては、背景にある読書歴というのが欠かせない。またそれらの書籍を通じてよりハイコンテキストな情報を限られた時間で伝達できる。だから今回はいろいろな書籍を挙 げながらMad web programmerと私の望む世界とそこに至るための私自身の取り組みについて話した。

スライドだけ見ても意味不明で、むしろ誤解を招きかねない部分もあるのでスライドの公開予定はない。ただ、その中では次のような書籍に言及した

正直なところ、あの内容を話すのも準備するのもかなりしんどい。それで若干準備し切れていない部分もあった。需要があればまたどこかで話したいと思う。

光目覚まし時計

光目覚まし時計というものを初めて買った。騒音でなく光によって目覚めを図るというものだ。2ヶ月ばかり使っている限りではなかなか好印象だ。OKIROという直球な名前も一周回ってセンスよくすら感じる。定価は39,000円だけど、Amazonではもっと安く売ってたし。

私はもともと睡眠時間が長いたちで、日常生活を送っているとなかなかその体質に足るだけの睡眠時間を毎日とることは難しい。 それで起きられなくて目覚まし時計に頼る訳だけれども、生半可なものでは起きられない。新しい目覚まし時計を買うとしばらくは起きられるが、一週間ぐらい経って新しい機体の操作に慣れると半ば眠ったまま無意識に止めてそのまま寝続けてしまう。そういうわけで、爆音目覚ましだとか音色が豊富な(=その音に慣れるのを防ぐ)目覚ましだとかをいろいろと試してそれなりに効果は得たものの完璧とはいかなかった。

それに比べると現在はOKIROによって次のように改善されている。

  • 指定した時刻よりも少し前から徐々に明るくなって日の出を再現する。明るくなったら起きるという自然な仕組みに基づいているので目覚めがすっきりする。どのぐらいの時間をかけて明るくしていくかは調整できる。
  • 従来は、目覚まし時計の音がまだ眠っている他の人に五月蝿くて迷惑だろうと考えて、早めに音を止めてしまっていた。しかし、それが為に二度寝を防げないことがあった。光であれば音波よりも遥かに指向性が強いので自分にしか影響しない。だから安心して、起き上がって着替えて顔を洗うまで目覚まし時計を放置しておける。目覚まし時計を止めた状態で二度寝という最悪のパターンを避けられる。
  • 個人的には音よりも光の方が目覚めやすい模様。これは体質によるだろうけれども、私は慣れればある程度大きな音が鳴っていても寝られる。けれども1時間明るい光を間近で照らされるとさすがに目が覚める。

ちなみにメーカーは読書灯としても使用可能とか時差ぼけの解消に有効とか謳っているけれども、こちらは試していないのでわからない。Amazonでの評を見ると読書灯としては光がどぎつくて目に厳しいとかいう意見もある。 光の照射面積が狭いという意見にはあまり賛同しない。私も寝相は良くないけれども、上下逆さになるとかベッドから落ちて寝ているような寝相でなければ有効範囲内には頭があるだろうと思われる。

SSD/Linuxをvirsh+kvm+qemuにインストールする

OpenMicroServerカーネルビルド環境としてSSD/Linuxを用意しようと思う。 VMWare用のイメージが提供されているので以前はVMWare Fusionでそれを動かしたことがある。 今回は故あってKVM+qemu環境で動かすことになった。

インストール

サポートサイト からVMWare実行イメージをダウンロードする。zipで固められているのでこれを展開する。

% unzip ssdlinux-1.0.0-20121220.zip

このイメージは3つのディスクイメージから成っている。

% ls
hda.vmdk  hdb.vmdk  ssdlinux.vmx  vmboot.fs

hda.vmdkがルートファイルシステム, hdb.vmdkがホームディレクトリらしい。 それでvmboot.fsがext2のrawイメージで起動用FDのイメージだ。

最初hda.vmdkの中にbootセクタを探そうとしたり、hda.vmdkをqcow2に変換したら動かなかったりといろいろ苦労した。幸いなことにqemuがそのままvmdkを読めるので特に変換はせずに使用する。

VMWare用のssdlinux.vmxを参考に、virsh用に次のようなドメインを定義した。 virt-managerの手も借りたので下記は最小セットではない。

<domain type='kvm'>
  <name>v254</name>
  <description>Build Environment for OMS firmware</description>
  <memory>262144</memory>
  <currentMemory>262144</currentMemory>
  <vcpu>1</vcpu>
  <os>
    <type arch='i686' machine='pc-0.12'>hvm</type>
    <boot dev='fd'/>
    <bootmenu enable='yes'/>
  </os>
  <features>
    <acpi/>
    <apic/>
    <pae/>
  </features>
  <cpu>
  </cpu>
  <clock offset='utc'/>
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>restart</on_reboot>
  <on_crash>restart</on_crash>
  <devices>
    <emulator>/usr/bin/kvm</emulator>
    <disk type='file' device='floppy'>
      <driver name='qemu' type='raw'/>
      <source file='/var/lib/libvirt/images/ssdlinux/vmboot.fs'/>
      <target dev='fda' bus='fdc'/>
      <alias name='fdc0-0-0'/>
      <address type='drive' controller='0' bus='0' unit='0'/>
    </disk>
    <disk type='file' device='disk'>
      <driver name='qemu' type='vmdk'/>
      <source file='/var/lib/libvirt/images/ssdlinux/hda.vmdk'/>
      <target dev='hda' bus='ide'/>
      <alias name='ide0-0-0'/>
      <address type='drive' controller='0' bus='0' unit='0'/>
    </disk>
    <disk type='file' device='disk'>
      <driver name='qemu' type='vmdk'/>
      <source file='/var/lib/libvirt/images/ssdlinux/hdb.vmdk'/>
      <target dev='hdb' bus='ide'/>
      <alias name='ide0-0-1'/>
      <address type='drive' controller='0' bus='0' unit='1'/>
    </disk>
    <controller type='ide' index='0'>
      <alias name='ide0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
    </controller>
    <controller type='fdc' index='0'>
      <alias name='fdc0'/>
    </controller>
    <interface type='bridge'>
      <mac address='52:54:00:99:cf:fe'/>
      <source bridge='br0'/>
      <target dev='vnet0'/>
      <model type='e1000'/>
      <alias name='net0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>
    <serial type='pty'>
      <source path='/dev/pts/1'/>
      <target port='0'/>
      <alias name='serial0'/>
    </serial>
    <console type='pty' tty='/dev/pts/1'>
      <source path='/dev/pts/1'/>
      <target type='serial' port='0'/>
      <alias name='serial0'/>
    </console>
    <input type='mouse' bus='ps2'/>
    <graphics type='vnc' port='5900' autoport='yes' listen='127.0.0.1' keymap='en-us'>
      <listen type='address' address='127.0.0.1'/>
    </graphics>
    <video>
      <model type='cirrus' vram='9216' heads='1'/>
      <alias name='video0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
    </video>
    <memballoon model='virtio'>
      <alias name='balloon0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
    </memballoon>
  </devices>
 </domain>

このXMLをssdlinux.xmlに保存して、

% virsh define ssdlinux.xml

と定義する。

ここでvirt-managerを起動して、GUIからこのドメインを起動した。

シリアルコンソール

さて、何をするにせよvirt-managerのターミナルエミュレーション経由では不便極まる。 デフォルトでDHCPクライアントとSSHdが立ち上がるので、起動してからの作業ならSSHでも良い。でも できればシリアルコンソールから操作したい。

そこでbootディスクをマウントして修正してやることにする。幸いなことに起動ディスクに入っているのは独自のブートローダーとかではなくGRUBなので、勝手は分かっている。

% mkdir /mnt/floppy
% mount -t ext2 /dev/fd0 /mnt/floppy
% cd /mnt/floppy/boot/grub

で、menu.lstの中身を編集してカーネルオプションとしてconsoleの指定を足してやる。

kernel          (hd0,0)/vmlinuz root=/dev/hda1 clock=pit nosmp noapic nolapic console=tty0 console=ttyS0,9600n8

そうしたらアンマウントして再起動でOKだ。

% cd /
% umount /mnt/floppy
% shutdown -r now

virt-managerのView -> Text Consoles -> Serial1を選択すると仮想シリアルポートに起動中のメッセージが出るのが分かる。

これだけだとシリアルからはログインできないのでgettyも設定してやる。Graphical Console VNCの方に戻してログインしてから、

  • /etc/inittab にttyS0のエントリを足す

    c7:2345:respawn:/sbin/agetty ttyS0 9600

  • /etc/securetty のttyS0の行をuncommentする。
  • kill -HUP 1 する。

これでホスト環境で virsh console v254 とすればログインできるようになった。

指定バイト数ぐらいの長さの文字列を読み込む方法

IO から指定したバイト数以内の長さを読み込みたいが、多バイト文字の途中で切れてしまうのは嬉しくないのでそういうときはもう少し読む、というような処理を書きたいことがよくある。 これ、というメソッドは見当たらないので仕方がないから自前でバッファリングしたりしてなんとかしていたのだけど、 IO#gets にそういう機能があることが分かった。

IO#gets はseparatorに nil を指定するとseparateせずにファイルの最後まで読む。それからもう1つ、読み込むバイト数の上限を指定できる。この上限指定は1.9ではもちろん多バイト文字を壊さないようになっている。だからこれらを組み合わせて io.gets(nil, limit) とすると希望の動作をする。行操作でもないのに gets というのはちょっと思いつかないね。

余談

なぜ突然こんなのに気づいたのかというと、今書いているライブラリの関係で IO の挙動を細かくみているのだ。

IO クラスはもともと結構大きなクラスだったのだが、Ruby 1.9になってM17Nが入ったためにエンコーディングがらみでさらに挙動が複雑になった。もはや StringIO みたいに自前で IO もどきのクラスを書くのは容易ではない。そこで IO もどきを作るのを助ける IOable というライブラリを書いている。

性的保守主義と性同一性障害の親和性

性同一性障害の典型例、つまり 自己の性的同一性を明確に認識——身体との間には齟齬があるにせよ自分の人格の中核を成す性別には疑問がない——し、ヘテロセクシュアルで、性的自己認知と性別役割に葛藤が無く、その現象を「性同一性障害」として医療化することを受け入れている人にとって性的保守主義は甘い誘惑だ。

性的保守主義と抑圧

ここで性的保守主義とは、最も典型的な男、女という性に性現象のすべてを回収するものとしよう。彼らは例えば社会での男女の性別役割を自然で当然のものと考える。そこから外れる人を「男なのに○○」「女なのに○○」と自己の属する多数例を基準に評価する。同性愛は彼らに言わせれば例えば「女と寝るように男と寝る者」(レビ記18:22)だ。私が知人の男性同性愛者を見たり資料を読んだりする限りにおいて、これはたぶん不当なことだ。彼らの関係性が「異性愛ではない」のは自明なのに、なんで何もかもが異性愛と同じだと考えるかなぁ。フィクションによくあるような、レズビアニズムに男根主義を期待する心性もそうだし。

さてさて、これら性的保守主義は非典型的な性現象のあり方を抑圧する。それらを不自然であると言って攻撃したり、さも選択肢があるかのように「しかるべき場所にいるならいいけど、堂々と一般の場に出てくるな」という。特定の属性を持つが故に職業選択の自由を剥奪されたり自己の心情を表現することを禁じられたりすることの、どこが選択肢なのか。それはゲットーだ。だから、こうした保守主義は非典型的な性のありかた——性的少数者にとって脅威である。性同一性障害の典型例にとっても、基本的には。

誘惑

ただし、性同一性障害の典型例についてだけはこの抑圧からの逃げ道がある。

もともと性的保守主義は性差の本質主義と親和的だ。男と女は生まれつきある程度違っていてだから女がその母性によって子どもを育てるのは自然なことだし、男のほうが数理的能力に優れていて女のほうが感性が繊細で、とかいう。ここで、現代においてはこうした本質主義は、男女では遺伝子やそこからの脳機能の表現型が異なりそれが支配的なのだという主張に等価だ。この主張はある程度までは真実だろうけれども、本当に数理的能力やら言語能力やら、まして育児家事の分担までここから自然に導かれるのかどうかは議論を要する。性的保守主義はこの議論において高次能力や社会的役割にいたるまでかなりの程度自然に導かれるという立場に親和的なのである。そしてここに性同一性障害が登場する。

高次の精神機能の性差が生物学的必然であるとすれば、逆説的にそこには必ず性同一性障害がなければならない。人間の精神、例えば性的自己認知のような複雑な機構が生物学的過程において一件のエラーもなく形作られるなどということはほぼあり得ないからだ。だから性差が生物学的必然ならばエラーによって必ず性同一性障害は発生し、それは本人の選択ではないし、本人に何の責任もない。 つまり性同一性障害の典型例は、性差本質主義を採用すれば厄介な性的保守派からの否定的な視線から保守派自身の主張によって逃れることができる。さらに保守派にとってもメリットはある。性同一性障害者が自己認知と異なる身体や性的役割を受け入れようとして失敗してきた葛藤の深さをして「男女の本質的差異の大きさ」の論拠とすることができる。「" ブレンダ "を見ろ、性同一性障害もそうだ。ただ表層的な身体の形に合わせて自己同一性と異なる性になろうとしても無理だったじゃないか。男は男、女は女、生まれつき決まってるんだ」というわけだ。

性同一性障害の典型例にとってこれは魅力的な誘いである。得られるものは性的保守主義の抑圧からの脱却である。対価は他の後天的・文化的(である可能性のある)性的少数派あるいは男女にくっきりと線を引くことを阻む例、たとえば趣味的異性装者や性的自己認知が男女いずれでもない人に対して保守主義と一緒になってに石を投げることである。つまり性同一性障害の典型例はある種の本質主義に与することによって、性的少数者への抑圧を放置したままに抑圧される側からする側に移ることができる。

性差の本質主義がどの程度真実かは議論の余地がある。そこで本質主義を主張するのは自由だし、主張する人がたまたま性同一性障害であるということもあるだろう。ただそれは非典型的な性現象に対しての差別性を肯定しないはずだ。そして、性同一性障害者が自己の信念に寄ってではなく単に生きるのに楽だからという理由で保守主義の抑圧に荷担するとしたらそれは悲しいことだ。

良い相続人であるために

翔泳社の「君のために選んだ1冊 ソフトウェア開発の名著」という企画に寄稿を依頼されて、以下のような文章を書いた。ブログ等で公開して良いとのことだったのでここに公開したいと思う。 この企画は他の人の分を読むのが楽しみだ。早く本ができあがらないかな。

ちなみに「 きっと何者にもなれないお前たちに告げる 一冊」というタイトルを最初に思いついたけれど、長く読み継がれる本であってほしいという企画の趣旨を鑑みて流行のネタを使うのは避けた。

yuguiがレガシーコードに絶望した人に贈りたい一冊 - 『レガシーコード改善ガイド』

レガシーコード改善ガイド (Object Oriented SELECTION)

レガシーコード改善ガイド (Object Oriented SELECTION)

振り返るに私のキャリアの大部分はWebアプリケーション業界のレガシーコードとの戦いであった。 多くのシステム開発者にとって全くのゼロからシステムを開発する機会よりも既存のシステムの拡張や保守に携わる機会のほうが多い。それは私にとっても同様であった。

これは恵まれたことであった。私は先人の遺産(=legacy)とともに仕事をしてきた。 現在私が暮らしている業界自体を作り出した黎明期の開発者たち、あるいはやんちゃな天才ハッカーたち、彼らの仕事に触れることができた。 Webアプリケーションの黎明期には出遅れた、論文を書けるような先端技術に通じているわけでもなく、競技レベルの優れたコーダーでもない平凡な私が彼らと同じ開発の場に立つことができた。

ここで問題は、それらのシステムの多くがいわゆるレガシーコードであったということだ。 適切なデザインのシステムにおいて、ある変更をするとどのような影響があり得るかは自明である。あなたがそのシステムを知って数日しか経っていなくとも自信を持って変更を行うことができる。しかしレガシーコードにおいてはそうではない。多くの情報が目に見えない形で埋もれていてそのすべてを知ることを要求し、新参者の貢献を拒んでいる。 レガシーコードは変更のコストを増やすのみならず、見通しが悪いためにリスク評価自体を困難にする。

先駆者や天才たちは前人未踏の領域ですばやく動いて生き延びるためにこのコードベースを作り出した。あるいは抽象化や分割統治、すなわち複雑と多量を凡人が取り扱うための工夫を必要としない故に。 そして先駆者にだけ通じる暗黙知を前提とした拡張や、天才が次の挑戦を求めて旅だった後の担当者による生半可な保守行為がレガシーコードを静かに腐らせていた。 拡張しづらく、複雑で理解に苦しみ、ちょっとした変更が予期せぬ副作用を産むレガシーコードに私は絶望した。 あなたもまたレガシーコードに絶望してきたのではないだろうか。そうでなくともあなたが先駆者や天才でないならば、いつかレガシーコードに出会いその中で開発することだろう。そんなときにどうすれば良いのか。

最悪の選択はレガシーコードに向き合うことをやめて、適当に目に付いたところに拡張を施しては壊れませんようにと祈ることだ。そうした半端な仕事こそがコードをますます腐らせる。それは先人の遺産を食い潰して生きることに等しい。その果てになんの望みがあるだろう。

いっそ初めからやり直したくなることもある。レガシーコードを捨てて新たに同じ機能を書き下ろす。それが適切なときもある。けれども先人の知恵が詰まったそのコードを、大体は完璧な仕様書など存在しないというのにどうやって漏れなく再実装するのか。こうしたリスクを取れないこともある。

だから、朽ちていくレガシーコードに出会ったならばそれを殺さぬまま再生に導かねばならない。 生まれたてのシステムのように適切なモジュール化を施せ。考古学を行なって暗黙の知識を発掘しコードに明示化せよ。 『レガシーコード改善ガイド』はこうした作業をなすための知恵を説く。

まず本書は独特の意味でレガシーコードを定義する。「テストケースの無いコードはレガシーコード」である。これは過激なようだが上手な定義だ。 適切にテストケースを書こうとすれば自ずとシステムは適切にモジュール化され、前述のような欠点はなくなる。つまりまだテストケースのないシステムはそのような欠点を抱えている可能性が高い。

次に、いかにしてテストケースを取り付けるか、それから著者が「テストハーネス」と呼ぶテストでソフトウェアを固定してリファクタリングすることを述べる。 更にいくつもレガシーコードでの開発によくある状況を挙げて対処法を教える。

私はレガシーコードを多く見てどのようなときに何が悪い設計なのかを知った。多くの本を読んでは実践し、あるべきソフトウェアデザインを考えた。 しかしレガシーコードをどうやってあるべき姿に導くのかは手探りを続けていた。そんなときに本書を読んだ。自分のやり方が正しかったことを知ったり、思いつかなかった大胆なやり方に息を呑んだりした。

あなたもレガシーコードに出会うだろう。そんなときに本書から知恵と勇気を得て欲しい。