2010-02-25 12 views
13

Estoy trabajando en un gran proyecto en el que, incluso con 10s de miles de pruebas automatizadas y cobertura de código 100%, estamos obteniendo una cantidad ridícula de errores. Aproximadamente el 95% de los errores que obtenemos son NullReferenceExceptions.¿Cómo implico la verificación nula?

¿Hay alguna manera de forzar la comprobación nula en tiempo de compilación?

Al margen de eso, ¿hay alguna forma de aplicar automáticamente la verificación nula en pruebas unitarias sin tener que escribir las pruebas para casos nulos?

+1

¿Las NullReferenceExceptions provienen del marco de prueba o del código real que se está probando? –

+0

¿Qué servidor de compilación? si TFS puede usar las reglas de política de análisis de código, ayuda. –

+1

Quizás agregue una regla a su comprobador de estilo buscando '{} = null' y' return null; '? Si nunca establece nada en nulo, las únicas cosas que debe verificar para nulo son los resultados de las llamadas a la biblioteca. –

Respuesta

18

Debería mirar en Code Contracts. El verificador estático solo está disponible para las ediciones VS de nivel superior, pero eso es básicamente lo que buscas.

Hay muchos recursos en línea, y <plug> también puede leer una versión preliminar del capítulo sobre Contratos de código de la 2da edición de C# en profundidad - download chapter 15 for free. </plug> (El capítulo está ligeramente desactualizado con respecto a la compilación más reciente y mejor de Contratos de código, pero nada importante)

+0

+1 Los contratos de código definitivamente detendrán las referencias nulas en el momento de la compilación. No podrá construir hasta que elimine todas las posibilidades de pasar un valor nulo a un método/clase en particular. También echa un vistazo a Pex, que va de la mano con los contratos de código. –

+0

@Jon Skeet: estoy equivocado o los contratos de código solo funcionan si el desarrollador usa Requires.Something en el código? Entonces, si hay un error del desarrollador al verificar usando contratos, pasará en tiempo de compilación. Creo que Juliet quiere comprobar esto después del tiempo de desarrollo, cuando lo prueba o construye. –

+0

@Yoann: Bueno, sí, debes expresar el contrato en el código. ¿De qué otro modo va a distinguir entre las API que * pueden * aceptar nulos y las que no? Pero el verificador estático * does * realiza la comprobación en tiempo de compilación de los llamadores de la API. –

4

100% de cobertura de código no significa nada.

Es una falsa sensación de seguridad.

Lo único que está midiendo es que está ejecutando todas las líneas de código.

No

:

  • Que esas líneas de código son todas las líneas de código que debería haber estado allí
  • Que esas líneas de código funcionan correctamente (que está poniendo a prueba todos los casos extremos?)

Por ejemplo, si su procedimiento para hacer frente a un incendio contiene 1 paso "ejecutar fuera del edificio", incluso si eso ocurre en el 100% de los casos, quizás un mejor procedimiento sería "alertar al fuego" departamento, intente detener el fuego, luego agote si todo lo demás falla ".

No hay nada integrado en C# que lo ayude con esto sin que usted específicamente ingrese y agregue código, ya sea contratos de código (.NET 4.0) o declaraciones IF específicas (< 4.0).

+0

Corrección: la cobertura del código significa algo, simplemente no significa todo. –

0

No puede tener una comprobación nula en tiempo de compilación ya que en el momento de la compilación los objetos son solo Tipos y solo en en tiempo de ejecución, los tipos se convierten en instancias que tienen un valor concreto ... aquí nulo.

1

Esto no es una solución técnica, sino social. Simplemente haga que sea inaceptable en su entorno acceder a un tipo de referencia sin verificar si el tipo de referencia ha sido modificado de alguna manera por un código externo (otra llamada a método, etc.). Las Pruebas Unitarias no reemplazan la buena revisión anticuada del código.

+0

esto lleva a miles de líneas de código nuevo que realmente no agregan mucho valor. si obtiene un valor nulo y no puede tratar con un valor nulo, no lo revise, simplemente colóquelo y arrástrelo. una mejor convención es "nunca bajo ninguna circunstancia pasar referencias nulas a otros en el código de producción (nulos en el código de prueba donde sea aplicable es ideal para reducir el desorden)" – kai

