the billion dollar mistake

Post on 14-Apr-2017

198 Views

Category:

Software

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

T H E B I L L I O N D O L L A R M I S TA K E

Quien soyaloa i sa

• Más decepcionante que los Generics de Java

• Peor que la barra invertida de Windows \

• Más problemático que la comparación en JS ===

• Más común que PHP

• Más lamentable que UTF-16

• Más escandaloso que MongoDB

• Más confuso que el Pre-Compilador de C •El peor error se produjo en 1965!!

No eres un verdadero programador

hasta que no has tenido un NullPointerException

Tony Hoare

“ It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object oriented language (ALGOL W). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn't resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years. ”

“I call it my billion-dollar mistake”

Que pasa con los nulls?

Que pasa con los nulls?

• NullPointerException es de lejos la excepción más común en Java

• Empeora la legibilidad llenando todo con chequeos de nulls

• Rompe la filosofía Java de ocultar a los desarrolladores los punteros.

• Es un agujero en el Sistema de Tipos

• No tiene un sentido semántico en particular.

• Es un mal modelo para representar la ausencia de valor para un lenguaje estáticamente tipado.

“La ausencia de señal, nunca debe ser usada como señal”

J. Bigalow 1947

null != Ausencia de valor

Problema típico en POO

Problema típico en POO

• Muchos ordenadores no tienen Soundcard. ¿Que devolvemos entonces?

• Comúnmente y como mala práctica, se suele usar null para indicar la ausencia de SoundCard

• Con lo que el resultado será un NullPointerException en tiempo de ejecución y el programa se parará.

¿Como se ha resuelto en otros lenguajes ??

• Lenguajes como C# o Groovy tienen el “Safe navigation operator” ?.

• A la variable version se le asignará null si computer es null, getSoundCard() devuelve null o getUSB() devuelve null.

• No es necesario escribir código complejo para chequear los null

Groovy - Elvis Operator ?:

• Es usado en casos simples cuando la variable necesita un valor por defecto

• En el caso que .getVersion() nos devolviera null podríamos devolver un valor por defecto de esta forma:

Otros puntos de vista• Haskell: Incluye el tipo Maybe

• Maybe puede contener un valor de un tipo dado o nada, ya que no existe el concepto de nulo

• En esencia encapsula a un Optional

• Scala: Similar con Option[T]• Encapsula la presencia o la ausencia de un valor de un tipo T

• Tenemos que chequear si el valor está presente, lo cual es similar a el chequeo de nulos.

• Fuerza al programador a controlarlo a través del sistema de tipos

Y en Java ??• Solución 1: (Guarrada)

• Desagradable a la vista

• Debemos chequear todos los valores para evitar que nos pase

• Todos estos checks están en medio de la lógica

• Disminuye la legibilidad del programa

Y en Java ??• Solución 2:

Podemos utilizar notaciones para restringir los contratos:

@NotNull y @Nullable (Java 8 > No estandars)

• @Nullable nos recuerda la necesidad de introducir un chequeo de null cuando llamamos a métodos que pueden devolver nulos.

• @NotNull nos establece un contrato por el que el método no puede devolver null - Y sus parámetros no pueden ser pasados como null

Y en Java ??• Solución 3:

Patrón NullObject

• Añade complejidad

• Hay que crear bastantes NullObjects dependiendo de la arquitectura

Y en Java ??• Solución 4: (Otra guarrada)

Devolver Null

• Mala práctica

• Fuente de NullPointerExceptions

• No estamos pensando en el caso de que sea vacío

Que pasa en Java 8 ??• java.util.Optional<T>

• - Inspirado en la idea antes vista de Haskell y Scala

• - Es una clase que encapsula un valor opcional

Optional• Un Optional puede ser visto como un contenedor de un solo

valor que puede contener un valor o no.

Optional

• Computer puede tener o no soundCard

• SoundCard puede tener o no puerto USB

Optional

• Este nuevo modelo refleja si un valor dado puede estar ausente

• Establece la intención del API

• Optional no es para reemplazar cada referencia nula

• Es para ayudarnos a hacer un diseño más comprensible

• Con la firma del método podemos saber si es un valor opcional

• Te obliga a hacer frente a la posible ausencia de valor

Y ahora qué ??

Creando Optionals

• Si soundCard fuera null se lanzaría un NullPointerException

• Si soundcard fuera null el resultado del Optional sería empty

.ifPresent()• Ejecuta algo si el Opcional contiene algún valor

Antes:

Ahora:

.isPresent()

• Devuelve true o false dependiendo si contiene o no valor

• Podemos usarlos de esta forma para evitar excepciones

• Este no es el mejor uso, ya que no es mucho mejor al chequeo de nulos

.get()

• Nos devuelve el valor contenido en el Optional

• Si no hay valor almacenado, dará un NoSuchElementException

• Podemos usarlos de esta forma para evitar excepciones

• Este no es el mejor uso, ya que no es mucho mejor al chequeo de nulos

.orElse()Patrón típico:

• Usando un objeto Optional podemos escribir este código usando orElse()

• Este método provee un valor por defecto si el Optional está vacío.

.orElseGet()

• orElse() ejecuta siempre el contenido y lo devuelve si es el caso, a no ser que sea un lambda

• orElseGet() solo ejecuta el código si le toca actuar

• Puede dar un NullPointerException si lo que ejecuta devuelve null

.orElseThrow()

- Lanza la excepción que le digamos si el Optional está vacío.

.filter()

•El método filter() coge el valor como argumento

•Si el valor está presente en el Optional y la comprobación es true, el método filter() devuelve el propio Optional

•Si el valor es vacío, devuelve un objeto Optional vacío

Antes:

Ahora:

.map()

• El valor dentro del Optional es pasado como argumento al método getUSB()

• Mientras que no pasa nada si está vacío

Antes:

Ahora:

.flatMap()

• getUSB() devuelve un objeto de tipo Optional<USB> • Esto significa que el resultado de la primera operación map es un

objeto de tipo Optional<Optional<USB>>

• Como resultado, la llamada a getVersion() es inválida

Antes:

Ahora:

.flatMap()• El propósito es aplicar el método de transformación sobre el valor del Optional y

"aplanar" el resultado de dos niveles de Optional en uno solo.

.flatMap()

• flatMap se utiliza para métodos que devuelven Optionals

• flatMap devuelve un Optional<USB> en lugar de un Optional<Optional<USB>>

• Podemos llamar a map() ya que getVersion() devuelve un String en vez de un objeto Optional

Antes:

Ahora:

• El propósito de Optional NO es reemplazar cada referencia nula en el código

• El propósito de Opcional es el poder diseñar mejores APIs

• Nos fuerza a extraer su valor y gestionarlo en el caso de su ausencia

• Nos protege de nullPointerExceptions

• Simplifica el código

• Un nullPointerException en producción puede hacerte perder mucha pasta!!

Conclusiones:

Recurso shttp://www.oracle.com/technetwork/articles/

java/java8-optional-2175753.html

http://es.slideshare.net/Stephan.Schmidt/better-

strategies-for-null-handling-in-java

http://es.slideshare.net/Yokomark/17-50372457

http://www.slideshare.net/mariofusco/monadic-java

https://www.jetbrains.com/help/idea/15.0/

nullable-and-notnull-annotations.html

https://www.lucidchart.com/techblog/2015/08/31/

the-worst-mistake-of-computer-science/

top related