L'istanza di Dipendente deve contenere un riferimento all'istanza di Office o Office deve contenere una matrice di Dipendente?

7

Il titolo è un'astrazione di ciò che sto effettivamente facendo, ma in sostanza è lo stesso.

L'entità principale con cui mi occuperò sono i Employee s stessi; "Invia il pacco al dipendente John Doe". Per lavorare con un dato Employee , ho bisogno di usare il IOffice a cui appartengono, e ogni ufficio ha un modo diverso di consegnare quel pacchetto a quel Employee . Non mi interessa veramente come il pacchetto viene consegnato, solo che arriva lì.

Nel primo modo menzionato nel titolo, sarebbe simile a questo:

public class Employee
{
    private IOffice _office;

    public Name { get; set; }

    public void Send(Package package)
    {
        _office.Send(package, this)
    }
}

public class SomeOffice : IOffice
{       
    public void Send(Package package, Employee employee)
    {
        // Implementation of how this office gets the package to employee
    }
}

In questo modo, posso semplicemente avere un elenco di tutti i dipendenti e i dipendenti nello stesso ufficio possono condividere lo stesso oggetto IOffice .

Il secondo approccio in questo modo:

public class Employee
{       
    public Name { get; set; }
}

public class SomeOffice : IOffice
{
    public List<Employee> Employees { get; set; }

    public void Send(Package package, Employee employee)
    {
        // Implementation of how this office gets the package to employee
    }
}

Questo rende più difficile avere un'istanza di Employee e inviare un pacchetto ad esso. Devi ottenere l'istanza desiderata da Employees -collection e passarla nel metodo di invio dell'ufficio. Tuttavia, mantiene la classe Employee più semplice e fa in modo che IOffice si occupi di tutto.

Ci sono probabilmente anche altri modi per farlo. Come lo faresti?

Modifica : Per esempio concreto, sostituisci IOffice con CommunicationInterface , ad esempio SerialPort , UdpClient , TcpClient ecc.

Alla fine di ogni endpoint ci sono diversi Devices ( Employees ). Questi dispositivi si comportano tutti allo stesso modo, ma come inviarli una richiesta ( Package ) e ottenere una risposta diversa.

Dal mio programma, voglio avere un elenco di tutti i dispositivi disponibili, attraverso tutti i CommunicationInterfaces, e inviare richieste a loro, e ottenere risposte indietro.

    
posta Walkingsteak 09.07.2015 - 15:12
fonte

6 risposte

5

Trovo difficile dare soluzioni generali di questo tipo poiché l'architettura del sistema dipende sempre molto dall'intero dominio.

Se il routing dei pacchetti ai dipendenti è una preoccupazione principale nel tuo sistema, forse né l'ufficio né il dipendente devono sapere in che modo si relazionano tra loro.

Potresti anche pensare a un'entità aggiuntiva del tuo sistema, come ad esempio un EmployeeRegister, che può cercare l'istanza di Office for a Employee. Di quanto tu possa consegnare questo pacchetto all'Ufficio.

In un ulteriore passaggio, puoi incapsulare questo passaggio specifico in una Entità Postmaster, che accetta solo un Pacchetto e un Dipendente. Utilizza tale registro per trovare l'Office e quindi lo consegna.

    
risposta data 09.07.2015 - 15:35
fonte
2

Una cosa che vedo con il primo esempio che potrebbe portare a confusione è che Employee non sta inviando il pacchetto, stanno ricevendo il pacchetto. Penso che il metodo send porti alla confusione che il Employee sta inviando il pacchetto, quando Employee sta ricevendo il pacchetto.

Penso che il secondo esempio sia migliore. La classe SomeOffice ha un motivo per mantenere un elenco di Employee s ed è l'entità che eseguirà Send() se ci pensi in termini di un ufficio reale che potrebbe inviare un pacchetto fisico a un dipendente.

    
risposta data 09.07.2015 - 15:29
fonte
1

La funzione send è un'aringa rossa, perché non è correlata alla domanda di base, ovvero se è necessario che ogni dipendente conosca il proprio ufficio o se sia necessario che ogni ufficio sappia quali dipendenti ci sono dentro. La funzione send non influisce, né è influenzata da, la risposta alla domanda di base. Probabilmente non dovrebbe essere una funzione di Office o Employee ; è un problema di applicazione, quindi probabilmente appartiene alla logica dell'applicazione. (Qualche oggetto Application forse.)

Ora sembra che tu capisca che i due approcci sono equivalenti: puoi far conoscere a ciascun dipendente il loro ufficio o puoi far sapere a ciascun ufficio quali dipendenti ci sono dentro.

