0 votes

Refonte de deux niveaux de déclarations Switch

J'ai hérité d'une base de code qui fait un usage intensif des instructions switch (C#, FWIW) pour piloter une certaine logique. Il s'agit d'une application web multi-tenant où un ensemble d'instructions switch concerne l'affichage du contenu et l'autre concerne les liens vers les fonctionnalités, du moins dans la plupart des cas.

J'ai l'opportunité de refactoriser, donc je prends les déclarations de changement liées au contenu et je prévois de créer une classe Content de base avec une méthode Render(), puis de mettre en place des enfants spécifiques pour les types qui ont besoin de surcharger l'implémentation de base.

Mais il y a de rares cas où le rendu HTML est basé sur le type de contenu et le locataire spécifique et je ne veux pas avoir toutes les nouvelles méthodes Render() avec exactement le même problème que j'ai commencé. Existe-t-il un modèle qui puisse aider dans ce type de situation ?

Je vois quelques autres questions similaires sur SO, mais je ne sais pas comment appliquer les réponses ici.

1voto

jkndrkn Points 2211

Désolé, mes compétences en matière de conception OOP sont un peu rouillées. Vous pouvez remercier les macros Lisp pour cela ;]

Peut-être que l'utilisation de deux classes d'usine fonctionnerait ?

Le constructeur de la classe Content() accepte les variables $content_type et $feature. Le constructeur renvoie ensuite une instance d'une sous-classe Content() contenant une propriété initialisée à une instance d'une sous-classe Feature() générée par la classe usine Feature() en utilisant la valeur de $feature pour sélectionner la sous-classe appropriée. Lorsqu'une méthode render() de la sous-classe Content() est appelée, cette méthode render() peut inclure un appel à une méthode de la fabrique Feature() qui peut compléter ou poursuivre le traitement des données générées par la méthode render(). Dans les cas où un traitement supplémentaire via les méthodes Feature() n'est pas nécessaire, vous pouvez simplement ne pas faire appel à ces méthodes.

1voto

thedeeno Points 12553

Je crois que je te comprends. Ce que je ferais, c'est ceci :

Créer une classe pour gérer le flux de contrôle du rendu :

class Renderer
{
    Tenant _tenant;

    void Render(ContentType type)
    {
        switch (type)
        {
            case ContentType.JSON: 
                _tenant.RenderJSON();
                break;
            default:
                _tenant.RenderHTML();
                break;
        }
    }
}

Créez ensuite une super classe pour le locataire :

class Tenant
{
    virtual void RenderJSON() { ... };
    virtual void RenderHTML() { ... };
}

Enfin, créez des sous-classes pour les éléments spécifiques au locataire :

class JoeBlow : Tenant
{
    override void RenderJSON() { // joe blow's json };
}

Vous devriez ainsi obtenir un beau modèle :

  • 1 classe par locataire (ce qui est bien puisque vous dites que le comportement change en fonction du locataire)
  • 1 super classe pour mettre en place un comportement commun (pour tous les locataires)
  • 1 endroit où votre contentType est résolu dans la méthode de rendu.

L'ajout d'un nouveau type de contenu est simple : Il suffit de mettre à jour le commutateur (1). Si nécessaire, vous pouvez ajouter une nouvelle méthode à la super-classe et ajouter aux sous-classes une gestion spécifique du nouveau type de contenu.

L'ajout d'un nouveau locataire est également facile. Il suffit de les sous-classer.

C'est bien d'avoir des interrupteurs, mais si vous les répétez, il y a quelque chose qui ne va pas, je pense.

0voto

DerrickH Points 11

Dans la mesure du possible, vous pourriez abstraire les rares différences qui se produisent en fonction du type de contenu et créer ensuite un ensemble de rendus par locataire avec des objets d'aide par type de contenu. Cela transforme le problème en un problème n+m au lieu d'un problème n*m. Où n et m sont respectivement le nombre d'utilisateurs et de types de contenu. Vous pourriez alors construire le moteur de rendu comme suit :

// uses a DefaultContentTypeDelegate
IRenderer tenantADefault = new TenantARenderer();
// specify a specific content type helper object
IRenderer tenantAType1 = new TenantARender(new ContentType1Delegate());

Ensuite, vos méthodes de rendu pour le moteur de rendu de chaque locataire pourraient implémenter la méthode Modèle de méthode Modèle et, de temps à autre, appeler une méthode sur le contentTypeDelegate.

class TenantARenderer : IRenderer {
    ...
    public render() {
        // do a bunch of tenant A specific stuff
        this.contentTypeDelegate.doSomeContentTypeSpecificStuff();
        // do some more tenant A stuff
        this.contentTypeDelegate.doSomeOtherContentTypeSpecificStuff();
    }
    ...
}

Cette conception dépend bien sûr de la capacité d'abstraire proprement les différences de type de contenu.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X