DDD: radice di aggregazione ottiene un riferimento a un'altra radice di aggregazione

1

Ho 3 AR:

  • Student
  • Guardiano

Regola aziendale :

  • Lo studente dovrebbe avere almeno 1 tutore autorizzato Le entità non dovrebbero essere in uno stato non valido, giusto?

In questo momento ho forzato l'invariante nel mio costruttore Student :

public function __construct(StudentId $id, Name $name, Guardian ...$guardians) {

  if ( $this->hasNoAuthorizedGuardian(...$guardians) ) {
      throw new NoAuthorizedGuardianException();
  }

  // initialized fields
}

Tuttavia, durante la creazione della parte repository per la mia AR studente, ho riscontrato un problema nel recuperare i guardiani "necessari" per questo.

class StudentRepository {
    public function getById(StudentId $id): Student {
        // other lines omitted for brevity
        return new Student($id, $name, ...$guardians);
    }
}

Ho pensato a queste domande:

  • Dovrei fare riferimento a GuardianRepository all'interno di StudentRepository ? Mi sento come se la risposta fosse no, ma sono nuovo di DDD quindi potrebbe essere valido

  • Le AR dovrebbero avere il permesso di fare riferimento ai repository? Sento che la risposta a questo è anche no, ma come ho detto sono nuovo di DDD, quindi questo potrebbe essere valido.

  • Ho applicato correttamente il mio invariante? O dovrei metterlo in Domain Service in modo che non abbia bisogno di recuperare le entità correlate in un singolo repository?

Il secondo approccio mi consentirà di fare questo:

class StudentService {

    public function getById(StudentId $id) {
        $student = $this->studentRepo->getById($id);
        $guardians = $this->guardianRepo->getByStudentId($id);

        $student->guardians(...$guardians);

        return $student;
    }

}

Contro di farlo anche se le mie entità diventeranno un'entità di dominio anemico da quando ho trasferito l'invariante in un altro livello.

Un'altra possibile soluzione che ho trovato è il caricamento lento, ma non sono sicuro di come farlo, incluso quando e come recuperare le entità correlate.

TL; DR : se la tua entità radice richiede un riferimento a un'altra entità radice, come puoi ottenerla?

Modifica :

Per chiarimenti, non ho menzionato che Guardian ha le sue entità come Contatti e altri Value Objects. Penso che sia abbastanza per essere considerato un AR perché dovrebbe essere quello che li gestisce.

Il riferimento Studente-Guardiano qui è un Contesto Limitato Credo che ho appena imparato ora.

    
posta doesnotmatter 18.08.2018 - 09:38
fonte

1 risposta

0

È assolutamente normale per le Entità essere in uno stato "non valido" in base a regole aziendali come "Gli studenti devono registrare un tutore o non possiamo legalmente iscriverli"

Queste regole sono soggette a cambiamenti e casi eccezionali. Devi contrassegnare tali casi come infrangere le regole, piuttosto che rendere impossibile per il tuo programma creare un'istanza di un oggetto di quel tipo.

In questo caso la tua applicazione può semplicemente fare riferimento a entrambi i repository AR, AR può avere una proprietà sudentId / guardianId che puoi cercare, oppure puoi avere la relazione in un servizio separato.

Ora, se la 'invalidità' non è semplicemente una regola aziendale, ma inerente alla natura dell'Entità, come, non so, Cats ha 0-4 Legs e Cat.Speed dipende dal numero esatto . Quindi la gamba dovrebbe far parte del gatto AR.

Se un Gatto ha 5 Gambe allora Cat.Speed causerà il crash del programma, Se cambio il numero di Gambe su un gatto, la sua Velocità dovrebbe aggiornarsi automaticamente o otterrò l'output sbagliato dal mio programma ecc.

Mettere Cat e Leg in AR separate sarebbe problematico, Cat.Speed dovrebbe chiamare il LegRepo prima di restituire un risultato, potrei aggiungere una gamba senza aggiornare la velocità del gatto ecc.

Dovrai decidere in quale caso far cadere il tuo Studente e Guardiano. Se disponi di una singola AR, puoi avere Student.RemoveGuardian(id) e imporre che non autorizzi la rimozione dell'ultimo guardiano.

O sarebbe più sensato avere GuardianRemovalService.RemoveGuardian(studentId,guardianId) che può anche applicare la regola, ma consente la possibilità di un'altra applicazione che rimuove il tutore direttamente da GuardianRepo senza seguire la regola aziendale?

    
risposta data 18.08.2018 - 11:25
fonte

Leggi altre domande sui tag