インピーダンスミスマッチング

今日はインピーダンスミスマッチについて語ってみたいと思うのだが、そもそもインピーダンスって何よという所を説明しなければなるまい。

前半、オブジェクト指向には全然関係ない話に見えると思うが、少々辛抱いただきたいw

オームの法則


私が初めて「インピーダンス」という言葉を聞いたのは、大学の軽音楽部(要は、バンド部だ)に所属して、音響理論まわりを勉強している時だった。スピーカーや、マイク等の電子音響機器の入出力端子には、インピーダンスという値(単位はオーム)が示されている*1

学生時代、オームの法則でつまずいた人は多いと思う。おそらく、未だによくわからない人が大半を占めるだろう。E=IR、電圧=電流×抵抗って奴だ。

なんで理解できないのかって、「電流・電圧・抵抗って一体なによ」というイメージが全くできないからだと思う。抵抗はおぼろげながら「電気を流れにくくする何かやな」ってのは分かるかもしれないが。

ちなみに この件を自分は水の流れに具体化してイメージすることによって、理解することに成功した。

電流
水の体積と考える。電流が大きいという場合は、水の量が多い状態をイメージする。
抵抗
ある一定の広さを持った空間、その「狭さ」。狭ければ狭いほど、抵抗が高いと考える。簡単に言えば、水を送るホースが細ければ細いほど、水が通りにくい。つまり、抵抗が高い。
電圧
水圧と考える。上記空間に水を閉じ込めると、水圧が発生する。ただし、その空間内には水しか存在しない。余った隙間を空気が埋めることはない。ちなみに、通常、このような状況が起こると水は気化して水蒸気になったり、凝固して固体になったりするが、あくまでもたとえ話なので、水は常に液体の状態を保ち、液体のまま膨張・圧縮されるものだと考える。

ホースが細ければ細いほど、ホースから勢いよく水が飛び出す。つまり水圧は増す。ただ、ホースがいくら細くても、水の絶対量が少なければホースの先からチョロチョロと水が出てくるだけだ。ほらイメージできた。電気っちゅーわけのわからんもので考えようとするから分からないので、とにかく全部水で考える。

  • 空間が一定のまま水の量を増やすと、圧力が大きくなる。抵抗が一定のまま電流を増やすと電圧が大きくなる。
  • 水の量が一定のまま空間を広くすると、圧力が小さくなる。電流が一定のまま抵抗を減らすと電圧が小さくなる。
  • 水の量を増やした時、圧力を同一に保ちたい場合は、空間を広げなければならない。電流を増やした時、電圧を一定に保ちたい場合は、抵抗を下げなければならない。

っちゅーのがオームの法則だ。

水を使った通信とインピーダンス

さて、この水システムを使って、2つの機器の間で通信をしたい。となったら、何とか情報を水圧に置き換え*2て、水を強く押し出したり弱く押し出したりする。そして受け側には水圧センサーをつけておくことで情報を伝えることができる。ちなみに、常に押しだし続けて、水が一方向に流れっぱなしになるのが直流って奴だ。これだと、送信側の水の在庫はどんどん減っていくし、受信側には水がどんどん貯まってしまう。要らんのにw

というわけで、「そんじゃ、強く押し出す&弱く押し出す じゃなくて 押し出す&引き込む で符号化すりゃいいんじゃね?」つまりマイナスの圧力も使う。そうすると、水は行ったり来たりする。在庫が偏ってしまう心配はない。やったぜ。というのが交流。

あるシンセサイザーの出力端子には、水の出口がある。そしてスピーカーには水の入り口がある。その間をホースでつなげば、音を送れる。かなり分かりやすくなったと思う。

やっとインピーダンスの話に戻る。この機器についている水の出入り口の細さ、これがインピーダンスだ。細さ、つまり抵抗、単位はオーム。インピーダンスの単位もオーム。合点がいく。

で、電子音響の世界には「ロー出しハイ受け」という言葉がある。二つの機器をつなぐ時、ローインピーダンス(低抵抗)の出力端子とハイインピーダンス(高抵抗)の入力端子をつなごうね、という考え方だ。

なぜか? こうすると、情報の伝達効率が良く、ノイズが乗りにくいからだ。

同じ太さの水出入り口をつなげば、正常に情報伝達が出来ることはイメージできていると思う。ここで「細い出力端子」と「太い入力端子」をつないだ状況をイメージしてみる。つまりハイ出しロー受けの状態だ。細い出力から、一生懸命水の押し引きをしている。しかしその水圧は、受け側の端子に届いた時に、「ん? なんか言った?」という程度の微かな水圧変化にしかならない、というイメージはできるだろうか? こういう状態だと、受け側のセンサーの感度をものすごく敏感にしなきゃいけない。つまり効率が悪い。

さらに、この伝達ホースを外から踏みつける、という状況を考える。これがノイズだ。ハイ出しロー受けの状態だと、ノイズの影響が直撃する。センサーが敏感だから、ノイズを拾いまくるのだ。

