Código libre de NULLs

En este video explico los problemas que causan las referencias nulas en nuestro código y planteo cómo debemos crear un código libre de NULLs.

Sin categoría

16 thoughts on “Código libre de NULLs

  1. Excelente artículo Lucas, siempre he pensado que el trabajo de controlar los null aumenta mucho el coste de los desarrollos, creo que hay que buscar una buena solución para esto, ya que es muy fácil cometer este tipo de errores y además estos a veces son muy difíciles de encontrar.

    Un saludo.

  2. Lucas buenas, lo de los nulos es un infierno y como tu comentas, la mayoría de las veces es lo que yo llamo «programación defensiva». Hay devs que se preocupan tanto por evitar que el código falle que terminan inviertiendo más de del 60% del código en evitar esos fallos cuando el problema está en otro lado. Me ha encantado la idea y la forma en la que la presentas, ya la sumo a la lista de buenas prácitas para evangelizar con el látigo.

    Saludos

  3. Lucas, eres un crack, ánimo con este tipo de vídeos que al menos para mi, son sensacionales. Muchas veces se agradece una voz autorizada sobre temas tan, aparentemente sencillos, pero que pueden esconder todo un mundo de malas prácticas.
    Un saludo y enhorabuena!

  4. Felicidades Lucas!

    No tanto por lo que cuentas (que también) sino por como lo cuentas: claro y conciso. Me ha gustado mucho el vídeo.

    @Juan
    Realmente ya existe una solución para ello: comportarse como «si no existieran». Realmente lo que viene a mostrar Lucas en el video. Si GetCustomer() no encuentra el cliente… debe devolver null o lanzar una excepción? Si devuelve null bienvenido al baile de los ifs.
    En el fondo todo se trata de «meditar» sobre el contrato de cada método. Así pues, la postcondición de GetCustomer() es que el resultado que devuelve no puede ser null. Y ya está, fin del tema. O tienes un customer o tienes un error…
    Lo de devolver null muchas veces es por inercia de lenguajes antiguos que no tenían soporte para excepciones y por lo tanto no se podían modelar los errores…
    Saludos!

  5. @Eduard, sin embargo, quizas, podria ser interesante que el propio metodo evite el valor, lo mismo que cuando en un parametro de tipo int restringe de forma automática que puedas enviar un valor nulo, tendrias que cambiar el parametro como int?, se me antoja que los metodos en estos casos deberian ser mas restrictivos evitando pasar nulos, una solución con un atributo o con otro valor, podría facilitar la escritura de nuestras aplicaciones, lo cierto es he cometido infinidad de veces este error y veo muy interesante contar con alguna restricción en este sentido. Imagina además con equipos de varios programadores, es muy facil cometer este tipo de errores si no conoces en detalle como trabajar con valores nulos.

    Un saludo.

    Un saludo.

  6. Juan, para qué querés que te impidan hacer algo? ¿No podés simplemente no usar nulos? ¿O es que acaso se trata de una especie de adicción de la que no se puede salir si no es mediante una fuerza externa?

    a ver… por qué no usas gotos? por qué tu métodos no tienen 100 parametros? por qué tus clases no tienen 30.000 lineas de código? Es porque existe algo que lo impida o es porque sabés que no debés hacerlo?

    El punto es claro, si algo es perjudicial para el código, aún cuando nada te impida hacerlo, simplemente no lo hagas.

  7. @Lucas, está claro, sin embargo, no solo lo tengo que saber yo, lo tienen que saber todos, y cuando tenemos que modificar aplicaciones hechas por otros es fácil encontrarte con este tipo de problemas, yo los he realizado asiduamente en mis aplicaciones hasta que alguien ha venido a decir que esto no es correcto, por eso creo que una regla ayudaría enormemente a evitar este tipo de errores tal y como se realiza con tipos int e int?, de esta forma evitarías escribir las líneas de excepciones para controlar este tipo de situaciones, a mí me parece mucho más lógico ya que en este caso en el “contrato” ya defines la restricción, por ello soy partidario de una solución que evite cometer este tipo de errores, en este sentido fxcop y resharper no me han avisado de esta mala práctica, sería muy interesante integrarlas, al menos para aquellos programadores más noveles que desconozcan estas normas.

    Tan solo imaginar, menos restrictivos significaría utilizar por ejemplo dynamic o var en lugar de int, entonces, ¿qué preferirías? , utilizar tipos restrictivos o aquellos que no lo son, y ya sé que dinamic y var no están diseñados para esto, pero todos sabemos que pueden provocar innumerables errores, por ello, en este caso, yo utilizaría una regla que evite este tipo de prácticas fáciles de cometer si no se conocen.

    Un saludo.

  8. Buenos días Lucas (y a todos).

    Acabo de ver tu video y me gustaría compartir con todos algunas observaciones/reflexiones respecto al mismo.

    En la primera mitad del video estás trabajando con un ejemplo que bajo mi punto de vista se podría plantear de otro modo, y así, se vería que un null no es tan «malo» como parece deducirse de tus planteamientos en el video.

    Me explico.

    En el ejemplo de código indicas dos funciones:

    – public long CalculateCustomerOrder(long customerId)
    – private long CalculateCustomerOrder(Customer customer)

    Lógicamente, la llamada a la función pública llamará a la función privada.

    Indicas que se puede generar un null en public dentro de este código (al llamar a GetCustomerById):

    public long CalculateCustomerOrder(long customerId)
    {
    var customer = GetCustomerById(customerId);
    return CalculateCustomerOrder(customer);
    }

    La variable customer recibiría un null por parte de GetCustomerById en el caso de que el id no existiera.
    Este campo null sería enviado a CalculateCustomerOrder, y ésta nos devolvería un 0.

    El planteamiento aquí es erróneo porque los métodos y funciones privados NO deberían realizar validaciones.
    Las validaciones deberían realizarse SIEMPRE en la parte pública.
    La parte privada debería asumir que la validación YA SE HA HECHO.
    (Perdonad las mayúsculas, pero quiero dar un énfasis importante a mis apreciaciones porque creo que hay personas que no han caido en la cuenta de estos detalles).

    Por lo tanto, mi función pública quedaría de la siguiente manera:

    public long CalculateCustomerOrder(long customerId)
    {
    var customer = GetCustomerById(customerId);
    if (customer == null)
    {
    // Enviamos Exception.
    }
    return CalculateCustomerOrder(customer);
    }

    De esta manera, el contrato de la función privada se cumplirá sin problemas.

    El planteamiento erróneo bajo mi punto de vista, está en que damos a la función o método privado una responsabilidad que no debería tener, la validación.

    Espero que queden claras mis matizaciones al respecto.

    Por cierto, personalmente el uso de null hay que evitarlo… totalmente de acuerdo contigo, pero no lo veo tan malo. Siempre que se pueda se debe evitar, pero cuando trabajamos con bases de datos que tienen campos null o en cualquier otra circunstancia o requisito Software muy concreto, los campos null pueden sernos de gran utilidad y resolver conflictos que de otra manera requeriría mayor codificación. Alguno se queja aquí de que con null hacemos uso de if, pero nadie se ha parado en pensar en que sin null, necesitaríamos una gestión de control y codificación mayor.

    Un saludo.

    Jorge Serrano

  9. @Jorge lo que decís es claro y ya lo expliqué en otro video sobre excepciones (esta es una serie) la validaciones van en la superficie pública ES ASI.
    Lo que quiero decir es que la responsabilidad de lanzar la excepción es de GetCustormer y no de sus, probablemente innumerables, clientes. Por eso no estoy de acuerdo con tu implementación ya que vamos a tener esas validaciones por Null por todas partes y como vos bien sabes a alguien se la va a olvidar verificarla, no así las excepciones.
    La idea es tal cual lo dice Eduard y el Tio Bob: no pasar ni devolver nulos, pero para que esto sea posible hay que hacer cumplir los contratos y si un método no puede devolver lo que le pedimos entonces debe fallar.

  10. Hola @Lucas,

    estoy de acuerdo con tu matización, pero el video que has preparado no representa exactamente lo que acabas de explicar.

    Completando tu explicación, creo que deberías haber dejado claro que GetCustomerById debería ser el encargado de devolver una excepción en el caso de no existir un cliente con el id demandado, en cuyo caso, solventamos el tema de los null y en el código que he propuesto, sobraría el if.

    Si la responsabilidad de lanzar la excepción la delegas en GetCustomerById me parece perfecto y correcto, pero no se ha entrado a analizar GetCustomerId en ningún momento, por lo tanto, me he ceñido al código que sí muestras en el video. Es decir, el «pero» que le veo al video es que para nada has mostrado el comportamiento de GetCustomerById y que por lo que parece ahora, es vital para completar tus explicaciones.

    Lucas, tómate mis palabras como una crítica constructiva, que tus videos están geniales, simplemente para indicarte que en mi modesta opinión, el video no aclara completamente lo que ahora mismo estás comentando, o que yo no lo he entendido correctamente, algo que le puede pasar a alguien más.

    Un abrazo,

    Jorge

  11. Gracias Jorge, y no hace falta que aclares tu intención ya que para mí está bien claro que es un aporte constructivo y se agradece mucho.

    Tenés razón en lo que decis, lo que pasa es que para hacer los videos cortos (quiero que sean de menos de 10 minutos) me restrinjo a no repetir los conceptos de los que ya he hablado en los videos anteriores de la serie. Por eso es que este video aislado puede parecer a quien lo ve como «incompleto». Pero te juro que, lo que es responsabilidad de método GetCustomerById el lanzar la excepción, ya lo expliqué previamente. Es más, en el último video sobre NullObject (que no publiqué en Geeks – solo en youtuve) creo que también queda claro.

    Básicamente, es parte de una serie.

    Un abrazo Jorge.

  12. Muchas gracias Lucas por tomarte a bien mis comentarios. No es fácil y sobre todo después de tomarse tantas molestias como las que tú te estás tomando para grabar estos videos.

    Entiendo también lo que dices de la duración de los videos y demás,… :-S y tienes mucha razón.

    Me alegro de que por otra parte se aclaren los puntos y salgan estas conversaciones para que les pueda servir a otras personas y les pueda resolver o aclarar posibles confusiones, o incluso ver diferentes puntos de vista. 🙂

    Es lo bueno de la Comunidad. 😉

    Un abrazo,

    Jorge

  13. @Juan, ni los lenguajes ni los frameworks ni las herramientas te van a salvar nunca. Todo lenguaje, todo framework y toda herramienta en manos de un mono va a servir para lo mismo: para nada!

    Hay que ver en donde ponemos la responsabilidad de lograr mejor código, si en el lenguaje o si en las personas. Desde mi punto de vista, los lenguajes, frameworks y herramientas ayudan poco. Y entonces no importa cuanto restrinjas a un programador porque siempre se las arreglará para hacer desastres. Los desastres los vas a ver en todas partes independientemente de las tecnologías usadas.

    Lo importante es notar que aquellos que hacen desastres no lo hacen a deliberadamente sino que lo hacen porque «no saben como hacerlo» entonces, restringiéndolos más no atacas el problema de que «no saben como hacerlo». La solución es transmitirles tus conocimientos y que aprendan cómo se hace.

  14. Lucas, no estoy en absoluto de acuerdo, algunas reglas nos ayudan a programar mejor, si no ¿porque activas políticas de checking?, ¿porque utilizas decimal y decimal?, si con utilizar decimal? es suficiente, ¿Por qué defines interfaces?, …., ¿Por qué usas fxcoop, stylecop, resharper u otra herramienta parecida, porque utilizas una máscara de entrada y posteriormente puedes lanzar una excepción y controlarla… entiendo que lo haces para establecer y controlar las tus reglas, ya que difícilmente te vas a acordar de todas y que el sistema te avise o te obligue si es posible a aplicarlas correctamente.

    Si yo lo único que digo es que para mí sería muy útil poder restringir los parámetros en el método en lugar de hacer una excepción con cada uno, entiendo que la programación sería más limpia. Imagina un método así.

    public bool ValidateCustomer(Customer customer) {
    }

    Para mi, este método solo debería aceptar un Customer y no un null, en este punto ya estas incumpliendo el contrato, le pasas un null a algo que no debería recibirlo.

    Si quisiera aceptar un null en el método debería hacer algo como esto:

    public bool ValidateCustomer(Customer? customer) {
    }

    Así es como se restrigen los tipos actualmente, porque no utilizarlo de la misma forma con nuestros parámetros, creo que tiene todo el sentido.

    Simplemente esto, creo que esto nos permitiría aplicaciones con menos validaciones y con un código más limpio, en lugar de encontrarnos los típicos métodos:

    If (customer == null) Throw new ArgumentException(…..)

    En resumen, evitar el error antes de que este se produzca, esto es solo mi punto de vista, no digo que no pueda estar equivocado, en cualquier caso el debate es muy interesante.

    Un saludo.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *