2010-06-08 8 views
8

Estaba buscando un código que heredé y no pude decidir si me gusta un poco de código.¿Debería un método de conexión devolver un valor?

Básicamente, hay un método que tiene el siguiente aspecto:

bool Connect(connection parameters){...} 

Devuelve cierto si se conecta correctamente, en caso contrario.

He escrito un código como ese en el pasado, pero ahora, cuando veo este método no me gusta por una serie de razones.

  1. Es un código fácil de escribir que simplemente ignora el valor devuelto, o no se da cuenta de que devuelve un valor.

  2. No hay forma de que devuelva un mensaje de error.

  3. Comprobación del retorno del método en realidad no se ven bien:

    si {....}

pude volver a escribir código para (Connect (...)!) lanza una excepción cuando no se conecta con éxito, pero no considero que sea una situación excepcional. En vez estoy pensando en refactorización el código como sigue:

void Connect(Connection Parameters, out bool successful, out string errorMessage){...} 

Me gustaría que otros desarrolladores tienen que proporcionar las cadenas de éxito y error para que sepan el método tiene las condiciones de error y puedo saber devolver un mensaje

¿Alguien tiene alguna idea al respecto?

Gracias -Matt

Respuesta

3

Tengo solo una opinión, así que tómalo por lo que vale la pena.

Un método llamado así, "Conectar", es un pedido. Es como dárselo a un soldado, "saltar" o "disparar". No esperas que el soldado responda a menos que no pueda completar el pedido, y eso sería un acontecimiento raro.

Como tal, tengo la tendencia a no tener un valor de retorno para tales métodos, pero si hay una posibilidad de que bajo el uso regular del método, haya fallas, entonces construyo un segundo método, llamado TryXYZ, devolviendo un bool y, si es necesario, proporcionándome los resultados de cualquier XYZ como parámetros de salida.

Esto sigue el estándar establecido por los métodos Parse de varios tipos numéricos en .NET BCL.

Así, en su caso, que probablemente tendría:

void Connect(connection parameters); 
bool TryConnect(connection parameters, out status); 

Lo bueno es que si se construye el método TryConnect adecuadamente, Conectar hace realmente fácil.

Ejemplo:

public bool TryConnect(string connectionString, out ConnectionStatus status) 
{ 
    ... try to connect 
    ... set status, and return true/false 
} 

public void Connect(string connectionString) 
{ 
    ConnectionStatus status; 
    if (!TryConnect(connectionString, out status)) 
     switch (status) 
     { 
      case ConnectionStatus.HostNotFound: 
       throw new HostNameNotFoundException(); 
      ... 
     } 
} 

No espero que mis órdenes a no completa, pero en el sentido de que podría, quiero ser explícita al respecto.

+0

Me gusta este enfoque. Ciertamente deja las cosas claras. Creo que combinar el método TryConnect (...) con la sugerencia de Foovanadil de un tipo de devolución personalizado es lo que voy a hacer. –

+0

Si su conexión es de corta vida, también podría considerar la posibilidad de regresar IDisposable para permitir una fácil limpieza de la conexión como sigue: usando (var connection = connect (...)) // –

12

optaría por la excepción frente a los parámetros out. Si desea que a los consumidores de su clase les importe, haga que se preocupen por la Excepción, o de lo contrario, déjenlos en paz. Al usar los parámetros de salida, simplemente está haciendo que sus vidas sean más incómodas si no lo hacen, tiene para que les importe usar variables desechables. También considere que si su función ya está en libertad, está introduciendo un cambio de rotura si cambia la firma (en lugar de proporcionar una sobrecarga adicional).

Los programadores esperan excepciones en casos de error, especialmente en idiomas como C#. Hemos sido entrenados.

+1

Estoy de acuerdo con esta respuesta. Normalmente, no poder conectarse a algo se considera un caso excepcional y suele tratarse como tal en .NET Framework (ADO.NET, WCF). Devolver un par de mensaje de error/éxito es la programación de estilo API de Windows de la vieja escuela: es mucho más agradable manejar una excepción fuertemente tipada con un try/catch (y esta es la convención). Si tiene las herramientas a su disposición, debe usarlas. – luksan

1

Veo sus puntos, pero para agregar mi 2c.

Por lo general, no soy partidario de los parámetros de salida. Si necesita devolver múltiples valores de una función, vuelva a evaluar qué está haciendo la función, en la mayoría de los casos, los valores de retorno múltiples son una señal de que un método hace demasiado. En su caso, es legítimo que se devuelva un tipo complejo desde su método de conexión (más allá de un simple booleano).

Estoy a favor de devolver un tipo personalizado del método de conexión que almacena toda la información relevante en lugar de múltiples parámetros de salida. Piense en la extensibilidad futura, ¿qué pasa si necesita incluir más información en el futuro?Agregar parámetros de salida adicionales es un cambio de rotura

Además, tiendo a estar en desacuerdo con forzar a un usuario a proporcionar asignaciones de memoria para todos los datos de estado. Puede haber momentos en los que no me importa el mensaje de éxito (tal vez solo me importa si se produce un error) en cuyo caso tener que pasar los dos parámetros de salida es un problema.

Estoy de acuerdo en que no es ideal verificar el valor de retorno del método inicial publicado.

0

No estoy seguro de si esto es mejor que su código de refactorización, pero espero que esto podría darle otra idea.

Para mis proyectos, creo un método que devuelve el último mensaje de error.

string Error = ''; 
bool Connect(connection parameters) 
{ 
// do my connection here 
// if there's an error set string variable Error 
// This way you can set different error message depending on what you're doing 
} 

string lastErrorMessage(){ 
// return Error string 
} 

De esta manera usted puede hacer esto:

if(!connect(...)) 
{ 
string message = lastErrorMessage(); 
// Then do what you need here. 
} 

esto podría no ser la mejor manera, pero debe ayudarle :)

1

no me importa la función Conectar devolver un valor lógico y no soy un gran admirador de los parámetros de salida. Si la función no devolvió el estado de conexión, es probable que tenga que escribir una función/propiedad IsConnected (dependiendo de su estilo) de todos modos para permitir que alguien la revise, por lo que guarda un paso.

En lo que respecta a las expectativas, permita que la excepción quede atrapada por el código de llamada, que forzará a la persona que llama a importar. :)

1

Acepto que no establecer una conexión (en la mayoría de los casos) no debe considerarse como una situación excepcional. Sin embargo, forzar al usuario a proporcionar argumentos para la cadena de error, etc. tampoco es agradable. Otras posibles soluciones:

  1. Utilice el registro. El inconveniente es que los mensajes se escriben en el registro, pero no (sin mucho esfuerzo) disponibles para quien llama.
  2. Uso retorno boolean y proporcionar métodos para consultar el último error (como errno en C). En mi humilde opinión tampoco es agradable.
  3. refactorizar su código, devuelven un objeto de una clase de conexión. Proporcione métodos para consultar el estado de la conexión.
  4. devolver una instancia de una clase que reúne toda la información pertinente, también conocido como isSuccessfull(), GetErrorString, etc.
Cuestiones relacionadas