Va bene chiamare servizi esterni o database all'interno dell'entità

1

Ho un "motore logico" che esegue un insieme di passi configurati dall'utente. Questi passaggi sono salvati nel database come entità "Step". Il motore ottiene il primo passo e quindi esegue i passaggi finché non ci sono più passaggi da eseguire:

public void Execute(details, data, Step firstStep)
{
    var step = firstStep;
    while (null != step)
    {
        step = step.Execute(details, data);
    }
}

I diversi tipi di passaggi sono espressi come classi derivate. Ognuno di loro deve implementare il metodo Execute. I parametri di dati e dettagli vengono utilizzati dal passaggio per eseguire una logica. Come il motore logico sa che sta solo eseguendo passo dopo passo senza sapere cosa fanno questi passaggi.

Il problema:

Alcuni passaggi devono accedere a servizi esterni per ottenere dati o anche lo stesso database o lo stesso database in cui sono archiviate le entità di passaggio effettive. Le informazioni sono solitamente utilizzate da altri passaggi. Si potrebbe dire che alcuni dei passaggi sono solo per il caricamento di dati da fonti esterne / database e altri passaggi stanno usando tali dati per prendere decisioni. Questa separazione viene eseguita in modo da poter utilizzare diverse origini dati (purché producano lo stesso tipo di output) senza la necessità di scrivere alcun codice aggiuntivo.

C'è un modo migliore per gestire questo tipo di dominio? Se separo l'attuale Step e la logica (ovvero caricando i dati dal servizio esterno o dal database), allora il mio intero modello di dominio (passaggi) non ha alcuna logica. Molto probabilmente avrei qualcosa di simile:

var handler = dictionary[step];
handler.Execute(step, details, data);

Ora la logica e tutte le dipendenze esterne sono nell'oggetto gestore ma l'oggetto dominio effettivo (passo) è solo un fittizio segnaposto per le informazioni. Anche questo non sembra corretto.

    
posta Toni Parviainen 06.01.2012 - 18:29
fonte

1 risposta

2

Suggerisco di implementare un nuovo tipo di oggetto, Step Data Source, nel tuo dominio. Puoi farlo implementare un'interfaccia in modo che la singola fonte non sia importante finché le fonti utilizzano la stessa interfaccia. Proprio come hai diversi tipi di passaggi, puoi avere diversi tipi di StepDataSources. Poiché i passaggi sono configurati dall'utente, potresti anche avere un elenco di origini dati disponibili per l'utente tra cui scegliere (se si tratta di una storia utente che desideri implementare).

Ecco come potrebbe apparire un passaggio che utilizza un'origine dati di passaggio:

public class DerivedStep : Step, IStepWithData
{
    ...
    public IStepDataSource IStepWithData.GetDataSource() { ... }
    public void IStepWithData.Execute(IStepDataSource DataSource, ...)
    {
        ...
        // use the data source to get the data to pass to Step.Execute
        var data = DataSource.SomeMethodWhichReturnsData(...)
        Execute(data, ...);
    }

    // overridden from Step parent class
    public void override Execute(data, ...)
    {
    }
}

// logic engine might do something like this
...
Step step = ...
if (step is IStepWithData)
{
    IStepWithData dataStep = step as IStepWithData;
    var source = dataStep.GetDataSource();
    dataStep.Execute(source);
}
else
{
    step.Execute(...);
}
...

Non sono esattamente chiaro sul tuo dominio, quindi è solo una pugnalata. Ci sono molti dettagli di implementazione che non sono mostrati ovviamente e potrebbero non essere esattamente adatti al tuo dominio.

Non mi preoccuperei troppo delle tue lezioni che non hanno un comportamento "sufficiente", ed ecco perché; Il tuo dominio è di natura transazionale (gli utenti che definiscono i passaggi da eseguire sugli oggetti), quindi è naturale che il tuo modello di dominio (codice) lo rifletta e diventi più transazionale.

    
risposta data 02.05.2012 - 17:11
fonte

Leggi altre domande sui tag