Quando utilizzare un repository / servizio vs una variabile di istanza?

3

Quando un oggetto appartiene veramente a una classe? Ho familiarità con la relazione "ha-a", ma nel caso di un oggetto Employee, ha "un-un" 401k, ma non è realmente composto da un oggetto 401k. Come dipendente, il mio 401k non mi rende quello che sono.

Quello che sto ottenendo è che non dovrei aver bisogno di raggiungere l'oggetto Impiegato per arrivare al suo 401k. L'aderenza a questo sarebbe considerata l'aderenza alla Legge di Demetra (ad esempio A (). B (). C (). D ()), che vorrei seguire.

Inoltre, un oggetto Employee ha molti attributi come EmployeeID, age, dateOfBirth, ecc. Potresti finire con attributi infiniti solo per un Dipendente, che ricade tutti sotto la stessa responsabilità.

Nel caso di un 401K, non gestisce lo stesso 401k, quindi il Dipendente aderisce ancora al Principio di Responsabilità Unica, ma ne ha "uno". Hai solo bisogno di raggiungere attraverso l'oggetto Impiegato per ottenere il suo 401k. Perfino un Supervisore non compone davvero un Dipendente. Simile a 401k, forse EmployeeRepository dovrebbe avere un metodo FindSupervisor (Employee employee).

È qui che un repository & il servizio arriva?

class Employee
{
  public Employee(401k 401k) {...}

  public 401K Get401K() 
  { 
    return 401k; // EWW! No, does not follow LoD
  } 

  public Money Calculate401k() 
  { 
    return 401k.calculate(); // Ugly and breaks SRP?  No Employee should calculate 401k just to follow LoD...
  } 

  private 401K 401k;
}

class 401K
{
  public void MakeContribution(IContribution contribution) 
  {
    //add contribution
  }

  public Money Calculate(ICalculator calculator) 
  {
    //calculate & return money object
  }
}

VS

class Employee
{
  public int Age() {//calculate age with dob...}
  // Other employee-specific methods

  private string name;
  private DateTime dob;
  // other employee-specific attributes
}

class 401kRespository
{
  public 401K FindByEmployee(Employee emp) {// return 401k of Employee);
  // More 401KRepo functions...
}

class 401K
{
  public void MakeContribution(IContribution contribution) {//add contribution}
  public Money Calculate(ICalculator calculator) {//calculate}
}
    
posta keelerjr12 15.12.2017 - 01:57
fonte

2 risposte

1

L'ambiguità della composizione

Una relazione ha-un indica che composizione è usato instead di un'eredità is-a .

Nella programmazione orientata agli oggetti, composizione significa solo una combinazione di elementi. Ad esempio la classe Employee combinerebbe diversi membri come name , address , currentJob e così via. La composizione per 401k significa aggiungere un membro 401k . E quindi, non ci sarebbe dubbio che il membro della classe ha-un 401k. In questo contesto, has-a riguarda i membri della classe.

Nella modellazione orientata agli oggetti, composizione ha un significato più specifico: è una strong relazione parte intera , in cui le parti non sono condivise (secondo UML). Qui, has-a riguarda gli oggetti della classe. E hai ragione, il piano pensionistico 401k non fa parte di un dipendente.

Modellazione del dominio

Nel tuo dominio, esiste definitivamente un'associazione tra Employee e 401K .

Le prossime domande riguardano l'interdipendenza tra le due classi:

  • Navigabilità di questa associazione: navighi solo da Employee a 401K (caso 1) o devi anche navigare in entrambe le direzioni, ad es. da un 401K al corrispondente Employee e viceversa (caso 2)?

  • Aggregato o no: sono Employee e 401K da intendere come un tutto ai fini della modifica dei dati (caso 1) o possono essere modificati indipendentemente l'uno dall'altro (caso 2)?

Conclusione

Secondo la tua spiegazione, capisco che il caso 2 sembrerebbe più appropriato. Quindi avresti 2 repository: uno per i dipendenti e uno per i piani.

    
risposta data 16.12.2017 - 17:48
fonte
1

As an employee, my 401k does not make me who I am.

401k non deve essere una parte di un'identità di Employee . Se si identificano i concetti di stato e identità (trattando così tutti i tuoi oggetti come immutabili), ottenendo (calcolando?) il suo 401k potrebbe essere una parte del suo comportamento. Questo approccio si allinea con il principio di accesso uniforme .

What I'm getting at is, I don't feel that I should need to reach into the Employee object to get to his 401k. Adherence to this would be considered adherence to the Law of Demeter

Law of Demeter, come la vedo io, si occupa di proteggere l'incapsulamento. Non consente di rivelare la struttura interna dell'oggetto. Mentre non vedo alcun problema nel chiamare in sequenza i metodi degli oggetti, che rappresentano il comportamento che viene estratto dietro un'interfaccia.

Additionally, an Employee object has a lot of attributes like an EmployeeID, age, dateOfBirth, etc.

Non è necessario - in teoria, almeno :) Esporre il comportamento al posto dei dati semplici, se possibile. Anche se mi rendo conto che devi usare un framework ORM. Ad ogni modo, il fatto che tu mantenga un riferimento esplicito al tuo oggetto 401k è solo un dettaglio di implementazione indotto dall'ORM, se ho capito bene. E

Detto questo, rendere 401k una parte del tuo dipendente o meno è più una questione di semantica. Personalmente, non posso immaginare 401k senza un dipendente. E il dipendente deve avere un 401k (correggimi se sbaglio, non sono degli Stati Uniti). Quindi è probabile che tu voglia trattare un dipendente come radice aggregata , con 401k nascosto dietro il suo limite di incapsulamento.

    
risposta data 15.12.2017 - 16:24
fonte