sorprendente que sólo fue capaz de encontrar uno en la pregunta anterior SO sobre este tema, y yo sólo quisiera obtener el "voto de confianza" de la comunidad (o no!) En mi enfoque.Debug.Assert vs excepciones
La forma en que veo que es así:
- uso
Debug.Assert
decir las cosas que se pueden esperar sería verdad. Esto se usaría cuando tengamos un control total sobre nuestro entorno, por ejemplo, en un método verifique algunas condiciones previas y posteriores. - use Excepciones cuando surgen circunstancias excepcionales. Tratar con recursos externos, es decir, archivos, bases de datos, redes, etc. es una obviedad. Pero ...
Se pone un poco turbio en el siguiente escenario. Tenga en cuenta que este es un EJEMPLO CONTRARIO solo para ilustración.
Digamos que tenemos class MiClase, que tiene un Mi modo la propiedad pública y un método GetSomeValueForCurrentMode()
. Considere MyClass como uno destinado a ser enviado (lanzamiento incorporado) en una biblioteca para uso de otros desarrolladores.
Esperamos Mi modo de ser actualizado por los usuarios externos de esta clase. Ahora, GetSomeValueForCurrentMode()
tiene la siguiente lógica:
switch(MyMode)
{
case Mode.ModeA:
return val1;
case Mode.ModeB:
return val2;
default:
//Uh-uh this should never happen
}
Lo que quiero decir aquí es que el usuario de MiClase ha dejado en un estado no válido. ¿Entonces, qué debemos hacer?
En el valor predeterminado, ¿deberíamos Debug.Assert
o throw new InvalidOperationException
(u otro)?
Hay un mantra que dice que no debemos confiar en los usuarios de nuestras clases. Si seleccionamos Debug.Assert y construimos MyClass como una versión de lanzamiento (eliminando así las Aserciones de depuración), el usuario de la clase no obtendría información útil de que la había dejado en un estado no válido. Pero es un poco contrario al otro mantra que dice que solo arroja excepciones cuando suceden cosas completamente fuera de tu control.
encuentro que dar vueltas con esto - uno de esos debates de programación que no parecen tener una respuesta definitiva 'correcta'. ¡Así que pongámoslo a votación!
Editar: me di cuenta de esta respuesta en una cuestión de forma relacionada (Design by contract using assertions or exceptions?):
La regla de oro es que usted debe usar aseveraciones cuando se está tratando de atrapar sus propios errores y excepciones cuando se trata de captar los errores de otras personas En otras palabras, debe usar excepciones para verificar las condiciones previas para las funciones API públicas, y cada vez que obtenga datos que sean externos a su sistema. Debe usar afirmaciones para las funciones o datos que son internos a su sistema.
Para mí, esto tiene sentido, y se puede combinar con la técnica 'Assert then throw' descrita a continuación.
Pensamientos ¡bienvenidos!
Chris, arrojar una excepción de "contrato roto" (que solo puede indicar un error) no es "fallido rápido", es "error medio rápido": primero tiene que suceder un montón de desenrollado de la pila. Abortar allí mismo cuando detecte el incumplimiento de contrato sería el verdadero "fracaso rápido". –
Y. Lo siento todos. Quité la referencia a "Fail Fast". Si desea utilizar FailFast, puede usar Environment.FailFast() en C# en lugar de lanzar una excepción. Pero ten en cuenta que tus bloques finalmente no se ejecutarán. – ChrisV
Considere el uso de [fluentassertions] (http://fluentassertions.com/). Ayuda a crear contratos legibles y al mismo tiempo arroja excepciones si se violan los contratos. –