Come progettare un'entità di dominio che utilizza una dipendenza per gestire un campo di stato?

3

Sono nuovo di DDD e IOC / DI e sto avendo qualche problema a capire come progettare un'entità che ha bisogno di utilizzare un modello di stato per gestire il suo stato. Poiché le transizioni sono un po 'complicate, sto usando una macchina a stati finiti (FSM) per gestire gli stati (sto usando Stateless ).

Per complicare ulteriormente la situazione, l'FSM deve essere liberamente associato a un'entità. Cioè mentre so che lo stato dell'entità deve essere gestito da un FSM, non necessariamente so esattamente cosa sia l'FSM (cioè l'entità non sa quali stati / trigger / transizioni potrebbero attraversare). Gli utenti usano il termine flusso di lavoro per definire l'FSM (stato, trigger, transizioni, regole, ecc.). Il flusso di lavoro cambia indipendentemente dall'entità. Potrebbero voler aggiungere nuovi stati, cambiare regole, trigger ecc. Indipendentemente da eventuali modifiche all'entità.

Sto gestendo questo caricando dinamicamente un assembly che contiene una definizione di FSM (che implementa un'interfaccia conosciuta), quindi utilizzando un servizio che viene iniettato nell'entità, l'entità chiama il servizio e ottiene l'FSM che è utilizzando. Ciò comporta potenzialmente il caricamento di assiemi, il caching della factory che crea l'FSM e l'assegnazione dell'FSM nello stato appropriato all'entità. Infine, l'FSM può restituire l'insieme di trigger validi che possono essere forniti all'interfaccia utente in modo che uno di quei trigger possa essere selezionato e attivato. Il flusso di lavoro effettivo completamente incapsulato esternamente all'entità.

Quindi, attualmente sono la mia entità che assomiglia a qualcosa del tipo:

public class EntityUsingWorkflow
{
  private readonly workflowService;

  public Order(IWorkflowService service, string workflowKey, string status)
  {
    this.workflowService = service;
    this.WorkflowKey = workflowKey;
    this.Status = status;

    // Note that the two lambdas are used to retrieve
    // and set the state on the entity.
    this.Workflow = service.GetStateMachine(workflowKey, () => this.Status, stateValue => this.Status = statValue );
  } 

  public string WorkflowKey { get; set; }
  public IStateMachine Workflow { get; private set; }
  public string Status { get; private set; }

}

Sono interessato a questo design. La mia comprensione di base è che le entità di dominio non dovrebbero avere delle dipendenze iniettate in esse, ma qui ne sto iniettando una. Comprendo inoltre che l'entità deve gestire il proprio stato , quindi io È esitante spostare il flusso di lavoro completamente fuori dall'entità. Altre idee che ho avuto, come un metodo init, sposterebbero semplicemente l'iniezione sull'iniezione del metodo.

Quale sarebbe un modo pulito per progettare un'entità con questi requisiti? Va bene iniettare una dipendenza in questa situazione?

    
posta Greg McGuffey 10.04.2014 - 22:02
fonte

1 risposta

5

Va perfettamente bene - anzi, è una buona idea - usare l'iniezione di dipendenza nel tuo modello di dominio.

Dovresti sviluppare il tuo modello di dominio indipendentemente da una particolare tecnologia o libreria. I dettagli di tale e tali database o così e così non sono la preoccupazione del tuo modello di dominio: se hai bisogno di scambiare i database le tue regole aziendali rimarranno le stesse. Quindi applichiamo il principio di inversione di dipendenza e dipendiamo da interfacce che rispondono alle preoccupazioni del modello di dominio e adattatori che adattano un determinato problema tecnologico al dominio. (È importante sottolineare che l'interfaccia è formulata in termini di operazioni a livello di dominio e vive nello stesso pacchetto delle classi di dominio.)

Un grande esempio di questo è il pattern di repository. Il repository adatta il database a un'interfaccia adatta al modello di dominio. Quindi puoi scrivere customerRepository.FindByEmailAddress(email) e non preoccuparti delle esatte istruzioni SQL che recuperano il cliente per te. E dipendendo da un'interfaccia, il tuo modello di dominio non ha idea se si tratti di un database SQL, di un file, o di MongoDB o Neo4j o altro.

Quindi il principio di inversione delle dipendenze e l'iniezione di dipendenza è di enorme utilità nel DDD. Ciò che ritengo sia meno utile è mantenere il dominio in un contenitore IOC . Il problema è che si finisce per memorizzare informazioni a livello di dominio (come come allegare un ordine a un cliente) lontano dalle classi di dominio in un file di configurazione da qualche parte. IOC nasconde i dettagli che non dovrebbero essere nascosti dal tuo modello di dominio. Inoltre, i dettagli del tuo particolare contenitore tendono a filtrare nelle tue classi di dominio.

Utilizzare IOC ai limiti del proprio sistema, se necessario, per collegare i gestori di comandi e altri servizi API. Utilizza Inversione dipendenza e Iniezione di dipendenza nel tuo modello di dominio ogni volta che ha senso farlo, ma mantieni l'IOC fuori dall'immagine.

    
risposta data 10.04.2014 - 22:18
fonte

Leggi altre domande sui tag