私はクライアント/サーバーアプリケーションと非常に簡単な通信プロトコルを持っています。より正確には、サーバーが送信する一連のコマンドと、クライアントが実行できる一連の要求です。次のようにネットワークメッセージ用のクラスアーキテクチャを設計する
考え方は次のとおりです。
コマンドがサーバによって行われた場合、クライアントはそれを実行する必要があります。 要求が行われると、サーバーはアクセス許可をチェックし、すべてがOKであれば要求を許可します。
アプリケーションは、C++で書かれていると私は少し通信プロトコルのこの種のためのアーキテクチャを設計捕まってしまいました。コマンド/リクエストが最初のパラメータがメッセージの名前であるタブ区切りの文字列であると仮定して、すべてのメッセージをハッシュテーブルに格納し、必要に応じてそれらを取得するMessageManager
クラスを作成する予定でした。ここに問題があります:
typedef std::vector<std::string> ArgArray;
class Request : public Message
{
public:
Request(const char *name) : Message(name) { }
#ifdef CLIENT
/** problem here **/
virtual void make(...) = 0;
#elif defined SERVER
virtual void grant(const Client &c, const ArgArray ¶ms) const = 0;
protected:
virtual void checkPermissions(const Client &c, const ArgArray ¶ms) const = 0;
#endif
};
さまざまなメッセージが異なる引数で構築されるため、実際には完全なインターフェイスを作成できません。たとえば、いくつかのメッセージには単純な文字列が必要な場合がありますが、他のメッセージでは数値データが必要な場合があります。これは物事を複雑にして、デザインを少しばっちりとさせます...私はインターフェイス定義からmake()
を除外することによって問題を解決しなければならず、単純に私が行う各要求に対して異なるmake()
を追加する必要があります。また、別のリクエストへのポインタを1つのコンテナに格納する場合は、Request
が多型ではないため、dynamic_cast
を使用することはできません。明らかな(曖昧な)解決策は、make(int n, ...)
の定義を使用し、stdarg.h
を使用して異なる引数を抽出しますが、これはプログラマーにとって安全でないと紛らわしいと考えています。
私の考えには明らかに設計上の欠陥があります。私は既に念頭に置いて解決策を持っていますが、私はちょうど不思議です。だから、人々はどのようにこの問題に取り組んでいますか?どのような種類のオブジェクトアーキテクチャを使用しますか?この問題を解決する簡単なアプローチはありますか?できるだけシンプルにし、実際のプロトコルをそのまま維持すること(タブ区切りの文字列で、どのメッセージであるかを示す第1パラメータ付き)以外は、特別な要件はありません。
私は心の中で持っていたソリューションの一種です。実際の解析と実行を分けてください。私。作成された各メッセージにはシリアライズ可能な構造があり、それ以降は引き継がれます。次に、構造体のすべてのメンバーであるため、引数を取らない仮想関数 'make()'を作成することができます。 :) – sneg
申し訳ありません。私が 'make()'を書いたとき、私は間違いを犯しました。私は要求/コマンドを実行する実行機能を意味しました。 – sneg
もう一つ考慮すべきことは、Visitorのパターンを解析してコードをシリアライズすることです。あなたが扱う必要があるメッセージクラスの定義済みのセットがあるとき、それは素晴らしい仕事をしました。 – oscarkuo