Oggetti immutabili vs mutabili - Design

2

Ho una classe che modella LogicalExpressions. Le foglie sono classi che implementano un'interfaccia IEvaluable, che ha un metodo chiamato Evaluate che restituisce un booleano come risultato.

public class MyEvaluable : IEvaluable
{
    public bool Evaluate(Environment env)
    {

    }
}

Alcuni di questi oggetti valutabili devono fare alcune cose pesanti per produrre il risultato, come ad esempio chiamare un servizio web. E poiché un'espressione logica può avere più oggetti correlati, vorrei valutarli tutti in una volta, facendo una chiamata al servizio web per tutti loro invece di chiamate separate per ogni parametro.

Quindi ho pensato a un buon modo di progettare un sistema del genere e ho trovato 2 soluzioni:

1) Rende mutevoli i miei oggetti valutabili.

public interface IBatchEvaluable
{
    void BatchEvaluate(object[] siblings, Common.Environment env);
    bool IsEvaluated { get; }
    bool EvaluationResult { get; }
}
public interface IBatchEvaluable<T> : IBatchEvaluable
{
    void BatchEvaluate<T>(T[] siblings, Common.Environment env);
}

Quindi ogni oggetto che è IBatchEvaluable avrà uno stato. Quando ho bisogno di valutarlo, controllo se è già stato valutato e, se necessario, esegue la valutazione del lotto. L'unico neo è che i miei oggetti saranno mutabili, e questo non è davvero desiderabile.

2) Memorizza i dati di valutazione nell'ambiente

Potrei mantenere gli oggetti immutabili e spostare i dati IsEvaluated e EvaluationResult nell'ambiente. Quindi ogni oggetto dovrebbe prima cercare nell'ambiente per vedere se è già stato valutato e in tal caso ottenere il risultato dall'ambiente, altrimenti valutare tutti i fratelli in una volta sola e inserire i dati nell'ambiente.

Anche questo non è molto interessante, dal momento che l'implementazione dei miei oggetti dipenderà da dati esterni, non sembra rispettare i principi OOP.

Come dovrei fare questo da una prospettiva OOP? Sono aperto ad ascoltare altre potenziali soluzioni a questo.

    
posta Adrian 16.01.2017 - 15:45
fonte

2 risposte

2

And since a logical expression may have multiple such objects that are related, I would like to evaluate them all at once, doing one web service call for all of them instead of separate calls for each parameter.

Quindi perché non lo fai?

Passare e memoizzare i risultati delle espressioni non sarà l'ideale quando si effettuano chiamate a servizi Web e tali perché sono invariabilmente chiamate non puri. Se chiedi la temperatura ora, il servizio web ti darà un risultato diverso rispetto a un'ora. Passando a questo approccio di batch sotto le copertine, stai cambiando il risultato del tuo calcolo in modo invisibile dal tuo utente.

Se il tuo obiettivo è quello di ottenere tutti i dati e poi operare su di esso, allora fallo. Quello che descrivi è MapReduce in poche parole. Invece di avere espressioni logiche su singoli elementi, dovresti spostare la progettazione in operazioni che funzionano su insiemi. Quindi diventa più naturale ottenere i dati come batch ed eseguire operazioni su quel batch. Non devi preoccuparti troppo se parti dei dati sono state caricate da quando è diventato più chiaro nel mondo delle operazioni impostate. E con un sacco di implementazioni esistenti, puoi trovare risorse per aiutarti o forse scoprire che non è necessario scrivere il codice perché esiste già.

    
risposta data 16.01.2017 - 16:54
fonte
0

Un approccio con cui potresti andare è usare la composizione e il modello di strategia. Ciò non eliminerà la mutabilità, ma affronterà la questione dell'incapsulamento a cui punti alla fine della tua domanda. Fondamentalmente aggiungi un altro strato oltre il Evaluable . Avrà un riferimento a un altro Evaluable che può essere risolto o un risultato. Quando viene chiamata la tua percentuale composita% co_de, ottieni il risultato dalla% risolvibile% co_de e lo metti in un oggetto risultato.

Se vuoi essere completamente agnostico, puoi farlo semplicemente con ogni Evaulable indipendentemente dal fatto che sia già stato risolto. Questo creerà un churn di nuovi oggetti ma potrebbe non essere un problema. Se lo è, puoi aggiungere un metodo a Evaluable per restituire il risultato come Evaluable e il risultato risolto restituisce semplicemente Evaluable

    
risposta data 16.01.2017 - 16:37
fonte

Leggi altre domande sui tag