Esiste un modello di progettazione o un'architettura che si adatta meglio alla mia situazione

2

Supposto che abbia un blocco di codice comune tra due controller in cui l'unica differenza è la classe concreta utilizzata dal blocco. Entrambi i cloni implementano un'interfaccia comune quindi sto usando un'interfaccia per interagire con l'oggetto.

Il blocco di codice è una serie di passaggi che interagiscono con le funzioni della classe concreta. La classe avvolge una libreria di terze parti e gestisce gli errori e i ritiri dalla terza parte libreria chiama api remote.

Credo che questi blocchi siano i principali di DRY, quindi cerco di rifattorizzarli dal controller. Il mio primo pensiero è di aggiungere un'altra funzione all'interfaccia e spostare il blocco su istanza di classe. Tuttavia questo è ancora in violazione di DRY.

Un'altra opzione è quella di spostarlo in una classe di utilità ed eseguire il blocco lì, ma questo non sembra il modo "pulito" per costruire questo.

So che questo blocco non appartiene al controller se deve duplicare lo stesso blocco con una piccola differenza. Questo dovrebbe essere spostato sul livello logistico di business? O c'è un modello di progettazione che può aiutare a risolvere questo invece di spostarlo in una classe di utilità?

Esempio aggiunto Supponiamo che abbia due controller che eseguono la stessa sequenza di passaggi ma differiscono solo dalla classe concreta necessaria.

class Controller1 {
    IWrapper wrapper = Wrapper1();
    public ActionResult DoSequence(){
        wrapper.SetepOne();
        wrapper.StepTwo();
        wrapper.StepThree();
        return View();
    }
}

class Controller2 {
    IWrapper wrapper = Wrapper2();
    public ActionResult DoSequence(){
        wrapper.SetepOne();
        wrapper.StepTwo();
        wrapper.StepThree();
        return View();
    }
}

Voglio spostare il blocco di codice,

wrapper.SetepOne();
wrapper.StepTwo();
wrapper.StepThree();

fuori dai controller quindi sarebbe qualcosa di simile,

class Controller1 {
    IWrapper wrapper = Wrapper1();
    public ActionResult DoSequence(){
        <some class>.RunSequence(wrapper);
        return View();
    }
}

class Controller2 {
    IWrapper wrapper = Wrapper2();
    public ActionResult DoSequence(){
        <some class>.RunSequence(wrapper);
        return View();
    }
}

class <Some Class>{
    public void RunSequence(IWrapper wrapper)
    {
        wrapper.SetepOne();
        wrapper.StepTwo();
        wrapper.StepThree();
    }
}

Mi chiedo se ci sia un modello di progettazione che potrebbe aiutare a costruire <Some Class> o un modello architettonico che potrebbe aiutare a decidere dove dovrebbe andare quella classe.

    
posta DFord 19.12.2017 - 16:14
fonte

2 risposte

5

Il modello di design classico per questo è il modello di metodo del modello . Questo porterebbe ad un design come

class AbstractController{
    IWrapper wrapper;
    public ActionResult DoSequence() {
        wrapper = CreateWrapper();
        wrapper.StepOne();
        wrapper.StepTwo();
        wrapper.StepThree();
        return View();
    }
    protected abstract IWrapper CreateWrapper();
}

Ora puoi ricavare Controller1 e Controller2 da AbstractController e implementare CreateWrapper in ciascuna classe derivata di conseguenza.

Tuttavia, in questo caso potresti anche usare generici (in Java o C #, o modelli in C ++) per risolvere il tuo problema:

class Controller<T>  {
    IWrapper wrapper = T();
    public ActionResult DoSequence(){
         wrapper.StepOne();
         wrapper.StepTwo();
         wrapper.StepThree();
         return View();
    }
}

(esercizio per il lettore: correggi la sintassi del tuo linguaggio di programmazione).

Questo è più breve poiché non è necessario ricavare nulla qui, tuttavia, gli utenti di quella classe ora devono essere a conoscenza del tipo che possono passare per il parametro T .

    
risposta data 19.12.2017 - 19:33
fonte
2

Vedo due modi per andare qui:
A prima vista penso a astrazione e ereditarietà , riutilizziamo la logica aziendale comune usando una super classe, puoi spostare il blocco di codice in un'astrazione e poi ereditarlo in entrambi i controller senza esporlo agli altri (favorisce l'incapsulamento).

class AbstractController {
    protected void runSequence() {
        wrapper.SetepOne();
        wrapper.StepTwo();
        wrapper.StepThree();
    }
}

class Controller1 extends AbstractController {
    IWrapper wrapper = Wrapper1();
    public ActionResult DoSequence(){
        this.RunSequence(wrapper);
        return View();
    }
}

class Controller2 extends AbstractController {
    IWrapper wrapper = Wrapper2();
    public ActionResult DoSequence(){
        this.RunSequence(wrapper);
        return View();
    }
}

Puoi anche creare una classe diversa per esternare la logica di business, questa è chiamata Visitor Pattern , potrebbe essere la soluzione migliore in situazioni in cui la logica di business è la stessa anche in altri luoghi (favorisce il riutilizzo).

    
risposta data 19.12.2017 - 19:38
fonte

Leggi altre domande sui tag