5

一部のサービスのクライアント インターフェイスを定義するライブラリに取り組んでいます。内部では、ユーザーから提供されたデータを検証し、別のライブラリの Connection クラスを使用して「エンジン」プロセスに渡す必要があります (注: Connection クラスはライブラリのユーザーには知られていません)。私の同僚の 1 人が PIMPL の使用を提案しました。

class Client {
public:
    Client();
    void sendStuff(const Stuff &stuff) {_pimpl->sendStuff(stuff);}
    Stuff getStuff(const StuffId &id) {return _pimpl->getStuff(id);}
private:
    ClientImpl *_pimpl;
}

class ClientImpl { // not exported
public:
    void sendStuff(const Stuff &stuff);
    Stuff getStuff(const StuffId &id);
private:
    Connection _connection;
}

ただし、テストするのは非常に難しいと思います。テストを接続の模擬実装にリンクしたとしても、期待を設定して検証するために簡単にアクセスすることはできません。私は何か不足していますか、それともよりクリーンでテスト可能なソリューションは、インターフェイス + ファクトリを使用しています:

class ClientInterface {
public:
    void sendStuff(const Stuff &stuff) = 0;
    Stuff getStuff(const StuffId &id) = 0;
}

class ClientImplementation : public ClientInterface { // not exported
public:
    ClientImplementation(Connection *connection);
    // +implementation of ClientInterface
}

class ClientFactory {
    static ClientInterface *create();
}

この状況で PIMPL を使用する理由はありますか?

4

3 に答える 3

4

Pimplイディオムを使用する通常の理由は、クラスの実装に対するコンパイル/リンク時間の依存関係を減らすことです(パブリックヘッダーファイルから実装の詳細を完全に削除することにより)。もう1つの理由は、クラスがその動作を動的に変更できるようにすることです(別名Stateパターン)。

2つ目はここでは当てはまらないようで、1つ目は継承+ファクトリでも実現できます。ただし、ご指摘のとおり、後者のソリューションの方が単体テストがはるかに簡単なので、これをお勧めします。

于 2010-07-07T11:54:54.207 に答える
1

GoTW15

GoTW28

ハーブサッターから。始めるための良い指針。

于 2010-07-07T11:54:09.910 に答える
0

はい、これは Pimpl パターンを使用するのに適した場所であり、そのままテストするのは難しいでしょう。

問題は、2 つの概念が相反することです。

  • Pimpl は、クライアントから依存関係を隠すためのものです。これにより、コンパイル/リンク時間が短縮され、ABI の安定性の観点から優れています。
  • 単体テストは通常​​、依存関係への外科的介入に関するものです (たとえば、モックアップの使用)。

しかし、それはあなたが別のものを犠牲にする必要があるという意味ではありません. これは、コードを調整する必要があることを意味するだけです。

Connectionでは、同じイディオムで実装されていたらどうでしょうか?

class Connection
{
private:
  ConnectionImpl* mImpl;
};

そして工場を通して配達されます:

// Production code:

Client client = factory.GetClient();

// Test code:
MyTestConnectionImpl impl;
Client client = factory.GetClient(impl);

このようにして、実装をクライアントに公開したり、ABI を壊したりすることなく、クライアントをテストしながら、接続のテスト実装の核心にアクセスできます。

于 2010-07-07T13:51:19.820 に答える