2009-10-11 8 views
5

¿Existen mejores prácticas para devolver diferentes tipos de devolución en métodos sobrecargados? Por ejemplo, si tengo un método Load en mi DAL, o deseo cargar un solo elemento o un grupo de elementos. Sé que podría utilizar una serie de enfoques:¿Debo usar diferentes tipos de devolución en métodos sobrecargados?

Cargar un objeto

MyBusinessObject LoadOne(int id) 
{ 
} 

cargar varios objetos

MyBusinessObject[] LoadMany(params int[] ids) 
{ 
} 

Ahora algo que sé que puede hacer es sobrecargar un método y tener diferentes tipos de devolución. De este modo:

MyBusinessObject Load(int id) 
{ 
} 

Y

MyBusinessObject[] Load(params int[] ids) 
{ 
} 

Aunque parece que no hay nada que dejara de hacer esto, y que mantiene las cosas ordenadas desde una perspectiva API, sí parece esto como una buena idea? Lo descubrí anoche y una parte de mí piensa que no debería estar haciendo esto por el deseo de hacer coincidir los tipos de devolución para el método sobrecargado.

También podría hacer que el método Load (int id) devuelva una colección que solo contiene un elemento. Me parece que esto viola el principio de la menor sorpresa, aunque si esperas que se devuelva un artículo, debes devolverlo, no debes devolver una lista que contenga un solo artículo.

Así que aquí están mis pensamientos contradictorios que rodean estas ideas:

  • Los métodos sobrecargados todos deben devolver el mismo tipo.
  • Si los métodos hacen lo mismo, no les dé un montón de nombres diferentes, sobrecargue el mismo nombre de método. Hace las cosas más simples desde la perspectiva de un usuario API, no tienen que navegar a través de un montón de métodos diferentes que esencialmente hacen lo mismo pero con diferentes parámetros.
  • Devuelva el tipo más obvio para el método, es decir, si el usuario probablemente espera una colección de artículos, devuelva una colección de artículos, si es probable que esperen un solo artículo, devuelva un solo artículo.

De modo que las dos últimas ideas superan a la primera, pero al mismo tiempo, el primer pensamiento parece una especie de práctica programática.

¿Existen mejores prácticas en esta práctica? Me interesaría escuchar los pensamientos de otros sobre el tema.

+0

En cualquier caso, considere devolver 'IEnumerable 'en lugar de una matriz. Eric Lippert tiene una gran publicación en el blog sobre esto. –

+0

devolver una matriz es suficiente para resaltar el escenario. Volvería un IEnumerable en mi código actual. – BenAlabaster

+0

De acuerdo, genial. Siempre que estés enterado. –

Respuesta

8

que podría estar tentado de hacer explícita la API y el uso pluralidad en los nombres:

Customer LoadCustomer(int id) {...} 
Customer[] LoadCustomers(params int[] id) {...} 

En realidad, el params rara vez es útil en este caso - que normalmente no conoce los identificadores en tiempo de compilación.

+0

En referencia a los params, entiendo su punto, pero estaba resaltando un concepto en lugar de una ruta de código real. Me imagino que en un escenario de la vida real estaría pasando información de filtrado que devolvería potencialmente una lista de artículos en lugar de un solo elemento. Me gusta la idea de pluralidad, ciertamente mantendría los múltiples métodos juntos en intellisense. – BenAlabaster

0

Mi idea personal es que este último método parece más comprensible desde la perspectiva del usuario API.

3

Puede simplemente mirar a una API existente. Tomemos LINQ por ejemplo, tiene el método "Seleccionar" que devuelve muchas entidades y también el método "Único" que devuelve solo una entidad. La mayoría de las API existentes tiene dos métodos diferentes, no uno sobrecargado, y creo que esto es lógico y más legible.

+0

Pero también significa que su API está llena de muchos métodos que hacen lo mismo. – BenAlabaster

+0

Además de eso, seguir las API de otras personas como ejemplo no lo ayuda a comprender sus procesos de pensamiento por haberlo diseñado de esa manera. Prefiero ver media docena de ejemplos * diferentes con procesos * thought que un montón de API sin ellos. De esta manera puedo tomar una decisión informada en lugar de solo seguir ciegamente el ejemplo de otra persona. – BenAlabaster

+0

No soy un seguidor ciego =) Escribí mi opinión, y las tecnologías líderes merecen mi atención como mínimo. Por cierto, obtener una entidad y obtener múltiples entidades no es lo mismo. – Restuta

2

Tiendo a seguir el primer punto en su lista de "pensamientos que rodean esta idea" que dice "las sobrecargas deben regresar del mismo tipo".

pero luego puede sobrecargar el "LoadMany" con algunos escenarios diferentes;

public Customer Load(int id) 
{ 
    // return just one customer 
} 

public List<Customer> LoadMany() 
{ 
    // return every single customer 
} 

public List<Customer> LoadMany(int statusFilter) 
{ 
    // return a filtered list of customers 
} 

public List<Customer> LoadMany(DateTime InitialContactFrom) 
{ 
    // return a filtered list of customers 
} 

public List<Customer> LoadMany(DateTime InitialContactFrom, DateTime InitialContactBefore) 
{ 
    // return a filtered list of customers 
} 

... cualquier combinación que necesite obviamente se puede agregar, pero al final, LoadMany devuelve una lista y Load devuelve una entidad.

3

Probablemente existan excepciones, pero a menos que tenga una muy buena razón para devolver tipos diferentes, una función y sus sobrecargas deberían devolver el mismo tipo para que no vuelva locos a otros desarrolladores.

Por ejemplo:

var a = MyFunc("Some text"); 

y

var a = MyFunc(1); 

tanto parecen que deben resolver el var al mismo tipo para mí. Antes de que me desviara de tener todas las sobrecargas para devolver el mismo tipo, me aseguraba de tener una razón muy sólida para devolver diferentes tipos.

+0

De acuerdo, no había considerado la perspectiva var, que en realidad infringe mi principio de hacer que cada línea sea lo más comprensible posible con referencia a la menor cantidad de código posible. – BenAlabaster

Cuestiones relacionadas