「Open棟梁 wiki」は、「Open棟梁Project」,「OSSコンソーシアム .NET開発基盤部会」によって運営されています。
目次 †
概要 †
「通信制御機能」開発の試行錯誤を纏めておく。
- 「通信制御機能」で最も成功したのは、.NETオブジェクトをバイナリ転送する
インターフェイスの汎用性の高いWebAPIである。
- これが実現できたのは、.NETのBinarySerializer? が強力だったため。
例えば、C言語の構造体表現という方法もあるが、これでは、
ネイティブ・オブジェクト表現へのパースが難しくなってしまい利用されない。
- この場合、下位のプロトコルはなんでも良い。何を使用しても問題なく利用できる。
- 問題があるとすれば、通信の相互運用性が無いというところ。
- 次に成功するだろうと思われるのは、REST JSON、JSON-RPCの個別インターフェイス。
- 共通層を経由してB層・D層にアクセスできる点を除いて特に特徴は無い。
- 個別インターフェイス上で特定の型にパースすれば、
共通層ではベースの型やobject型を使用して、個別処理にデータを渡すことができる。
- これにより、インターフェイスの汎用性、通信の相互運用性を両立できるが、
個別インターフェイスの定義と、個別インターフェイス上で特定の型にパースする処理を書くのは面倒。
トレード・オフ †
ソレ以外の方式には、
の問題が有り、使い難い。
サマリ †
通信方式は、以下のように評価できる。
# | 評価項目 | バイナリ転送 | WCF | SOAP | JSON |
1 | インターフェイスの汎用性 | 高 | 高(選択可能) | 基本的には「低」い | 基本的には「低」い |
2 | 通信の相互運用性 | 低 | 低(選択可能) | 基本的には「中」程度 | 基本的には「高」い |
3 | インターフェイス定義 | 任意のバインディング(SOAP、JSONも利用可能) ≒オブジェクト型 | 任意のバインディング(SOAP、JSONも利用可能) データコントラクト≒オブジェクト型 | WSDL | Bean(POJO/POCO)やGenericで構築したobjectの階層構造 これは、パースの仕様が言語を跨いで標準的になっているため。 |
ポイント †
インターフェイスの汎用性 †
要素 †
- WebAPIはなるべく汎用的に定義したい(インターフェイス定義を増やしたくない)。
- この場合、インターフェイス記述、データ記述言語は1つだが、その中を通るデータのフォーマットが可変となる。
- 何かをキーにして、中を通るデータをパースする先の型が明確になればイイだけだが、
これは、インターフェイス記述、データ記述言語の次の段階のobjectの階層構造やbinary表現の話になる事が多いため、
そもそも、汎用性を追求してしまうと、通信の相互運用性に問題が発生するものと考える。
- .NETオブジェクトのバイナリ転送がまさにこれに該当する(通信の相互運用性は無い)。
- SOAPやXML/JSONでも可能だが、SOAPやXML/JSONの通信の相互運用性に問題が発生する。
通信の相互運用性 †
SOAPやXML/JSONなどは通信の相互運用性がある
(≒異なるテクノロジ間をブリッジできる)
インターフェイス記述、データ記述言語であると言える。
データ・フォーマット †
- 異なるテクノロジ間で通信の相互運用性を高めるには、
データ記述言語でデータ・フォーマットが標準化されている必要がある。
- インターフェイスの汎用性を高めるために、さらにその中を通る
データ・フォーマット(objectの階層構造やbinary表現)を規定し出すと、
これは=言語レベルの話になることが多く、相互運用に問題を与える。
パーサー †
また、各言語向けのパーサーが拡充してくる必要がある。
SOAPやXML/JSONなど、標準化されているため各言語向けのパーサーの提供を受けやすい。
- SOAP
- インターフェイス記述言語はWSDL、データ記述言語はXML。
- サーバーがWSDLを生成し、クライアントはWDSLを理解してプロキシを生成する。
- これで相互運用は可能だが、ライブラリがスクリプト言語には供給されなかった。
- このため、最近では、SOAPより、JSONを使用することが多くなってきた。
- XML
- インターフェイス記述言語は無く、データ記述言語としてXMLを使用する。
- XMLパーサーが必要だが、JavaScript?などのスクリプト言語には提供されていないことがある。
- JSONと同じく、REST APIを開発可能であったが、JSONのRESTがデファクトになりXMLのRESTは廃れた感がある。
- JSON
- インターフェイス記述言語は無く、データ記述言語としてJSONを使用する。
- 各言語間でBean(POJO/POCO)、Genericのパースが同じフォーマットで行われる。
- 特にJSONは仕組みが簡単なため、スクリプト言語含めて相互運用が可能になった。
技術的な問題 †
概要 †
- ABCを選択可能にするという野心的な試み。
- A:アドレス
- B:バインディング(トランスポート・プロトコル、エンコーディング)
- C:コントラクト
- サービス・コントラクト
- オペレーション・コントラクト
- データ・コントラクト
- ただ、トレードオフがあって結局の所、良い所取りが出来ないため、
バイナリ転送(汎用性の重視)か、SOAPやJSON(相互運用性の重視)など2択になっている。
- 例えば、WCFのデータコントラクトは、
- オブジェクト表現でデータコントラクトを行うため、そもそも相互運用性は低いと言える。
- このため、通信の相互運用性の低いバイナリ転送や、SOAPには適合した方式だった。
- この中で、SOAPは、唯一、相互運用が可能なバインディングだった。
- しかし、XML/JSONなど、高い通信の相互運用性を目的とした場合、問題を起こした。
バイナリ転送や、SOAP †
バイナリ転送や、SOAPはあまり通信の相互運用性を気にする必要は無いため問題は少ない。
- WCFのTCP/IP(バイナリ・データなので相互運用することが少ない)
- WCFのSOAP(WSDLで相互運用が保証されている。)
XML/JSON †
- しかし、XML/JSONについては、データコントラクトはミスマッチ
- 理由は、データコントラクトを交換できるということは、
- objectの階層構造やbinary表現が一致しているか、
- WSDLのような、インターフェイス記述言語が必要だった。
- このため、初期のパーサーは通信の相互運用性が殆ど考えられていなかった。
- このため、XML/JSONなどのRESTfulなAPIを定義するには、
データコントラクトを使用するWCFは向いていなかった。
- しかし、中期以降は、特にパースの仕様が言語を跨いで標準的なJSONで、
データコントラクト無しでデータの送受信が可能になった。
分析 †
- インターフェイス記述やデータ記述言語を重視すると、
- 相互運用性は高まるが、
- 複雑なオブジェクトを汎用的にパースする処理の実装は難しくなる。
- データコントラクトを重視すると、
- 汎用性は高まるが、
- 問題をインターフェイス記述やデータ記述言語に
移動させているだけなので、相互運用性が犠牲になる。
概要 †
- DataTable?を異なるランタイム間で交換できるようにするために作成した。
- 具体的には、.NET FrameworkとSilverlight間でDataTable?を交換する。
- ランタイムが異なっても、objectの階層構造を維持してデータ交換できる優れモノ
パーサーの問題 †
- しかし、実装量が多く、パーサーを各言語に向けて提供するのは無理があった。
- DataTable?はBean(POJO/POCO)、Genericと比べて廃れた感があるが、
複雑なデータアクセスをするエンタープライズ・システムでは依然として重宝する。
このため、各言語に向けてパーサーが提供されればイイ気もするが、しかし、その兆候は無い
(これは、エンタープライズ・システムを実装する言語が限られているためかもしれない)。
今後の展望 †
- .NET FrameworkとSilverlightに替り.NET Core間のデータ転送に重宝する。
- しかし、.NET Standard2.0からは、DataTable?が供給されているもよう。
このため、XmlSerializer?を使用すれば、.NET Frameworkと.NET Core間で、
データ交換ができるようになるかもしれない。
JSON †
JSONにもトレードオフがある。
インターフェイスの汎用性 †
- インターフェイスを汎用的にする場合、Genericが利用できる。
- Genericにはstringを使用して、必要に応じて個別にパースする。
- インターフェイスの汎用性を高めるために、object型を使用すると、
JSON.NETではJObjectが返るため、手動パースが必要になってしまう。
通信の相互運用性 †
- JSONには、インターフェイス記述言語は無いが、
Bean(POJO/POCO)やGenericのパースの仕様が言語を跨いで標準的になっているので、
Bean(POJO/POCO)やGenericで構築したobjectの階層構造が≒インターフェイス定義になっている。
- このため、通信の相互運用性を高めるには、
Bean(POJO/POCO)やGenericで≒インターフェイス定義するとイイ。
OpenAPI / Swagger †
REST 用のインターフェイス記述言語っぽいが、多分、流行らないと思う。
参考 †