7
votes

Comment gérer différentes versions de protocole de manière transparente en C ++?

Il s'agit d'une question de conception C ++ générique.

J'écris une application utilisant un modèle client / serveur. En ce moment, j'écris le côté serveur. De nombreux clients existent déjà (certains écrites par moi-même, d'autres par des tiers). Le problème est que ces clients existants utilisent toutes des versions de protocole différentes (il y a eu 2 à 3 changements de protocole au fil des ans). P>

Puisque je réécrit le serveur, je pensais que ce serait un grand Il est temps de concevoir mon code de telle sorte que je puisse gérer de nombreuses versions de protocole de manière transparente. Dans toutes les versions de protocole, la toute première communication du client contient la version du protocole, donc pour chaque connexion client, le serveur sait exactement quel protocole il doit parler. P>

Le naïf em> Méthode pour faire cela consiste à joncher le code avec des instructions telles que ceci: p> xxx pré>

Cette solution est assez mauvaise, pour les raisons suivantes: P>

  1. Lorsque j'ajoute une nouvelle version de protocole, je dois trouver partout dans l'arborescence source que ces déclarations sont utilisées et les modifier pour ajouter la nouvelle fonctionnalité. LI>
  2. Si une nouvelle version de protocole vient, et que certaines parties de la version du protocole sont identiques à une autre version, je dois modifier les instructions si elles ont donc lu si (clientProverse == 5 || ClientProverSion == 6 ) code>. li>
  3. Je suis sûr qu'il y a plus de raisons pour lesquelles c'est un mauvais design, mais je ne peux pas penser à eux maintenant. Li> OL>

    Ce que je recherche, c'est un moyen de gérer des protocoles différents intelligemment, en utilisant les caractéristiques de la languette C ++. J'ai pensé à utiliser des classes de modèles, éventuellement avec le paramètre de modèle spécifiant la version du protocole, ou peut-être une héritière de classe, une classe pour chaque version de protocole différente ... p>

    Je suis sûr que c'est un très modèle de conception commune, tant de gens doivent avoir eu ce problème auparavant. P>

    EDIT: > P>

    Beaucoup d'entre vous ont suggéré une héritière héritabilité, avec le plus ancien Version de protocole au sommet, comme ceci (veuillez excuser mon art ASCII): P>

    IProtocol
        ^
        |
    CProtoVersion1
        ^
        |
    CProtoVersion2
        ^
        |
    CProtoVersion3
    


0 commentaires

6 Réponses :


0
votes

J'aurais tendance à utiliser différentes classes pour mettre en œuvre des adaptateurs pour les différents protocoles à la même interface.

Selon le protocole et les différences, vous pouvez obtenir un gain à l'aide de TMP pour les machines d'état ou les détails du protocole, mais générer six ensembles de tout code utilise les six versions de protocole n'en vaut probablement pas la peine; Le polymorphisme d'exécution est suffisant et la plupart des cas, TCP IO est probablement assez lent pour ne pas vouloir tout de manière difficile.


0 commentaires

10
votes

Étant donné que vous devez choisir de manière dynamique quel protocole à utiliser, en utilisant différentes classes (plutôt qu'un paramètre de modèle) pour la sélection de la version du protocole semble être la bonne façon d'aller. Il s'agit essentiellement de la stratégie, bien que les visiteurs seraient également une possibilité si vous vouliez être vraiment élaboré.

Comme ce sont toutes des versions différentes du même protocole, vous pouvez probablement avoir des éléments communs dans la classe de base, puis les différences entre les sous-classes. Une autre approche pourrait être de pouvoir être la classe de base pour la version la plus ancienne du protocole, puis chaque version ultérieure a une classe qui hérite de la version précédente. C'est un arbre d'héritage quelque peu inhabituel, mais la bonne chose à ce sujet est qu'il garantit que les modifications apportées aux versions ultérieures n'affectent pas les versions plus anciennes. (Je suppose que les classes des anciennes versions du protocole se stabiliseront assez rapidement, puis rarement changent.

Cependant, vous décidez d'organiser la hiérarchie, vous souhaiteriez alors choisir l'objet de la version du protocole dès que vous connaissez la version du protocole, puis transmettez-la à vos différentes choses qui doivent "parler" du protocole. < / p>


1 commentaires

En effet, le modèle de stratégie est l'approche la plus probable, vous aimeriez probablement combiner avec une usine qui serait responsable de vous livrer la «stratégie» droite pour la version que vous utilisez.



0
votes

Peut-être trop simplifié, mais cela ressemble à un travail d'héritage? Une classe de base Iprotocol qui définit ce qu'un protocole est (et éventuellement de méthodes communes), puis une mise en œuvre de Iprotocole pour chaque protocole que vous avez?


0 commentaires

0
votes

Vous avez besoin d'une usine de protocole qui renvoie un gestionnaire de protocole pour la version appropriite: xxx

Vous pouvez ensuite utiliser l'héritage pour uniquement mettre à jour les parties du protocole qui ont été modifiées entre les versions. < / P>

Notez que le protocoleHhandler (classe de base) est fondamentalement un motif de straterglange. En tant que tel, il ne devrait pas connaître son propre État (si nécessaire, qui est passé via les méthodes et la stratergy mettra à jour la propriété de l'objet d'état).

Becuase La stratergly ne maintient pas l'état que nous pouvons partager la ProtColhandler entre tout nombre de fils et une telle propriété n'a pas besoin de quitter l'objet d'usine. Ainsi, l'usine doit simplement créer un objet gestionnaire pour chaque version de protocole qu'elle comprend (cela peut même être fait paresseusement). Parce que l'objet d'usine conserve la propriété, vous pouvez renvoyer une référence du gestionnaire de protocole.


0 commentaires

4
votes

J'ai utilisé (et j'ai entendu parler d'autres utilisateurs) des modèles pour résoudre ce problème aussi. L'idée est que vous cassez vos différents protocoles dans des opérations atomiques de base, puis utilisez quelque chose comme Boost :: Fusion :: Vecteur Pour construire des protocoles sur les blocs individuels.

Ce qui suit est extrêmement rugueux (beaucoup d'éléments manquants) Exemple: P> xxx pré>

car la version protocl est dynamique, vous aurez besoin d'une seule instruction de commutation de niveau supérieur pour déterminer quel protocle à utiliser. P>

typedef vector<read_int, write_int, write_int, write_int> Protocol4;


0 commentaires

0
votes

Je vais d'accord avec Pete Kirkham, je pense qu'il serait assez désagréable de maintenir potentiellement 6 versions différentes des classes pour prendre en charge les différentes versions de protocole. Si vous pouvez le faire, il semble que ce soit comme il serait préférable de disposer des versions plus anciennes de mettre en place des adaptateurs pour traduire le dernier protocole afin que vous ne disposiez qu'un seul protocole de travail à maintenir. Vous pouvez toujours utiliser une hiérarchie d'héritage comme indiquée ci-dessus, mais les implémentations de protocole plus anciennes font simplement une adaptation, appelez ensuite le nouveau protocole.


0 commentaires