The Go Blog

JSON-RPC: インターフェースの物語

Andrew Gerrand
2010年4月27日

ここでは、Go のインターフェースが、既存のコードをリファクタリングして、より柔軟で拡張性のあるものにするのにいかに役立ったかを示す例を紹介します。当初、標準ライブラリのRPC パッケージは、gobと呼ばれる独自のワイヤーフォーマットを使用していました。特定のアプリケーションでは、代替のワイヤーフォーマットとしてJSONを使用したいと考えました。

まず、既存のワイヤーフォーマットの機能を記述するために、クライアント用とサーバー用の2つのインターフェースを定義しました(下図)。

type ServerCodec interface {
 ReadRequestHeader(*Request) error
 ReadRequestBody(interface{}) error
 WriteResponse(*Response, interface{}) error
 Close() error
}

次に、サーバー側では、2つの内部関数シグネチャを、既存のgob.Encoderの代わりにServerCodecインターフェースを受け入れるように変更しました。そのうちの1つは次のとおりです。

func sendResponse(sending *sync.Mutex, req *Request,
 reply interface{}, enc *gob.Encoder, errmsg string)

func sendResponse(sending *sync.Mutex, req *Request,
  reply interface{}, enc ServerCodec, errmsg string)

になりました。その後、元の機能を再現するために、簡単なgobServerCodecラッパーを作成しました。そこからjsonServerCodecを構築するのは簡単です。

クライアント側にも同様の変更を加えた後、これだけで RPC パッケージに対する作業は完了しました。この一連の作業は全体で約20分でした!新しいコードを整理してテストした後、最終的な変更セットがコミットされました。

Java や C++ のような継承指向言語では、RPC クラスを一般化し、JsonRPC および GobRPC サブクラスを作成するのが明らかな方法でしょう。しかし、その階層とは直交するさらなる一般化を行いたい場合(たとえば、代替の RPC 標準を実装する場合)には、このアプローチは厄介になります。Go パッケージでは、概念的に単純で、記述または変更するコードが少ない方法を採用しました。

あらゆるコードベースにとって不可欠な品質は保守性です。ニーズが変化するにつれて、コードが扱いにくくなるのを防ぐため、簡単かつクリーンにコードを適応させることが不可欠です。Go の軽量でコンポジション指向の型システムは、スケールするコードを構造化する手段を提供すると信じています。

次の記事: 新しいトークとチュートリアル
前の記事: サードパーティライブラリ: goprotobuf など
ブログインデックス