Servizi di modelli di domini e container ricchi

2

Ho una lunga esperienza nella programmazione di progetti Java EE, ma come ho notato la maggior parte del lavoro che ho fatto era con Transaction Script (anti) pattern.

Quindi voglio imparare ad usare un modello di dominio ricco, ma poi c'è una domanda, l'oggetto dominio deve essere dipeso dai servizi container / di sistema (come persistenza, posta, ...)?

Ho letto questo articolo e non sono affatto d'accordo!

  • In che modo i servizi vengono inizializzati e iniettati in entità di dominio?
  • Che dire del paradigma della responsabilità unica?
  • E non è contro la riusabilità?

Ho letto anche Applicando UML e Pattern un libro fantastico, ma non so perché non sia stato autore descrivere il modo in cui le responsabilità devono essere assegnate alle entità dopo aver definito il livello di accesso ai dati (nel capitolo 38).

Quindi qual è la prassi migliore per avere un modello di dominio ricco e non avere dipendenza dai servizi di contenitore / sistema!

Un esempio, considera lo scenario seguente in un software:

  • Ci sono agenti (che funzionano con il sistema)
  • L'attività dei nostri agenti sta vendendo polizze assicurative.
  • Ogni tipo di polizza assicurativa ha un tipo speciale di carta prestampata che viene consegnata agli agenti e gli agenti li consegnano agli assicurati.
  • Dobbiamo monitorare il numero di schede disponibili di ciascun agente.

  • Quindi esiste un caso d'uso, che registra il numero di carte di ciascun tipo assegnato a ciascun agente.

  • Esiste un caso d'uso, per registrare il numero di schede inutilizzate danneggiate di ciascun tipo.
  • E le carte vengono utilizzate in quanto l'agente vende polizze assicurative.

Credo che Rich Domain Model suggerisca che avrò un metodo come segue nella classe agent:

class Agent {
    int computeRemainigCards(CardType cardType) {}
}

Ma poi l'Agente dipenderà da 3 classi DAO per una sola responsabilità:

  • Uno per il calcolo di SUM del conteggio di ciascun tipo di carta assegnato a un agente.
  • Uno per il calcolo del conteggio delle carte utilizzate (vendendo polizze assicurative).
  • Uno per il calcolo della SOM delle carte invendute danneggiate.

Credo che renderà le entità di dominio un disastro. Allora, qual è la buona pratica?

    
posta Amir Pashazadeh 08.04.2014 - 23:46
fonte

2 risposte

2

La tua domanda è esattamente la domanda a cui rispondere leggendo Progetto basato sul dominio .

Il commento di Andy è azzeccato. Le entità non dipendono dai DAO. Dipendono dalle astrazioni che rappresentano le operazioni che le entità devono funzionare. Il fatto che tali astrazioni rappresentino l'archiviazione dei dati e sono implementate utilizzando il database è irrilevante per le entità o qualsiasi parte del modello di dominio. Queste astrazioni sono chiamate repository in DDD.

Per rispondere alle tue domande:

  • In che modo i servizi vengono inizializzati e iniettati in entità di dominio? - Quando l'entità viene estratta dalla persistenza, viene inizializzata con le realizzazioni delle astrazioni di cui ha bisogno, insieme ai dati dell'entità.
  • E il paradigma della singola responsabilità? - Che ne pensi? L'entità ha una sola responsabilità: rappresentare il comportamento relativo al concetto di dominio singolo.
  • E non è contro la riusabilità? - In realtà è altamente riutilizzabile. Soprattutto se applichi altri principi SOLID e usi la composizione invece dell'ereditarietà.

Per il tuo esempio, che può essere facilmente risolto dall'agente con riferimento all'interfaccia, che gli consente di interrogare le carte in modo diverso. I metodi quindi chiamano questa interfaccia.

    
risposta data 14.04.2014 - 12:11
fonte
1

Che cosa intendi con Ma allora l'agente deve dipendere da 3 classi DAO per una sola responsabilità ? Se stai parlando di evitare chiamate DAO da classi di dominio, forse puoi progettarlo in questo modo:

class Agent {

   List<Card> assignedCards;

   int numberOfRemainingCards() {
      return assignedCards.size();
   }

   void sell(Card card) {
      // do something
      assignedCards.remove(card);
   }

   void damaged(Card card) {
      card.damaged = true;
      assignedCards.remove(card);
   }

}

class Card {

   String id;

   boolean damaged;

}

Hai bisogno di una sola chiamata a DAO (o repository) per recuperare un Agent con il loro assignedCards . Coinvolge solo un DAO, ad esempio:

List<Agent> agents = AgentDAO.getAllAgents();
for (Agent agent: agents) {
   System.out.println("Remaining cards for " + agent.name + 
                      " is " + agent.numberOfRemainingCards());
}

Un altro esempio:

Agent agentA = AgentDAO.findByName("Agent A");
agentA.sell(aCard);
agentA.damaged(anotherCard);
System.out.println("Number of remaining cards: " + agentA.numberOfRemainingCards());
AgentDAO.update(agentA); // if necessary

Se Agent ha un sacco di Card e non vuoi recuperare tutto Card solo per determinare il numero di Card s rimanente, puoi memorizzare il numero di carte rimanenti come stato, ad esempio :

class Agent {

   List<Card> assignedCards;

   int numberOfRemainingCards;

   int getNumberOfRemainingCards() {
      return this.numberOfRemainingCards;
   }

   void sell(Card card) {
      // do something
      assignedCards.remove(card);
      numberOfRemainingCards--;
   }

   void damaged(Card card) {
      card.damaged = true;
      assignedCards.remove(card);
      numberOfRemainingCards--;
   }

   void assign(Card card) {
      assignedCards.add(card);
      numberOfRemainingCards++;
   }

}
    
risposta data 14.04.2014 - 10:16
fonte

Leggi altre domande sui tag