逆に、ロー出しハイ受けを考えてみる。太い出口から、細い出口に向かって水圧による情報伝達。受け側は、鈍いセンサーを使っても、水圧が大きく変化するので十分に情報を受け取ることができる。ノイズが乗っても、センサーが鈍いので検知しない。

というわけで、インピーダンスマッチングやロー出しハイ受けが重要なのだ。

インピーダンスとO/Rマッパー

さて、前置きが長くてすまん。システム開発において、インピーダンスミスマッチングという言葉が使われるのは、主にO/Rマッパーの分野だ。データベースで使われるERモデルという情報の「出力」が持つインピーダンスと、オブジェクトモデルという情報の「入力(受け側)」が持つインピーダンスが一致しておらず、情報の伝達効率が悪い、という状況を表す言葉だ。

インピーダンスというのは抵抗の単位を持っていた。つまり、情報を入出力するにあたっての「制約」だ。言い換えれば「データ構造」と考えても良い。データベース上で、ERモデルで情報を扱う時のデータ構造(=制約=インピーダンス)。アプリケーション上で、オブジェクトモデルで情報を扱う時のデータ構造(=制約=インピーダンス)。

一般化すれば、「ある環境下で、取り扱いやすいデータ構造」というのが、その環境が持つインピーダンスだ。

確かにデータ構造が違っている(ミスマッチング)から、ERモデルからオブジェクトモデルに情報を伝達しづらい。ここを上手くやってくれるのが O/Rマッパー = データ構造変換器 = インピーダンス変換器 である。

音響の話に戻って申し訳ないが、インピーダンスの高い出力端子とインピーダンスの低い入力端子をつなぎたい時、ダイレクトボックスと呼ばれる機器を間に挟むことで、通信効率を改善できる。wikipediaにも「インピーダンス変換器である」という記述がある。ORMってのはダイレクトボックスと一緒なのねん、と面白い感覚に陥ったものだw まぁ、電子音響とプログラミング、両方を経験しないと味わえない感覚だけどw

様々なインピーダンスミスマッチ

さて、実はここまでが前置きだ。やっと本題w

インピーダンスミスマッチというのは、ERモデルとオブジェクトモデルの間にだけあるものだと思い込んではいまいか?

ORMでは「データベース環境下で取り扱いやすいデータ構造」と「オブジェクト指向で書かれたアプリケーション環境下で取り扱いやすいデータ構造」を解決していた。

しかし、「オブジェクト指向で書かれたアプリケーション環境」というのは、さらに細かく分類できる。例えば…

  • ORMからデータを受け取るという仕事をする環境下
  • UIにデータを渡すという仕事をする環境下

つまり、ORMからデータを受け取りやすいデータ構造(=クラス設計)と、UIにデータを渡しやすいデータ構造(=クラス設計)ってのは異なるよね?

ここにもインピーダンスミスマッチングが存在する。ちなみに、上記のミスマッチを解消しようという試みがSeasar2の「S2Dxo」って仕組みだ。

S2Dxo とは

DXO (Data eXchange Object) とは,JavaBeansとJavaBeansまたはJavaBeansとMapを相互変換 (exchange) することを目的としたオブジェクトです.主な用途としては,プレゼンテーション層のモデル (ページ) とドメイン層のモデル (エンティティ) を相互変換することを意図しています.

Seasar - DI Container with AOP -

上図の「EmployeeとDepartment」がドメイン層のモデル、「EmployeePage」がプレゼンテーション層のモデルにあたる。

上記は一例であって、そのほかにもいろんなインピーダンスが考えられる。XX業務をするときのクラス、YY業務をするときのクラス…。S2Dxoが「ドメイン層のモデル」と一括りにしてしまった中にも、細かいインピーダンスミスマッチが存在する。

インピーダンスの差が小さければ、その場その場でのコーディングをわずかに頑張れば、わざわざ変換器を通してやらなくても良いだろう。変換器を作るコストの方が高い。ただ、ある程度大きなインピーダンスミスマッチがあると、モデルクラスのSRP(単一責任原則)が崩壊してくる。様々な業務に対応すべく、モデルがスマート(多才)になっていき、カオス化する。

まぁ、大げさな例で、モデル自身がO/Rマッパーと同等の機能を内包している、と考えれば、どれだけカオスになるか想像付く。

Employee emp = new Employee(5);
emp.setName(emp.getName() + "ダイスケ");

ってやるだけで、DBのEMPLOYEEテーブルにクエリ掛けて、IDが5の行を引っ張って来て、各カラムを自分のプロパティに設定する。setNameすれば、UPDATEまで掛けてくれるのか? こんなEmployeeクラスの中身は絶対読みたくないw

これらのインピーダンスミスマッチをどう扱うか、というのがモデリングの醍醐味の一つだと思う。何でもかんでも「ミスマッチだ!」と考えて変換器を作りまくるのは愚の骨頂だと思うが、変換器を作った方が良いシーンで「単一のモデルインターフェイス」にこだわってカオス化する、というのも問題だと思う。

経験と勉強が必要だなぁ、と思った今日この頃でありました。(結論それかよ

*1:端子には書かれていかもしれないけど、説明書に書いてあるはず。

*2:符号化