2009-07-24 8 views
2

J'ai le scénario suivant.Quelle serait l'approche de conception correcte?

J'ai une classe Validator contenant la fonction validate (Command *) qui valide la commande qui lui est passée. J'ai trois classes disons WindowsExecute, SolarisExecute et AIXExecute

La fonction membre execute() dans SolarisExecute et AIXExecute créent directement l'objet Validator et utilisent la fonction validate (Comman *) pour valider la commande avant l'exécution. WindowsExecute est complètement différent et ne possède aucune commande.

Au lieu de cela, il doit valider certaines données de chaîne. Pour ce faire, il existe une classe distincte appelée WindowsValidator héritée de Validator. WindowsExecute :: execute() utilise WindowsValidator au lieu de Validator.

class WindowsValidator : Validator 
{ 
public: 
    validate(const string &xmlData) 
    { 
     // specific validation logic 
    } 
} 

class WindowsExecute 
{ 
public: 
    execute(const string &data) 
    { 
     WindowsValidate v; 
     bool valid = v.validate(data); 

     // some processing depending on 'valid' 
    } 
} 

Ceci est un code existant.

Maintenant, j'ai besoin de faire des validations spécifiques de Solaris et je ne peux donc pas utiliser Validator :: validate (Command *). Suivant la conception actuelle, je devrais créer une nouvelle classe appelée SolarisValidator et avoir ma propre implémentation de validate (Command *).

Je ne suis pas à l'aise avec cette approche. Quelques problèmes/commentaires Je pense:

  1. La classe Validator ne sera utilisée que par AIXExecute. Alors pourquoi avoir une classe de base s'il n'y a plus de logique commune? Il suffit d'avoir trois classes SolarisValidator, AIXValidator, WindowsValidator.

  2. Validator :: validate (Command *) est hérité inutilement dans la classe WindowsValidate. Notez que la signature de WindowsValidate :: validate (string) et Validator :: validate (Command *) sont différentes.

  3. Je devrais rendre Validator :: validate (Command *) virtual si je présente SolarisValidator :: validate (Command *). Cela signifie que j'introduis de l'overhead de pointeurs virtuels même si je n'utilise aucun polymorphisme dynamique. Alors pourquoi ne pas aller aveC# 1 ci-dessus et créer trois classes distinctes?

Quelle serait la meilleure solution pour ce scénario qui serait également extensible à l'avenir? J'utilise C++ pour la mise en œuvre.

Merci d'avance.

-GP

Répondre

2

Il semble que vous avez le concept d'une commande, qui est valide ou non. Selon votre plate-forme, la commande est représentée sous une forme différente. Donc je me suis demandé: pourquoi ne pas créer une interface ICommand avec une fonction "isValid", et faire en sorte que le code de votre plate-forme crée l'objet ICommand approprié pour cette plate-forme. Cela libérerait votre appel "execute" de la création d'un validateur, ce qui le rendrait indépendant de la plateforme. Remarque: ce sous-système d'enveloppement de plate-forme est idéalement conçu en utilisant le modèle Usine.

0

Il semble que vous n'ayez pas de fonctionnalité commune ou même d'interface commune entre vos différentes classes de validateurs. Personnellement, je supprimerais la classe de base commune et la ressusciterais si une véritable interface commune émerge. Essayer de forcer une classe de base commune sans objectif ou avantage clair ne conduira qu'à un code désordonné et/ou à un coût de maintenance sans bénéfice.

À ce stade, vous pouvez supprimer les classes ... Validator et déplacer la fonctionnalité dans une fonction distincte de ... Classes d'exécution. Il semble que la validation soit étroitement liée à l'implémentation des méthodes d'exécution et que vous ayez des difficultés à extraire une interface de validation appropriée.

Essayer de découpler des choses intrinsèquement couplées est souvent un exercice futile. D'un autre côté, les éléments qui ne sont pas intrinsèquement étroitement couplés ne devraient pas être étroitement liés dans la mise en œuvre par le biais d'une mauvaise conception.

Questions connexes