Andrew Gerrand

    2010年4月27日

    ここでは、Goのインターフェースを使用して、既存のコードをリファクタリングし、より柔軟で拡張可能にする方法の例を示します。元々、標準ライブラリのRPCパッケージgobというカスタムワイヤフォーマットを使用していました。特定のアプリケーションでは、JSONを代替のワイヤフォーマットとして使用したいと考えました。

    最初に、既存のワイヤフォーマットの機能を説明するためのインターフェースのペアを定義しました。1つはクライアント用、もう1つはサーバー用です(以下に示します)。

    1. type ServerCodec interface {
    2. ReadRequestHeader(*Request) error
    3. ReadRequestBody(interface{}) error
    4. WriteResponse(*Response, interface{}) error
    5. Close() error
    6. }

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

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

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

    に変わりました。

    次に、元の機能を再現するためのトリビアルなgobServerCodecラッパーを書きました。そこからjsonServerCodecを構築するのは簡単です。

    クライアント側にも同様の変更を加えた後、RPCパッケージで必要な作業はこれが全てでした。この全体の作業は約20分かかりました!新しいコードを整理し、テストした後、最終変更セットが提出されました。

    JavaやC++のような継承指向の言語では、明らかな道はRPCクラスを一般化し、JsonRPCおよびGobRPCのサブクラスを作成することです。しかし、このアプローチは、その階層に対してさらに一般化を行いたい場合には厄介になります。(たとえば、代替のRPC標準を実装する場合など)。私たちのGoパッケージでは、概念的によりシンプルで、書くまたは変更するコードが少なくて済むルートを選びました。

    コードベースにとって重要な品質はメンテナンス性です。ニーズが変化するにつれて、コードを簡単かつクリーンに適応させることが不可欠です。そうしないと、扱いにくくなってしまいます。私たちは、Goの軽量で構成指向の型システムが、スケールするコードを構造化する手段を提供すると信じています。