¿Cómo explico que si las comprobaciones (xyz == nulo) no son & # 8220; protectoras & # 8221;

StackOverflow https://stackoverflow.com/questions/1647666

  •  22-07-2019
  •  | 
  •  

Pregunta

Tengo algunos desarrolladores que constantemente ponen verificaciones nulas

Por ejemplo:

Run(Order order)
{
  if (order == null) return;
}

en su código ya que piensan que están protegiendo a su clase si alguien pasa un parámetro que es nulo. Estoy tratando de decirles la falla en su lógica porque si alguien pasa nulo en este caso, lo más probable es que sea un problema con el código del consumidor y en lugar de que esta clase arroje una excepción y falle rápidamente, maneja con gracia el mal comportamiento de al consumidor y sigue traqueteando.

otra sugerencia es tener precondición o clase de guardia que falle rápidamente y arroje excepciones. cualquier cosa que no sea ignorar el hecho de que el consumidor probablemente tenga algún otro problema y estoy ayudando a enmascararlo.

¿Cómo hago para que la gente aprecie el hecho de que tu clase no debería ser tan indulgente? si alguien no pasa buenos datos, se les debe informar.

¿algún buen artículo o sugerencia para ayudarme a entender este punto?

¿Fue útil?

Solución

Si su clase no puede aceptar argumentos null , entonces lo mejor que puede hacer es esto:

if (arg == null)
    throw new ArgumentNullException();

Esto es ampliamente preferible a obtener una NullPointerException más profunda en la pila. En el peor de los casos, almacenará ese null en algún lugar y no activará la excepción hasta mucho más tarde, y verá qué tan divertido será depurar el problema y luego .

Y como han dicho otros, a veces el contrato dice que null está bien. En ese caso, tener una cláusula de protección alrededor de algunas partes del código es correcto, aunque incluso entonces diría que el mejor diseño sería agregar una sobrecarga sin los argumentos opcionalmente nulos.

Otros consejos

Realmente depende de la situación precisa. Raramente es aconsejable dar sugerencias generales como "no ponga cheques nulos en su código", como parece indicar. El contrato de la clase debe definir qué es legítimo y qué no. Pero si el contrato deja en claro que pasar nulo no es aceptable, entonces una excepción es una respuesta apropiada.

Como todos los demás han dicho, es preferible fracasar antes que tener problemas misteriosos en la producción porque la función no hizo nada cuando se esperaba. si la función devuelve argumentos nulos, como en su ejemplo).

Incluso si la función no regresa y solo arroja una NullReferenceException , es fácil resolver un error cuando sabes que un argumento era nulo. Si una función arroja una NullReferenceException , no tiene idea de qué era null o de quién era la culpa.

Me gustaría agregar que ArgumentNullException toma un parámetro por una razón.

Es mejor escribir

if(myArg == null) throw new ArgumentNullException("myArg");

que lanzar un ArgumentNullException sin un paramName .

De esta manera, si tiene una excepción de una función que toma cinco parámetros, sabrá cuál de los parámetros causó el problema. Esto es especialmente importante si no puede adjuntar un depurador. (Por ejemplo, en un servidor web de producción o una máquina de usuario final)

Si está escribiendo muchas funciones, esto puede ser una sobrecarga, especialmente porque no hay IntelliSense para las cadenas. Escribí un fragmento de código para generar estas comprobaciones:

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
    <CodeSnippet Format="1.0.0">
        <Header>
            <Title>Check for null arguments</Title>
            <Shortcut>tna</Shortcut>
            <Description>Code snippet for throw new ArgumentNullException</Description>
            <Author>SLaks</Author>
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType>
                <SnippetType>SurroundsWith</SnippetType>
            </SnippetTypes>
        </Header>
        <Snippet>
            <Declarations>
                <Literal>
                    <ID>Parameter</ID>
                    <ToolTip>Paremeter to check for null</ToolTip>
                    <Default>value</Default>
                </Literal>
            </Declarations>
            <Code Language="csharp"><![CDATA[if ($Parameter$ == null) throw new ArgumentNullException("$Parameter<*>quot;);
        $end$]]>
            </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>

Los contratos de código en .net 4.0 con suerte harán que este comportamiento sea mucho más consistente. Cualquier artículo que hable sobre contratos de código ayudará a transmitir la idea y, en el futuro, este tipo de sintaxis proporcionará el método.

http : //blogs.msdn.com/bclteam/archive/2008/11/11/introduction-to-code-contracts-melitta-andersen.aspx

No lo he visto, pero eiffel.com tiene 2 presentaciones ( diapositivas + audio) sobre el tema de diseño por contrato . Estos tipos han inventaron el concepto, así que si alguien puede explicarlo, son ellos :-)

A veces no puedes decirle a la gente por qué una práctica como esta está mal, tienen que resolverlo por sí mismos. Pero podría ayudarlos a llegar a ellos haciendo una prueba unitaria que cause una falla desagradable debido a este problema, y ??hacer que depuren el error.

Si el contrato del método especifica que sus argumentos no deben ser nulos, entonces lo correcto es hacerlo explícito, utilizando un Assert, como este:

Debug.Assert( item != null, "Null items are not supported );

Esto fallará rápidamente cuando el ejecutable se construya usando una configuración de depuración, pero presentará una degradación de rendimiento cero cuando se construya usando una configuración de lanzamiento.

Esta parece ser una pregunta sobre cómo escribir mejor el código que es manejable. Creo que debe asumir la ignorancia de todos los consumidores de su código. Me metí en problemas asumiendo que yo o alguien con un conocimiento profundo estaría consumiendo mi código. Lo único que agregaría para lanzar una excepción es crear excepciones personalizadas y dejar migas de pan en la excepción interna. Creo firmemente en darles a sus desarrolladores la oportunidad de resolver el problema, especialmente si se debe a datos. Paso la mayor parte del tiempo buscando los datos que rompen mi código y, si puedes dejar pistas, ahorrarás semanas en un año.

Bueno, antes que nada, eres inequívocamente incorrecto. Estás abrazando una falacia lógica muy seria. Desea que su código sea correcto en virtud del código, suponiendo que todo lo que sucede a su alrededor sea correcto. Como si la corrección fuera algún tipo de polvo mágico de duendes que solo necesitas rociar en todas partes.

Todos los errores son o parecen estúpidos una vez que están expuestos. Pero sus controles como este los provocan para exponerse. Hasta entonces, los errores son invisibles. Y para proyectos lo suficientemente grandes y complejos, no sabes quién encontrará el error o en qué condiciones se encontrarán. El código diseñado para la resistencia generalmente tiene verificaciones como esta en todas partes y también verifica los valores de retorno para cada función que debe incluir valores de error. Así que terminas codificando un "No puedo hacer eso porque las subfunciones en las que confío no funcionan". semántico que en realidad se maneja adecuadamente. El gran valor de esto es que generalmente puede implementar soluciones alternativas o instrumentación de depuración autoconsciente con bastante facilidad. Por qué desea hacer cosas como esta es porque los errores más difíciles generalmente dependen de ambas propiedades para depurar correctamente.

Aprenda algunas lecciones de sus desarrolladores. Ponen controles como ese allí, porque no saben por qué a veces obtienen resultados extraños de las funciones. Los llamas ingenuos o demasiado cautelosos debido a un conocimiento limitado que tienes y que ellos no tienen. Pero cuando está depurando algo desagradable, se preguntará por qué no tiene tales controles en su código, y terminará pareciendo tan ingenuo por no poder detectar el error en primer lugar.

En resumen: ningún código se hace robusto asumiendo robustez sobre el entorno que los rodea.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top