2012-04-19 12 views
7
public class PageNotFoundException : HttpException 
{ 
    public PageNotFoundException() 
     : base(404, "HTTP/1.1 404 Not Found") 
    { 

    } 
} 

La idea es que en lugar de escribir esto cada vez¿Es esta una buena práctica para una excepción personalizada?

throw new HttpException(404, "HTTP/1.1 404 Not Found") 

Prefiero escribir

throw new PageNotFoundException(); 

que iba a añadir una sobrecarga para la inclusión de la InnerException sin embargo nunca a utilizar esto en un bloque try/catch.

¿Consideraría esta buena práctica?
es decir Heredar de una excepción y pasar información codificada a la base (...).

Respuesta

4

Decidí reescribir mi respuesta para que sea específica para su pregunta real, y en un sentido más amplio que una aplicación MVC no es la única a la que se aplican estas mejores prácticas.

(1) Respuesta. Esto no es una buena práctica. En su lugar, debe usar un método de creación de excepción que arroje HttpException directamente.

public static void ThrowPageNotFoundException() { 
    throw new HttpException((Int32)HttpStatusCode.NotFound, "HTTP/1.1 404 Not Found"); 
} 

(2) DO. Use métodos de creación de excepciones (por ejemplo, el código que proporcioné). Esto le permite evitar el costo de rendimiento adicional de tener su propio tipo de excepción, y permite que esté en línea. Los miembros que lanzan excepciones no son incluidos. Este sería el sustituto adecuado para tirar por conveniencia.

(3) DO.Utilice excepciones de biblioteca de clase base siempre que sea posible, y solo cree una excepción personalizada cuando no haya absolutamente ninguna excepción base que cumpla con los requisitos necesarios. La creación de excepciones personalizadas agrega una jerarquía de excepciones más profunda, lo que hace que la depuración sea más difícil cuando no es necesario, agrega una sobrecarga de rendimiento adicional y también agrega un exceso de inflado a su base de código.

(4) NO. Lanza la clase base System.Exception. Use un tipo de excepción específico en su lugar.

(5) NO. Crea excepciones personalizadas para mayor comodidad. Esta no es una buena razón para una excepción personalizada, porque las excepciones son intrínsecamente costosas.

(6) NO. Crea excepciones personalizadas solo para tener tu propio tipo de excepción.

(7) NO. Lanza excepciones que se pueden evitar cambiando el código de llamada. Esto sugeriría que tiene un error de usabilidad en la API en lugar de un problema real.

Cualquier persona que haya leído las Pautas de diseño de Framework de la serie de desarrollo .NET conocerá estas prácticas, y son muy buenas prácticas. Estas son las prácticas sobre las que se construyó el framework .NET, y MVC también.

+0

Es un sitio web de MVC. Al solicitar una entidad con ID que no existe, arrojo un error 404. ¿Qué hay de malo con eso? StackOverflow usa este método. Intenta ir a http://stackoverflow.com/questions/1022181121312312331 – Marko

+1

Las excepciones son cualquier cosa menos rápidas. Lanzar una excepción ocurre en estados excepcionales: un método en línea no tiene sentido en este caso. – zmbq

+0

Incorrecto. Uno de los errores más comunes es que los desarrolladores a menudo piensan que las excepciones son por condiciones excepcionales. El rendimiento y las optimizaciones con excepciones SI importan. –

2

Si eres el que lanza la excepción en primer lugar, entonces sí, está bien. Sin embargo, si atrapa un HttpException y luego intenta lanzar un PageNotFoundException en su lugar, debe colocar la excepción original como InnerException.

+0

Como se mencionó anteriormente ... "Iba a agregar una sobrecarga para incluir la innerException, pero nunca la utilizaré en un bloque try/catch". – Marko

+0

Oh, ¿eso es lo que querías decir? OK entonces. Entonces es una buena práctica. – zmbq

1

Si bien esta es una buena construcción en su propio código para su propio uso, una consideración es que puede promover la codificación por convención, que puede ser peligrosa cuando se trata de otros/nuevos desarrolladores.

En sus propias bibliotecas, si es coherente al lanzar una PageNotFoundException cada vez que se lanza una excepción HttpException 404, podría tener más sentido que catch (PageNotFoundException). Sin embargo, cuando empiece a usar otras bibliotecas que no tengan su excepción personalizada, perderá 404 HttpExceptions lanzadas por otro código. Del mismo modo, si tiene otros desarrolladores contribuyendo en una fecha posterior (o incluso sus propias adiciones en el futuro), la consideración de que PageNotFoundExceptions es lo que está siendo capturado por la mayoría de la funcionalidad se puede perder y se pueden arrojar 404 HttpExceptions nuevos en los nuevos módulos , que tampoco sería atrapado por el código de llamada copiado/pegado.

Básicamente, construcciones como esta aumentan el tiempo de aclimatación requerido para trabajar en el proyecto, y deben manejarse de tal manera que este costo se minimice (se haga suficientemente visible en una biblioteca central de objetos compartidos fácil de encontrar que no ya demasiado abarrotado).

Por otro lado, sin duda hay un valor en la centralización de la generación de sus HttpExceptions si lo que busca es esencialmente los beneficios del patrón de fábrica; puede valer la pena ir con eso en su lugar si eso es lo que intentas obtener de él (throw ExceptionFactory.NewPageNotFound()).

+0

Piénsalo así. Es un sitio web de MVC que trata con muchas entidades diferentes. Digamos Usuario en nuestro caso. Cuando un usuario no existe, lanzo una excepción 404 No Encontrado. Que es lo que ese código hace arriba. Si bien estoy de acuerdo con usted en las nuevas convenciones, está claro dónde está esta nueva Excepción porque está ampliamente presente en la mayoría de los controladores. Consideré ir con el enfoque de @David Anderson, pero prefiero arrojar la excepción real en mis controladores en lugar de hacerlo a través de un método estático porque arrojo otras excepciones de manera similar y preferiría no tener un método estático para cada una. – Marko

+0

Como todas las convenciones, es solo un problema si hay un problema al comunicarse y mantener la convención. Si eso no es un problema para ti, esta es una forma elegante de mantener métodos de fábrica de excepción, como mencionas, el código se ajusta al resto del código de lanzamiento de excepción. – Tanzelax

Cuestiones relacionadas