IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

[Archi. Logicielle] Design Pattern Strategy - Incrustation dans un projet


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert Avatar de Er3van
    Homme Profil pro
    Architecte Logiciel
    Inscrit en
    Avril 2008
    Messages
    1 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte Logiciel
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2008
    Messages : 1 430
    Par défaut [Archi. Logicielle] Design Pattern Strategy - Incrustation dans un projet
    Hello,

    Pas de question spécialement sur le pattern en lui-même, simplement une question pour avoir votre avis sur le positionnement des classes dans l'architecture logicielle. (Et cela permettra également à ceux qui ne connaissent pas ce pattern de l'aborder)

    Ce design pattern strategy sera utilisé par un WebService pour déterminer sa stratégie de "data mining" (c'est un bien grand mot, mais bon...).
    Pour faire simple, disons que c'est la donnée qui détermine la stratégie (si c'est le produit X, alors le pré-traitement sera ça, le post traitement ça), avec un traitement commun à tous les produits.
    Je précise que c'est une évolution d'un existant, où il n'y avait à l'époque qu'une seule stratégie (et donc pas de pattern en place), et que le WebService s'incorpore dans un ensemble plus grand, il utilise donc des couches métiers communes à d'autres applications.

    Grossièrement, voici l'algorithme :
    > Réception d'une requête XML
    > Analyse de la requête
    > Recherche du type de la donnée (accès à la base)
    > Choix de la stratégie
    > Pré-traitement, si nécessité par la stratégie (accès à la base ou non)
    > Traitement commun (accès à la base)
    > Post-traitement, si nécessité par la stratégie (accès à la base ou non)
    > Incorporation des données dans un XML
    > Envoi de la réponse XML

    Pattern Strategy en lui-même, je pense faire une arborescence de ce type là :
    - une classe DataMining qui définie le traitement commun
    - une interface DataMiningStrategy
    - deux classes ConcreteStrategyProductX et ConcreteStrategyProductY, qui définiront leurs pré et post traitement, et qui héritent de DataMining pour utiliser le même traitement commun
    - une classe Context avec une référence vers DataMiningStrategy, et qui exécutera selon le produit, l'une ou l'autre des ConcreteStrategy


    De plus, une contrainte projet impose l'utilisation d'une architecture logicielle propre à ma boite, qui organise la solution en briques techniques (proxy, modèles génériques d'exception, de logs, mapping à la base, etc...), briques "métier" (comme des Beans en Java) qui définissent chacune des aspects métiers (potentiellement sur les mêmes entités qu'une autre brique métier) et en briques applicatives, qui s'appuyent sur les briques techniques et métier.

    Donc, ma question dans tout ça...

    Etant donné que certaines des classes du Design Pattern Strategy utilisent des couches métiers, mais qu'elles définissent la stratégie propre au WebService, dans quelle brique logicielle doivent-elles être définies ?

    - Dans le WebService
    ou
    - Dans une brique technique, sur lequel le WebService a une référence
    ou
    - Dans une brique métier, sur lequel le WebService a une référence

    Habituellement, je pense que c'est fait au sein de l'application, donc ici du WebService, sauf que pour moi ça viole le découpage qui a été fait au niveau logiciel, dans le sens ou le Design Pattern contient une implémentation métier.

    Je penche donc plutôt sur la troisième hypothèse, même si j'emets une réserve du fait qu'elle ne sera utilisée que par une seule brique applicative, et du fait que ça ne soit pas vraiment une brique métier, dans le sens où elle est modelée par le Design Pattern, et ne suit plus la découpe de la guideline originelle...


    Si ça manque de détail n'hésitez pas !

    Merci d'avance !

    PS : Quand le code sera fait je posterai l'implémentation du Design Pattern Strategy pour ceux que ça intéresse. Je ne sais pas s'il existe pas déjà un tuto sur DVP en C# là dessus...

  2. #2
    Membre Expert Avatar de Er3van
    Homme Profil pro
    Architecte Logiciel
    Inscrit en
    Avril 2008
    Messages
    1 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte Logiciel
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2008
    Messages : 1 430
    Par défaut
    Voici le début de l'implémentation :

    La classe mère :
    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    public class DataMiningProcess
        {
            public virtual void PreProcess()
            {
                // jamais appelée, sinon c'est un problème...
                throw new NotImplementedException("DataMiningProcess.PreProcess");
            }
     
            public virtual IList<Item> Process(String param1, String param2)
            {
                this.PreProcess();
                IList<Item> itemsList = new List<Item>();
                this.PostProcess();
                return itemsList;
            }
     
            public virtual void PostProcess()
            {
                // jamais appelée sinon c'est un problème...
                throw new NotImplementedException("DataMiningProcess.PostProcess");
            }
        }

    L'interface :
    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    public interface DataMiningStrategy
        {
            void PreProcess();
            IList<Item> Process(String param1, String param2);
            void PostProcess();
        }

    Une des classes filles :
    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    public class ConcreteDataMiningStrategyProductX : DataMiningProcess, DataMiningStrategy 
        {
            #region DataMiningStrategy Members
     
            public override void PreProcess()
            {
                Console.WriteLine("ConcreteDataMiningStrategy.PreProcess - This methode does nothing but who cares ?");
            }
     
            public override IList<Item> Process(String param1, String param2)
            {
                return base.Process(param1, param2);
            }
     
            public override void PostProcess()
            {
                Console.WriteLine("ConcreteDataMiningStrategy.PostProcess - This methode does nothing but who cares ?");
            }
     
            #endregion
        }

    La classe consommatrice dans le WebService :
    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
                        // [...]
                        String Denomination = ProductManager.GetProductDenomination(someKey);
                        DataMiningContext context;
                        // Choose strategy according to product denomination
                        switch (Denomination)
                        {
                            case "ProductX" :
                                context = new DataMiningContext(new ConcreteDataMiningStrategyProductX());
                                break;
                            case "ProductY" :
                                context = new DataMiningContext(new ConcreteDataMiningStrategyProductY());
                                break;
                            default:
                                throw new Exception("Product denomination is not valid");
                        }
                        // Execute the appropriate strategy
                        itemList = context.ExecuteStrategy(param1, param2);
                        // [...]

    Pour info, Item est un objet métier défini par ailleurs.

    EDIT : Réflexion faite, je pense que les appels vers PreProcess et PostProcess seront faits directement depuis la méthode Process.

  3. #3
    Membre Expert Avatar de Er3van
    Homme Profil pro
    Architecte Logiciel
    Inscrit en
    Avril 2008
    Messages
    1 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte Logiciel
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2008
    Messages : 1 430
    Par défaut
    Le code semble bien marcher, et j'ai choisi l'option 3.

    Des commentaires/remarques/améliorations ?

  4. #4
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 193
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 193
    Par défaut
    si j'ai bien suivi, je pense que la classe de base appelle les pre et post process et en effet la meilleure solution, ca ne mélange rien
    et vu que tu fais pré process>process>postprocess, l'encapsulation dans process est tout à fait logique si la classe process a ce qu'il faut pour déterminer les pré et post process à appliquer
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  5. #5
    Membre émérite
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2007
    Messages
    693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juillet 2007
    Messages : 693
    Par défaut
    Bonjour,

    C'est-à-dire : Dans une brique métier, sur lequel le WebService a une référence

    Je n'avais pas vu ton post avant, mais de mon point de vue heureusement que tu as choisi de mettre ça là car c'est purement métier !

    Je ne connaissais pas ce pattern avant de lire ton post mais je trouve que l'implémentation qui en est faite est assez légère à mon goût !

    Si je prends l'exemple de wikipedia, voici ce qui me gêne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
            // une liaison tardive
            switch (météo) {
                case Météo.IlFaitBeau: 
                    kevin.Strategie = new DéfoncerLePontLevisDeFace(); break;
                case Météo.IlYADuBrouillard: 
                    kevin.Strategie = new PasserParLaFaceNord(); break;
                case Météo.IlFaitTropChaudPourTravailler:
                    kevin.Strategie = new AttendreQueLaVilleSeRende(); break;
                case Météo.IlPleut:
                    kevin.Strategie = new SeMarierAvecLaCousineDuDuc(); break;
                default: 
                    throw new Exception("Nan finalement seigneur de la guerre c'est "
                        + "pas cool comme job : vous décidez d'aller élever "
                        + "des chêvres dans le Perigord.");
            }
    Je trouve ça peu élégant et fait perdre un peu de l'intérêt au pattern. Je partirai sur l'idée d'une Factory (remplissant le rôle du new ...()) conditionnelle (remplissant le rôle du switch).

    Cela permettrait notamment de complexifier les conditions de manière transparente par rapport à l'appel et d'ajouter aisément de nouvelles stratégies (faisable si on pousse le bouchon un peu loin) via de la configuration (mais je pars très loin là quand même)...

  6. #6
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    38
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 38
    Par défaut
    J'ai surement loupé un truc, mais pourquoi ta classe de base n'implémente pas directement l'interface. Et puis pourquoi une virtual qui Throw plutôt qu'une abstract ?

  7. #7
    Membre émérite
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2007
    Messages
    693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juillet 2007
    Messages : 693
    Par défaut
    mais pourquoi ta classe de base n'implémente pas directement l'interface
    Car si la classe de base implémente directement l'interface, elle ne pourra avoir qu'une seule implémentation donc qu'une seule stratégie.

    Pour faire une image, je dirais que la classe de base tel qu'implémenter ici, son boulot c'est de savoir quelle stratégie elle a à sa disposition et laquelle utiliser dans quel cas mais par contre elle ne veut rien savoir de comment se déroule la stratégie.

    En gros, elle sait que toutes les stratégie vont l'amener au résultat souhaité mais elle s'en fout de comment on va s'y prendre.

    EDIT : ah ben je m'enflamme !

  8. #8
    Membre Expert Avatar de Er3van
    Homme Profil pro
    Architecte Logiciel
    Inscrit en
    Avril 2008
    Messages
    1 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte Logiciel
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2008
    Messages : 1 430
    Par défaut
    Citation Envoyé par ostenhard Voir le message
    Je trouve ça peu élégant et fait perdre un peu de l'intérêt au pattern. Je partirai sur l'idée d'une Factory (remplissant le rôle du new ...()) conditionnelle (remplissant le rôle du switch).

    Cela permettrait notamment de complexifier les conditions de manière transparente par rapport à l'appel et d'ajouter aisément de nouvelles stratégies (faisable si on pousse le bouchon un peu loin) via de la configuration (mais je pars très loin là quand même)...
    Merci pour ton input. Je prends note mais je ne sais pas si je vais avoir le temps d'implémenter "en plus" le pattern factory. Mais c'est vrai qu'ils vont bien ensemble !

    Citation Envoyé par nevaram
    J'ai surement loupé un truc, mais pourquoi ta classe de base n'implémente pas directement l'interface. Et puis pourquoi une virtual qui Throw plutôt qu'une abstract ?
    Parce que la classe mère, DataMiningProcess, n'est pas une stratégie.
    EDIT : Pour l'abstract je réponds plus bas

Discussions similaires

  1. Quels design patterns a utilisé dans mon cas?
    Par abdou32 dans le forum Design Patterns
    Réponses: 3
    Dernier message: 02/11/2009, 20h56
  2. Réponses: 4
    Dernier message: 22/12/2004, 14h28

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo