¿Debería la instancia de Employee contener una referencia a la instancia de Office, o Office debería contener una matriz de Employee?

7

El título es una abstracción de lo que realmente estoy haciendo, pero en esencia es lo mismo.

La entidad principal con la que me ocuparé son los Employee s; "Enviar el paquete al empleado John Doe". Para trabajar con un Employee dado, necesito usar el IOffice al que pertenecen, y cada oficina tiene una forma diferente de entregar ese paquete a ese Employee . No estoy realmente interesado en cómo se entrega el paquete, solo que llega allí.

De la primera forma mencionada en el título, se vería algo así:

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
    }
}

Haciéndolo de esta manera, simplemente puedo tener una lista de todos los empleados, y los empleados en la misma oficina pueden compartir el mismo objeto IOffice .

El segundo enfoque así:

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
    }
}

Esto hace que sea más difícil tener una instancia de Employee y enviarle un paquete. Debe obtener la instancia que desee de la colección Employees y pasarla al método de envío de la oficina. Sin embargo, mantiene la clase Employee más simple y hace que IOffice se encargue de todo.

Probablemente hay otras formas de hacer esto también. ¿Cómo lo harías?

Editar : Para un ejemplo concreto, reemplace IOffice con un CommunicationInterface , como SerialPort , UdpClient , TcpClient etc.

Al final de cada punto final hay diferentes Devices ( Employees ). Todos estos dispositivos se comportan de manera similar, pero la forma de enviarles una solicitud ( Package ) y de obtener una respuesta es diferente.

Desde mi programa, quiero tener una lista de todos los dispositivos disponibles, en todas las interfaces de comunicación, y enviarles solicitudes y recibir respuestas.

    
pregunta Walkingsteak 09.07.2015 - 15:12

6 respuestas

5

Me resulta difícil dar soluciones generales de este tipo, ya que la arquitectura del sistema siempre depende en gran medida de todo el dominio.

Si la distribución de paquetes a los empleados es una de las principales preocupaciones de su sistema, tal vez ni Office ni el Empleado tengan que saber cómo se relacionan entre sí.

También podría pensar en una Entidad adicional de su sistema, como un Registro de Empleado, por ejemplo, que puede buscar en la Oficina una instancia de Empleado. De lo que puede entregar este paquete a la oficina.

En un paso adicional, puede encapsular este paso específico en una entidad de administrador de correo, que solo acepta un paquete y un empleado. Utiliza dicho registro para encontrar la Oficina y luego lo entrega.

    
respondido por el user186641 09.07.2015 - 15:35
2

Una cosa que veo con el primer ejemplo que podría generar confusión es que Employee no está enviando el paquete, están recibiendo el paquete. Creo que el método send lleva a la confusión de que Employee está enviando el paquete, cuando el Employee está recibiendo el paquete.

Creo que el segundo ejemplo es mejor. La clase SomeOffice tiene una razón para mantener una lista de Employee s y es la entidad que realizará el Send() si lo piensa en términos de una oficina real que podría enviar un paquete físico a un empleado.

    
respondido por el DFord 09.07.2015 - 15:29
1

La función send es una pista falsa, ya que no está relacionada con la pregunta básica, que es si debe hacer que cada empleado conozca su oficina, o si debe hacer que cada oficina sepa qué empleados están en ella. La función send no afecta, ni se ve afectada por, la respuesta a la pregunta básica. Probablemente no debería ser una función de Office o Employee ; es una preocupación de la aplicación, por lo que probablemente pertenece a la lógica de su aplicación. (Algunos objetos Application quizás.)

Ahora, parece entender que los dos enfoques son equivalentes: puede hacer que cada empleado conozca su oficina, o puede hacer que cada oficina sepa qué empleados están en ella.

Personalmente, me gustaría ir con el primer enfoque, ya que se asigna más fácilmente a un modelo de base de datos relacional, y esto tiene ventajas específicas. En una base de datos, este tipo de relación siempre se implementaría al incluir en cada fila de empleados la identificación de la fila de la oficina a la que pertenece el empleado. El hecho de que así se haga en las bases de datos relacionales debería ser, en sí mismo, razón suficiente para elegir este enfoque, pero si desea ejemplos específicos de por qué sería mejor, considere esto:

  1. Existe la posibilidad de error. Dos oficinas pueden, por error, contener al mismo empleado, en cuyo caso usted tiene datos inválidos. De hecho, en las bases de datos relacionales esto se denomina una relación de muchos a muchos, donde de hecho está permitido que muchas entidades de un tipo estén relacionadas con muchas entidades de otro tipo; pero su situación no requiere una relación de muchos a muchos, por lo tanto, no debe implementarse como si fuera una relación de muchos a muchos.

  2. Supongamos que desea eliminar un empleado. Si cada oficina tiene su propia lista de empleados, además de eliminar el objeto del empleado, ahora tiene que visitar todos sus objetos de oficina, ver si alguno de ellos contiene a ese empleado y, de ser así, eliminar al empleado de la lista. de los empleados de esa oficina.

respondido por el Mike Nakis 09.07.2015 - 17:45
0
  

Probablemente hay otras formas de hacer esto también. ¿Cómo lo harías?

Comenzaría considerando el límite entre el mundo real y el modelo digital. Employee y Office son entidades buenas, pero están en el mundo real; no puedes cambiar el mundo real enviando un comando a tu modelo.

Cuando pequeñas mesas de Bobby se inscribieron, el modelo se desechó, pero los estudiantes no se lastimaron.

Así que profundice: ¿cuál es la entidad controlada por el modelo que rastrea la información que desea? "EmployeeRecord" es un despeje, no incorrecto, pero demasiado superficial para ser de utilidad. Usted sabe lo que es: una relación entre el empleado y la oficina. Entonces, ¿Asignación de Office? Probablemente se parece a un EmployeeId, un OfficeID, ¿una fecha de inicio y finalización efectiva para cubrir los casos de uso donde el empleado se traslada?

Es posible que su caso de uso del paquete de envío no toque al Empleado ni a la Oficina. La interfaz de usuario del cliente crea una RoutingSpecification en función de la ubicación del el paquete y la identidad del destinatario, y una consulta de OfficeAssignments selecciona un OfficeId, que luego se utiliza para ejecutar una consulta en RoutingPolicies para determinar el Itinerario correcto para esta Entrega ....

    
respondido por el VoiceOfUnreason 19.05.2016 - 02:09
0

Lo que falta en los ejemplos de código es lo que está esperando que parezca que realmente interactúa con las clases.

Parece que está comenzando con una referencia a un empleado. En el primer enfoque, el envío de un paquete parece:

employee.Send(package);

Y en el segundo, más como:

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

La simplicidad del primer ejemplo parece ser la molestia de llevar la referencia de Office: no solo no tiene que realizar una búsqueda, sino que la existencia de la clase Office está completamente oculta por esta interfaz.

Si está barajando a los empleados con frecuencia, necesita atravesar la relación en ambas direcciones y le preocupa la consistencia, entonces puede hacer que las propiedades de .Office y .Employees delegen en una tercera clase que realmente mantiene esa relación. Eso es más o menos cómo funcionan los ORM.

    
respondido por el user2313838 19.05.2016 - 06:23
0
  

... Necesito usar el IOffice al que pertenecen, y cada oficina tiene un   diferente forma de entregar ese paquete a ese Employee .

Me parece que el código debe ser específico del empleado en lugar de la oficina, el paquete y el empleado. Cada empleado debe implementar su propia forma de recibir un paquete y cada oficina solo sabrá que cada empleado puede recibir un paquete.

Comenzaría con la creación de una clase de empleado abstracta:

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

La implementación de la clase

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
    }
}

Cuando la oficina envíe un paquete a cada uno de sus empleados, utilizará cada método de recepción de empleados y su código será específico para cada tipo de empleado

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

    public void Send(Package package, Employee employee)
    {
        employee.Receive(package);
    }
}
    
respondido por el Marcus H 19.05.2016 - 08:55

Lea otras preguntas en las etiquetas