Personalmente, andrei con il primo approccio, perché si associa più facilmente a un modello di database relazionale, e questo ha vantaggi specifici. In un database, questo tipo di relazione verrebbe sempre implementato includendo in ogni riga del dipendente l'ID della riga dell'ufficio a cui appartiene il dipendente. Il fatto che questo sia il modo in cui viene fatto nei database relazionali dovrebbe, in sé e per sé, essere una ragione sufficiente per scegliere questo approccio, ma se vuoi esempi specifici del perché sarebbe meglio, considera questo:

  1. C'è una possibilità di errore. Due uffici possono, per errore, contenere lo stesso dipendente, nel qual caso si hanno dati non validi. Di fatto, nei database relazionali si parla di una relazione molti-a-molti, dove è in effetti consentito che molte entità di un tipo siano correlate a molte entità di un altro tipo; ma la tua situazione non richiede una relazione molti-a-molti, quindi non dovrebbe essere implementata come se fosse una relazione molti-a-molti.

  2. Supponiamo di voler eliminare un dipendente. Se ogni ufficio ha il proprio elenco di dipendenti, oltre a eliminare l'oggetto dipendente, è necessario visitare tutti gli oggetti dell'ufficio, vedere se uno di essi contiene quel dipendente e, in tal caso, rimuovere il dipendente dall'elenco. dei dipendenti di quell'ufficio.

risposta data 09.07.2015 - 17:45
fonte
0

There are probably other ways to go about this also. How would you do it?

Vorrei iniziare considerando il confine tra il mondo reale e il modello digitale. Employee e Office sono entità fini, ma sono nel mondo reale; non puoi cambiare il mondo reale inviando un comando al tuo modello.

Quando sono stati registrati piccoli tavoli Bobby , il modello è stato distrutto, ma gli studenti non si sono fatti male.

Quindi scavare più strong: qual è l'entità controllata dal modello che tiene traccia delle informazioni che vuoi? "EmployeeRecord" è un punt, non sbagliato, ma troppo superficiale per essere utile. Sai qual è la cosa - una relazione tra Dipendente e Ufficio. Quindi - OfficeAssignment? Probabilmente sembra un EmployeeId, un OfficeID, una data di inizio e fine efficace per coprire i casi di utilizzo in cui il dipendente si trasferisce?

Il caso di utilizzo del pacchetto di invio potrebbe non toccare affatto Employee o Office. L'interfaccia utente del client crea una RoutingSpecification in base alla posizione del pacchetto e l'identità del destinatario e una query di OfficeAssignments preleva un ID di Office, che viene quindi utilizzato per eseguire una query sui RoutingPolicies per determinare l'itinerario corretto per questa consegna ....

    
risposta data 19.05.2016 - 02:09
fonte
0

Ciò che manca negli esempi di codice è ciò che ti aspetti sembrerà effettivamente interagire con le classi.

Sembra che tu stia iniziando con un riferimento a un Dipendente. Nel primo approccio, l'invio di un pacchetto è simile a:

employee.Send(package);

E nel secondo, più simile a:

var office = offices.Find(o => o.Employees.Contains(employee));
office.Send(package, employee);

La semplicità del primo esempio sembra valere la pena di portare in giro il riferimento Office: non solo non è necessario eseguire una ricerca, ma l'esistenza della classe Office è completamente nascosta da questa interfaccia.

Se stai spostando frequentemente dipendenti, devi attraversare la relazione in entrambe le direzioni e sei preoccupato per la coerenza, quindi puoi delegare le proprietà .Office e .Employees a una terza classe che mantiene effettivamente tale relazione. È più o meno come funzionano gli ORM.

    
risposta data 19.05.2016 - 06:23
fonte
0

...I need to use the IOffice they belong to, and each office has a different way of delivering that package to that Employee.

Mi sembra che il codice debba essere specifico per il dipendente piuttosto che specifico per ufficio, pacchetto e dipendente. Ogni dipendente dovrebbe implementare il proprio modo di ricevere un pacco e ogni ufficio saprà solo che ogni dipendente può ricevere un pacco.

Vorrei iniziare con la creazione di una classe dipendente astratta:

public abstract class Employee
{       
    public Name { get; set; }
    public abstract void Receive(Package Package)
}

L'implementazione della classe

public class Boss: Employee
{       
    public override void Receive(Package Package)
    {
        //Handle specific receive for the boss
    }
}
public class Programmer: Employee
{       
    public override void Receive(Package Package)
    {
        //Handle specific receive for the real boss
    }
}

Quando l'ufficio invia un pacchetto a ciascuno dei suoi dipendenti, utilizzerà ciascun metodo di ricezione dei dipendenti e il codice sarà specifico per tipo di dipendente

public class SomeOffice: IOffice
{
    public List<Employee> Employees { get; set; }

    public void Send(Package package, Employee employee)
    {
        employee.Receive(package);
    }
}
    
risposta data 19.05.2016 - 08:55
fonte

Leggi altre domande sui tag