Come scrivere classi per rappresentare un modello di dominio? [chiuso]

3

In base a DDD e l'architettura pulita , le entità dovrebbero incapsulare i dati e la logica correlata.

Quindi, come si progetta una classe per rappresentare una particolare entità del mondo reale?

Due alternative tra molte delle possibili strategie:

  1. In primo luogo, definisci le proprietà dell'entità (chiedi quali informazioni devono essere memorizzate). Quindi creare getter / setter richiesti. Trova associazioni con altre entità. Infine aggiungi le operazioni per la logica di business extra.

  2. In primo luogo, definisci quali informazioni deve fornire l'entità (progetta un'interfaccia che includa solo i getter). Quindi decidere come la classe fornisce le informazioni richieste. (Implementa l'interfaccia e aggiungi alcune operazioni con effetti collaterali.) Puoi creare proprietà e setter, puoi calcolare i valori di ritorno. (Crea un'operazione pubblica calcolando le informazioni desiderate), ecc.

Ad esempio, consideriamo l'entità Studente. Ha nome, id, ecc. Uno studente frequenta alcuni corsi. Si iscrive ai corsi con alcune limitazioni e prende voti. Vuoi ottenere la sua trascrizione accademica. Ora, come inizi a scrivere una classe Student . Quali sono le tue considerazioni? Come ti assicuri che la classe soddisfi i requisiti?

    
posta Q Q 29.09.2016 - 13:34
fonte

3 risposte

3

È sciocco pensare di poter guardare un oggetto reale e iniziare a modellarlo. Ciò che è importante è ciò di cui hai realmente bisogno per quell'oggetto nel tuo sistema.

Detto questo, non ha molta importanza se si progetta la classe studentesca prima o tutto ciò che parla prima alla classe studentesca. Renditi conto di dover apportare modifiche in seguito, indipendentemente da dove inizi. Quindi 1 e 2 sono solo una preferenza personale. Puoi scrivere un buon codice in ogni caso.

Uno studente è un'entità. La trascrizione di uno studente non dovrebbe scomparire se lo studente ha il suo nome legalmente cambiato. Pertanto la trascrizione non è associata al nome dello studente ma alla sua identità.

    
risposta data 29.09.2016 - 14:08
fonte
1

Suggerirei di seguire il comportamento.

Uno studente è un oggetto reale. È anche la tua radice aggregata: una trascrizione non significa nulla se non appartiene a uno studente. Quindi, per prima cosa, crea la classe Student.

Then create required getters/setters.

Tipo di / no. Non ti scoraggio dal creare proprietà per gli attributi del mondo reale di cui sei a conoscenza. Ma le proprietà dovrebbero avere solo private set , altrimenti sono "promiscue". Puoi impostare un valore iniziale nel costruttore e modificarlo utilizzando un metodo comportamento speciale.

Questo è un tipo di arbitrario, ma per esempio ....

public string Name { get; private set; }

// usually there's more logic involved than just updating the value...
// in other words, usually there's a special real-world reason it's changing
public void ChangeName(string newValue) { Name = newValue; }

Seguendo il comportamento, dì che la prossima cosa di cui la tua app ha bisogno è caricare le trascrizioni di uno studente. La tua radice aggregata è uno Studente, quindi potresti avere uno StudentRepository per interrogare tutti gli Studenti. Il repository è un elenco di operazioni di accesso ai dati per uso speciale definite nel tuo dominio.

Questo appartiene al tuo core / dominio:

public interface IStudentRepository {
    IEnumerable<Transcript> GetTranscriptsForStudent(int studentId);
}

Questo appartiene al progetto che stai utilizzando per i dati (come EF):

public class StudentRepository {
    IEnumerable<Transcript> GetTranscriptsForStudent(int studentId) {
        //...
    }
}

(Questa separazione è forse soggettiva, ma personalmente penso che un modello di dominio non dovrebbe fare il proprio accesso ai dati.)

E quindi potresti argomentare che Course è la sua radice aggregata, con il suo repository per aggiungere uno studente a un corso.

E continua via via che cresce. Il comportamento del tuo dominio modella l'applicazione, ti dice quali unità testare per scrivere e in generale dovrebbe essere riconoscibile a qualsiasi analista aziendale analfabeta dal codice.

    
risposta data 30.09.2016 - 00:39
fonte
0

Il mio consiglio è di iniziare dall'esterno scrivendo prima il codice che usa l'entità. Pensa ai casi d'uso nella tua applicazione e scrivili nell'Ubiquitous Language del tuo dominio. Due esempi:

class ViewTranscript {

    // TODO populate using dependency injection or a service locator
    StudentRepository studentRepository;

    public StudentTranscript viewTranscript(String studentId) {     
        Student student = studentRepository.getStudent(studentId);
        StudentTranscript transcript = student.getTranscript();
        return transcript;
    }
}

e

class Enroll {

    // TODO populate using dependency injection or a service locator
    StudentRepository studentRepository;

    CourseRepository courseRepository;

    // I like having CourseEnrollment as a separate aggregate root 
    // but you could also have it as a child entity of student.
    CourseEnrollmentRepository courseEnrollmentRepository;

    public void enroll(String studentId, String courseId) {
        Student student = studentRepository.getStudent(studentId);
        Course course = courseRepository.getCourse(courseId);
        CourseEnrollment enrollment = selectedCourse.enroll(student);
        courseEnrollmentRepository.save(enrollment);
    }
}

Ora puoi iniziare ad implementare i metodi Course.enroll () e Student.getTranscript () poiché sai che sono effettivamente utili e ora sai quali parametri e tipo di ritorno dovrebbero avere.

Alcuni di voi potrebbero già urlare sulle classi ViewTranscript ed Enroll, ma vi assicuro, è perfettamente normale che DDD e Clean Architecture abbiano servizi applicativi che esercitano il modello di dominio chiamando metodi di alto livello, e ora il programmatore può iniziare a codificare la vera business logic nei metodi Course.enroll () e Student.getTranscript (). Le entità dovrebbero preferibilmente non conoscere i repository.

    
risposta data 30.09.2016 - 00:12
fonte

Leggi altre domande sui tag