Andrew Gerrand
2010年4月27日
ここでは、Goのインターフェースを使用して、既存のコードをリファクタリングし、より柔軟で拡張可能にする方法の例を示します。元々、標準ライブラリのRPCパッケージはgobというカスタムワイヤフォーマットを使用していました。特定のアプリケーションでは、JSONを代替のワイヤフォーマットとして使用したいと考えました。
最初に、既存のワイヤフォーマットの機能を説明するためのインターフェースのペアを定義しました。1つはクライアント用、もう1つはサーバー用です(以下に示します)。
type ServerCodec interface {
ReadRequestHeader(*Request) error
ReadRequestBody(interface{}) error
WriteResponse(*Response, interface{}) error
Close() error
}
サーバー側では、既存のgob.Encoder
の代わりにServerCodec
インターフェースを受け入れるように、2つの内部関数のシグネチャを変更しました。そのうちの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の軽量で構成指向の型システムが、スケールするコードを構造化する手段を提供すると信じています。