Design Pattern per il risultato del metodo di elaborazione

0

Attualmente sto rifattorizzando un pezzo di codice per mantenere le cose testabili e mantenibili nella nostra applicazione c #.

Mi sono imbattuto in uno scenario in cui un metodo esistente restituisce dati con elenchi ed enumerati che vengono poi elaborati con molte altre condizioni if in un lungo metodo lungo più di 800+ righe. Fortunato me!

Stavo cercando di scegliere un modello di design adatto dalla Gang Of Four, ma non riesco a vedere qualcosa che si adatti. Illustrerò ciò che ho in atto al minuto. Qualche idea su come affrontare al meglio / refactoring il seguente?

Il seguente codice è stato semplificato da quello che ho in produzione. Il suo scopo è mostrare la logica di riduzione nello scenario. Questo è ciò che ho rifatto finora. Non preoccuparti della statica e non ci sono interfacce: le interfacce sono state omesse per semplicità.

public class MySearchClass
{
    public static SearchResult Find(QueryParameters queryParams)
    {
        ...
    }
}

public class SearchEntityResult
{
    public IEnumerable<SearchEntityData> Matches { get; set; }
}

public class SearchEntityData
{
    public SearchMatchType MatchType { get; set; }
    public Guid SearchEntityId { get; set; }
    public string EntityName { get; set; }
}

public enum SearchMatchType
{
    Partial,
    Exact   
}


public class BigLongMethodClassProcessor
{
    public static void DoFindAndProcess()
    {
        ... spaghetti code ...

        SearchEntityResult result = MySearchClass.Find(...);

        if (result.BestMatch == SearchMatchType.Exact)
        {
            ...
        }
        else
        {
            foreach (var m in  result.Matches)
            {
                if (m.MatchType == SearchMatchType.Partial)
                {
                    ... do this ...
                }
                else if (m.MatchType == SearchMatchType.Exact)
                {
                    ... do that ...
                }
            }   
        }

        ...
    }
}

Il mio pensiero era di avere una fabbrica che avrebbe esaminato SearchEntityResult e creato un SearchEntityResultProcessor appropriato.

public class ExactSearchEntityResultProcessor : ISearchEntityResultProcessor
{
    public void Process(SearchEntityResult result)
    {
        ...
    }
}

public class SearchEntityResultProcessorFactory
{
    public static ISearchEntityResultProcessor Create(SearchEntityResult result)
    {
        if (result.BestMatch == SearchMatchType.Exact)
        {
            return new ExactSearchEntityResultProcessor();
        }
        else if (result.BestMatch == SearchMatchType.Partial)
        {
            return new PartialSearchEntityResultProcessor();
        }
        else
        {
            // throw
        }
    }
}

Quindi BigLongMethodClassProcessor avrà il seguente aspetto:

public class BigLongMethodClassProcessor
{
    public static void DoFindAndProcess()
    {           
        SearchEntityResult result = MySearchClass.Find(...);
        ISearchEntityResultProcessor processor = SearchEntityResultProcessorFactory.Create(result);
        processor.Process(result);
    }
}

Quindi tutte le statistiche verranno rimosse e introdotte le interfacce.

    
posta Andez 20.03.2017 - 09:57
fonte

2 risposte

1

La tua soluzione mi sta bene. Stai costruendo il processore in grado di gestire un risultato e quindi elaborare il risultato che lo utilizza.

Un'altra opzione è il modello della catena di responsabilità. link

È come se la soluzione, tranne il controllo per verificare se un processore è in grado di gestire il risultato, è contenuto nel processore stesso. Quindi dovresti semplicemente avere un elenco di tutti i processori e passare il risultato a ciascuno di essi fino a quando uno di essi è stato in grado di elaborarlo. In questo modo, se viene sviluppato un nuovo processore, è sufficiente aggiungerlo all'elenco.

    
risposta data 20.03.2017 - 14:58
fonte
0

Questo approccio non sembra male.

Hai una sezione rimanente in cui hai un gruppo di istruzioni if . Se i tuoi processori sono privi di stato, puoi eliminarlo utilizzando una tabella di ricerca, in questo modo:

public class SearchEntityResultProcessorFactory
{
    static private Dictionary<SearchMatchType,ISearchEntityResultProcessor > _processorLookup = new  Dictionary<SearchMatchType,ISearchEntityResultProcessor>();

    static SearchEntityResultProcessorFactory()
    {
        _processorLookup.Add(SearchMatchType.Exact, new ExactSearchEntityResultProcessor());
        _processorLookup.Add(SearchMatchType.Partial, new PartialSearchEntityResultProcessor());
    }

    public static ISearchEntityResultProcessor Create(SearchEntityResult result)
    {
        return _processorLookup[result.BestMatch];
    }
}

Se non sono apolidi, puoi ancora farlo, ma devi usare i delegati:

public class SearchEntityResultProcessorFactory
{
    static private Dictionary<SearchMatchType,Func<ISearchEntityResultProcessor>> _processorLookup = new Dictionary<SearchMatchType,Func<ISearchEntityResultProcessor>>();

    static SearchEntityResultProcessorFactory()
    {
        _processorLookup.Add(SearchMatchType.Exact, () => new ExactSearchEntityResultProcessor());
        _processorLookup.Add(SearchMatchType.Partial, () => new PartialSearchEntityResultProcessor());
    }

    public static ISearchEntityResultProcessor Create(SearchEntityResult result)
    {
        return _processorLookup[result.BestMatch]();
    }
}
    
risposta data 20.03.2017 - 20:53
fonte

Leggi altre domande sui tag