1分でできるほど世の中そんなに甘くない
密結合依存の影響や解決方法を示すため、例としてフロントエンドのWebアプリとバックエンドの金融システムが統合されたオンラインバンキングシステムを想定してみる。
二つのシステムをつなぐ最も簡単な方法はネットワークプロトコルで最もユビキタスなTCP/IPを使うことだ。
以下に、人の名前と金額を引数に与えて預金を個人口座に入れるコードをC#で表す。
String hostName = "finance.bank.com"; int port = 80; IPHostEntry hostInfo = Dns.GetHostByName(hostName); IPAddress address = hostInfo.AddressList[0]; IPEndPoint endpoint = new IPEndPoint(address, port); Socket socket = new Socket(address.AddressFamily, SocketType.Stream, ProtocolType.Tcp); socket.Connect(endpoint); byte[] amount = BitConverter.GetBytes(1000); byte[] name = Encoding.ASCII.GetBytes("Joe"); int bytesSent = socket.Send(amount); bytesSent += socket.Send(name); socket.Close();
このたった10行のコードはEAIツールやRPCツールキットなどの高価なミドルウェアは不要だが、一体このどこが統合において困難になるのだろうか?
プラットフォームに依存しないようにするためにはデータをバイトストリームに変換する必要がある(例ではBitConverter?を使用)が、システムにより内部表現が異なるため.NETなどの32bit上システムで整数(4バイト)を送ったとしても、64bit上の受信システムでは顧客名まで含んだデータ(8バイト)を1つの整数として解釈してしまう。
またビッグエンディアン形式で保存するシステムとリトルエンディアン形式で保存するシステムが混在することもある。
232 3 0 0
この4バイトはリトルエンディアンでは232 + 3 * 2^8 = 1000だが、ビッグエンディアンでは232 * 2^24 + 3 * 2^16 = 3892510720となってしまう。お金がふえるよ、やったね!ジョーくん
さらに問題としてリモートマシンの場所(finance.bank.com)を指定しているので、別ドメインに移動したりマシンに障害が発生したりした場合にコードを変更する必要がある。
TCP/IPはコネクション指向のプロトコルであり、両方のマシンとネットワークが全て同時に使用できる必要があり、どれかに障害があるとデータ送信は行えない。
非常に厳密なデータ形式に依存しているのも問題で、もし引数の数を変更すると送受信ともに変更する必要がある。
最低限の統合ソリューションは高速かつ安価だが、以下の前提条件が互いに成り立たないとならない非常に脆いものでもある。
共通データ形式、非同期通信、変換器などのメカニズムは密結合を疎結合にもたらすが複雑度が増すのが欠点である。そのため、メッセージ指向のミドルウェアインフラを使うことで始めにあげた例と同じくらい簡単に疎結合を実現できる。次のセクションではこのようなミドルウェアを構成するコンポーネントについて説明していく。
疎結合は万能薬か?全てのエンタープライズアーキテクチャにおいて単一の最良の答えはない。疎結合は柔軟性や拡張性をもたらすが、複雑なプログラミングモデルをもたらし設計や構築、デバッグも困難になる。