+0

@kai - eso es una locura. No solo permite que las aplicaciones de producción se bloqueen y se quemen, y usted no tiene control sobre si los métodos devuelven el valor nulo en las API de terceros. –

+0

es mucho mejor que se bloquee (o al menos termine la acción/solicitud actual) de lo que es tragar un error o permitir que el sistema continúe en un estado desconocido. por supuesto que no "dejas" que tu aplicación se bloquee, esto no debería suceder. si obtienes un nulo en algún lugar, tienes un error y debes arreglarlo para que no tengas ningún nulo allí. por supuesto, los límites de la aplicación, el código de la interfaz de usuario y los puntos de integración de terceros son lugares en los que debe validar cosas, pero cuando ingresa al modelo de dominio y la lógica de negocios, los valores nulos solo causan daño y perjudican la legibilidad. – kai

-1

El marco .NET estaba buscando para hacer cumplir el tiempo de compilación verificación de referencias nulas mediante el uso de una! modificador

public void MyMethod(!string cannotBeNull) 

Pero, por desgracia, no tenemos tiempo de compilación de comprobación. Su mejor apuesta es minimizar las ocurrencias cantidad de llamadas externas para pasar valores nulos y luego cumplir cheques nulos en los métodos de revestimiento públicos:

public class ExternalFacing 
{ 
    public void MyMethod(string arg) 
    { 
    if (String.IsNullOrEmpty(arg)) 
     throw new ArgumentNullException(arg); 

    implementationDependency.DoSomething(arg); 
    } 
} 

internal class InternalClass 
{ 
    public void DoSomething(string arg) 
    { 
     // shouldn't have to enforce null here. 
    } 
} 

A continuación, se aplican las pruebas unitarias adecuadas para la clase externa esperar ArgumentNullExceptions.

+0

No estoy seguro de por qué esto fue downvoted, SpeC# es una cosa real que se originó en el laboratorio de Microsoft Research. http://research.microsoft.com/en-us/projects/specsharp/ Code Contracts es una mejor opción, pero no estoy equivocado. – bryanbcook

1

¿Hay alguna manera de aplicar la verificación nula en tiempo de compilación?

Nope. El compilador no puede determinar si la variable de referencia en tiempo de ejecución apunta a nulo.

Y excluir declaraciones de producción nula (conjuntos y devoluciones) tampoco es suficiente. Considere:

public class Customer 
{ 
    public List<Order> Orders {get;set;} 
} 
    //now to use it 
Customer c = new Customer; 
Order o = c.Orders.First(); //oops, null ref exception; 
0

puedo estar equivocado, pero creo que FxCop tiene una regla que sugiere agregar controles de referencia nulo a su código. Podría intentar ejecutar sus ensamblajes a través de la herramienta y ver lo que tiene que decir.

0

Consulte Gendarme, puede ejecutar post-build junto con sus pruebas (posiblemente antes, si lo desea) y tiene algunas reglas relacionadas con los controles null. También puede escribir trivialmente el suyo.

1

1) Creo que el Resharper puede sugerirle que verifique algunos lugares críticos en su código. Por ejemplo, sugiere agregar el [código de verificación de referencia nulo] y lo agrega si permite.

Pruébalo. Aumentará tu experiencia si lo necesitas, por supuesto.

2) Use "fallar rápida" patrón (o hacer valer, afirmaciones) en su código en la etapa temprana de desarrollo de aplicaciones

1

La programación defensiva sólo puede llegar tan lejos ... quizás sea mejor para coger el excepción y lidiar con ella como cualquier otra.

+0

Al "tratar" la excepción, asegúrese de lidiar con por qué sucedió.¿Por qué nunca se establece esta referencia? ¿Se emitió una excepción antes de que se pudiera establecer? Eso me sucedió hoy, y era necesario rastrear el motivo (un recurso faltante que causaba una 'ArgumentNullException', que se registraba y se ignoraba). –

+0

Ciertas cosas, en operaciones io particulares, nunca se puede estar seguro de que funcionen. Si tirar de un cable en algún lugar hace que un método devuelva un valor nulo (probablemente una mala práctica, pero no siempre se puede obtener lo que se desea), entonces también se puede tomar como una excepción. – CurtainDog

Cuestiones relacionadas