Dilemma durante la progettazione di un modello di dominio

2

Ho una classe Document e il documento ha uno stato:

public enum DocumentStatus : byte
{
    Incompleted,
    Completed,
    Cancelled
}

Ora ho un dilemma che non posso risolvere da solo.

Se Document ha metodi come Cancel e Complete e eventi di dominio come DocumentCancelled e DocumentCompleted

public class Document : Entity, IAggregateRoot
{
    ...

    public DocumentStatus Status { get; private set; }

    public void Cancel()
    {
        Status = DocumentStatus.Cancelled;
        this.AddDomainEvent(new DocumentCancelled(this));
    }

    public void Complete()
    {
        Status = DocumentStatus.Completed;
        this.AddDomainEvent(new DocumentCompleted(this));
    }
}

O sarebbe anche bello rendere pubblico Status setter e avere eventi di dominio come DocumentStatusChanged ?

public class Document : Entity, IAggregateRoot
{
    ...

    private DocumentStatus _status;

    public DocumentStatus Status
    {
        get => _status;
        set {

            this.AddDomainEvent(new DocumentStatusChanged(this, _status, value)); // oldValue, newValue

             _status = value;
        }
    }
}

In questo caso è meglio che usare un metodo come:

public class Document : Entity, IAggregateRoot
{
    ...

    public DocumentStatus Status { get; private set; }

    public void SetDocumentStatus(DocumentStatus status)
    {
        this.AddDomainEvent(new DocumentStatusChanged(this, Status, status)); // oldValue, newValue
        Status = status;
    }
}

Scusa se questo sembra banale o stupido, ma sono nuovo di DDD e sto cercando di seguire le migliori pratiche.

    
posta Konrad 20.08.2018 - 13:39
fonte

4 risposte

1

Should Document have methods like Cancel and Complete and domain events like DocumentCancelled and DocumentCompleted

Non creare eventi se la tua applicazione non li sta ascoltando. A meno che non si stia lavorando su un'applicazione tradizionale (ad esempio desktop o telefono), gli eventi non sono molto utili. I metodi sono una buona idea. Rendono lo stato del documento un attributo di sola lettura e l'atto di cancellare o completare un documento è libero di avere altre azioni oltre al semplice stato di impostazione. Questa è una buona cosa.

Or would it also be fine to make Status setter public and have domain event like DocumentStatusChanged?

Ancora, lo stesso commento sugli eventi. Se devi aggiungere una logica aggiuntiva (come le convalide ecc.), Un semplice setter renderà il tuo codice difficile da seguire.

La più grande domanda che ti ho posto è dove viene utilizzato il tuo modello di dominio? Le applicazioni Web e le interfacce utente standard hanno diversi modi per comunicare tra loro. Se il tuo modello non deve notificare nessun altro codice, non è necessaria alcuna notifica.

C'è un'altra opzione:

class Document : Entity, IAggregateRoot
{
    public DocumentStatus Status { get; private set; }

    public void Cancel()
    {
        this.AddDomainEvent(new DocumentStatusChanged(this, Status, DocumentStatus.Cancelled));
        Status = DocumentStatus.Cancelled;
    }

    public void Complete()
    {
        this.AddDomainEvent(new DocumentStatusChanged(this, Status, DocumentStatus.Completed));
        Status = DocumentStatus.Completed;
    }        
}
    
risposta data 20.08.2018 - 21:18
fonte
4

In questo caso, dovresti probabilmente usare come guida la lingua dei tuoi esperti di dominio: un modo di pensare sulla modellazione del dominio è che stiamo cercando di creare un linguaggio specifico per il dominio che corrisponda ai problemi che stiamo cercando di risolvere.

Pochissimi domini usano "set" come preoccupazione di prima classe nella lingua.

Ad esempio, "ordiniamo", "completiamo" e "annulliamo" gli ordini. Quindi preferiremmo modellare quella lingua, piuttosto che usare le ortografie come "set status".

    
risposta data 20.08.2018 - 13:59
fonte
2

Se tutte le transizioni tra stati sono valide probabilmente farei una proprietà con getter + setter pubblico, è la cosa più semplice che potrebbe funzionare e non richiedere praticamente alcun codice.

Dove vorrete sicuramente mettere dei metodi imho è se certe transizioni sono proibite per es. non può andare da cancellato - > completa

    
risposta data 20.08.2018 - 13:59
fonte
0

Potresti usare il setter per questo. È, infatti, utilizzato nel mondo reale per l'implementazione di cose come l'associazione bidirezionale in Windows Form e proxy EF. Ma questo non significa che dovresti usarlo anche.

Le proprietà sono principalmente pensate per ottenere e impostare valori. Potrebbero esserci sviluppatori che non si aspettano effetti collaterali o si aspettano un ritorno immediato quando ottengono / impostano una proprietà. L'utilizzo di un metodo invece di una proprietà specifica meglio l'intento e ti protegge anche dalle eventuali modifiche successive quando potresti aver bisogno di parametri quando cambi lo stato.

    
risposta data 20.08.2018 - 14:11
fonte

Leggi altre domande sui tag