Domanda

Supponiamo abbiamo un'entità radice aggregato di tipo ordine che riguarda clienti e linee d'ordine. Quando penso a un'entità ordine è più naturale di concettualizzare come non essere definito senza un ID. Un ordine senza un ID sembra essere meglio rappresentato come un modulo d'ordine di un ordine.

Per aggiungere un ordine a un repository, di solito vedo la gente istanziare l'ordine senza l'Es e quindi avere il repository completano l'oggetto:

class OrderRepository
{
    void Add(Order order)
    {
        // Insert order into db and populate Id of new order
    }
}

Quello che mi piace di questo approccio è che si sta aggiungendo un'istanza Ordine ad un OrderRepository. Che fa un sacco di senso. Tuttavia, l'istanza di ordine non ha un ID, e alla portata del consumatore del repository, si fa ancora non ha senso per me che un ordine non ha un ID. Potrei definire un OrderRequest di essere un esempio di ordine e aggiungo che al repository, ma che si sente come una mela derivante da un arancio e poi aggiungere a un elenco di arance.

In alternativa, ho visto anche questo approccio:

class OrderRepository
{
    Order AddOrder(Customer customer)
        // It might be better to call this CreateOrder
    {
        // Insert record into db and return a new instance of Order
    }
}

Quello che mi piace di questo approccio è che un ordine è indefinito, senza un ID. Il repository può creare il record del database e raccogliere tutti i campi obbligatori prima di creare e restituire un'istanza di un ordine. Che gli odori è il fatto che non avete mai realmente aggiungere un'istanza di un ordine al repository.

In entrambi i casi funziona, quindi la mia domanda è:? Devo convivere con una di queste due interpretazioni, o c'è una buona pratica per modellare l'inserimento

Ho trovato questa risposta che è simile, ma per gli oggetti di valore: come devo aggiungere un oggetto in una collezione gestito da aggregato radice . Quando si tratta di un oggetto di valore non c'è confusione, ma la mia domanda riguarda un ente con identiy derivato da una fonte esterna (Database Auto-Generated Id).

È stato utile?

Soluzione

Vorrei iniziare escludendo il secondo approccio. Non solo sembra contro-intuitivo, ma viola anche diversi buoni principi di progettazione, come ad esempio Separazione Comando-Query e il principio del minimo Surprise .

Le opzioni variano a seconda del dominio Logic. Se il dominio logica vuole che un Ordine senza un ID non ha senso, l'ID è un invariante richiesta dell'Ordine, e dobbiamo modellare così:

public class Order
{
    private readonly int id;

    public Order(int id)
    {
        // consider a Guard Clause here if you have constraints on the ID
        this.id = id;
    }
}

Si noti che contrassegnando il campo id come readonly abbiamo reso un invariante. Non c'è modo siamo in grado di cambiare per una determinata istanza Ordine. Questo si sposa perfettamente con Domain-Driven 's Ente modello.

Si può ulteriormente far rispettare dominio Logic mettendo una clausola Guardia al costruttore per evitare che l'ID di essere negativo o pari a zero.

A questo punto vi starete chiedendo come questo sarà eventualmente lavorare con gli ID generati automaticamente da un database. Beh, non è così.

Non c'è buon modo per garantire che l'ID fornito non è già in uso.

Che ti lascia con due opzioni:

  • Modificare l'ID di un GUID. Questo permette ad ogni visitatore di fornire un ID univoco per un nuovo ordine. Tuttavia, questo richiede l'utilizzo di GUID come chiavi di database pure.
  • Cambiare l'API in modo che la creazione di un nuovo ordine non prende un oggetto Ordine, ma piuttosto un OrderRequest come lei ha suggerito -. L'OrderRequest potrebbe essere quasi identica alla classe Ordine, meno il ID

In molti casi, la creazione di un nuovo ordine è un'operazione di business che ha bisogno di modellazione specifica in ogni caso, quindi non vedo alcun problema fare questa distinzione. Sebbene Ordine e OrderRequest possono essere semanticamente molto simili, che non hanno nemmeno bisogno di essere connessi nella gerarchia tipo.

Potrei anche andare così lontano come a dire che non dovrebbero essere correlato, perché OrderRequest è un Valore oggetto , mentre ordine è un Ente .

Se è preso questo approccio, il metodo AddOrder deve restituire un'istanza d'ordine (o almeno la ID), perché altrimenti non possiamo conoscere l'ID dell'ordine che abbiamo appena creato. Questo ci riconduce alla violazione CQS ed è per questo tendo a preferiscono GUID per gli ID entità .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top