Lo que aprendí al hacer 1000 revisiones de código

Mientras trabajaba en LinkedIn, una gran parte de mi trabajo consistía en hacer revisiones de código. Hubo ciertas sugerencias que seguían surgiendo una y otra vez, así que decidí armar una lista que compartí con el equipo.

Aquí están mis 3 (+1 bonificación) sugerencias de revisión de código más comunes.

Sugerencia 1: Lanzar una excepción cuando las cosas van mal

Un patrón común que he visto es este:

Este patrón en realidad causó una interrupción en una de las aplicaciones móviles en las que trabajé. El motor de búsqueda que estábamos usando comenzó a lanzar excepciones. Sin embargo, el servidor API de la aplicación tenía un código similar al anterior. Por lo tanto, desde la perspectiva de la aplicación, obtuvo una respuesta exitosa de 200 y mostró felizmente una lista vacía para cada consulta de búsqueda.

Si, en cambio, la API arrojara una excepción, nuestros sistemas de monitoreo habrían recogido esto inmediatamente y se habría solucionado.

Hay muchas ocasiones en las que puede ser tentador simplemente devolver un objeto vacío después de haber capturado una excepción. Los ejemplos de objetos vacíos en Java son Optional.empty (), null y empty list. Un lugar donde esto aparece todo el tiempo es en el análisis de URL. En lugar de devolver nulo si la URL no se puede analizar desde una Cadena, pregúntese: "¿Por qué la URL está mal formada? ¿Se trata de un problema de datos que deberíamos solucionar antes? ".

Los objetos vacíos no son la herramienta adecuada para este trabajo. Si algo es excepcional, debe lanzar una excepción .

Sugerencia 2: utilice el tipo más específico posible

Esta sugerencia es básicamente lo opuesto a la programación de mecanografía .

Demasiado a menudo veo código como estos ejemplos:

Usar el tipo más específico posible le permite evitar toda una clase de errores y básicamente es la razón completa para elegir lenguaje fuertemente tipado como Java en primer lugar.

Así que ahora la pregunta es: ¿cómo los programadores bien intencionados terminan escribiendo código tipeado? La respuesta: porque el mundo externo no está fuertemente tipado. Hay varios lugares diferentes de donde provienen las cadenas, como:

  • parámetros de consulta y ruta en urls
  • JSON
  • bases de datos que no admiten enumeraciones
  • bibliotecas mal escritas

En todos estos casos, debe usar la siguiente estrategia para evitar este problema: mantenga el análisis sintáctico de cadenas y la serialización al margen de su programa . Aquí hay un ejemplo:

Esto confiere una serie de ventajas. Los datos mal formados se encuentran inmediatamente; la aplicación falla temprano si hay algún problema. Tampoco tiene que seguir detectando excepciones de análisis en toda la aplicación una vez que los datos se hayan validado una vez. Además, los tipos fuertes hacen que las firmas de métodos sean más descriptivas; no es necesario que escriba tantos javadocs en cada método.

Sugerencia 3: utilizar opciones en lugar de valores nulos

Una de las mejores características para salir de Java 8 es la clase Optional que representa una entidad que podría existir razonablemente o no existir.

Pregunta de trivia: ¿cuál es la única excepción que tiene su propio acrónimo? Respuesta: una excepción NPE o Null Pointer. Es, con mucho, la excepción más común en Java y se conoce como un error de mil millones de dólares .

Optional permite eliminar por completo los NPE de su programa. Sin embargo, debe ser usado correctamente. Aquí hay algunos consejos que rodean el
uso de Optional :

  • No debe simplemente llamar a .get() cada vez que tenga un Optional para usarlo, en su lugar piense detenidamente sobre el caso donde el Optional no está presente y obtenga un valor predeterminado razonable.
  • Si todavía no tiene un valor predeterminado razonable, los métodos como .map() y .flatMap() permiten .flatMap() esta decisión hasta más adelante.
  • Si una biblioteca externa devuelve null para indicar el caso vacío, envuelva inmediatamente el valor usando Optional.ofNullable() . Confía en mí, te lo agradecerás más tarde. los nulos tienen una tendencia a "burbujear" dentro de los programas por lo que es mejor detenerlos en la fuente.
  • Use Optional en el tipo de método de devolución. Esto es genial porque entonces no necesita leer el javadoc para determinar si es posible que el valor no esté presente.

Sugerencia de bonificación: métodos de "desenrollar" siempre que sea posible

Debería intentar evitar métodos que se vean así:

¿Qué tienen en común todos los métodos de evitación? Están utilizando objetos de contenedor como Opcional, Lista o Tarea como parámetros del método. Es incluso peor cuando el tipo de devolución es el mismo tipo de contenedor (es decir, un método de param toma un Opcional y devuelve un Opcional).

¿Por qué?
1) Promise<A> method(Promise<B> param)
es menos flexible que simplemente tener

2) A method(B param) .

Si tiene Promise<B> entonces puede usar 1) o puede usar 2) "levantando" la función con .map . (es decir, promise.map(method) ).

Sin embargo, si tiene solo B, puede usar fácilmente 2) pero no puede usar 1), lo que hace que 2) sea la opción mucho más flexible.

Me gusta llamar a esto "alejamiento" porque es lo opuesto al método de utilidad funcional común "levantar". La aplicación de estas reescrituras hace que los métodos sean más flexibles y fáciles de usar para las personas que llaman.

Ver también

Eche un vistazo a mi otro artículo sobre "Programación funcional funcional": https://hackernoon.com/practical-functional-programming-6d7932abc58b

Este artículo ha sido traducido al coreano por Ilkwon Sim : https://www.vobour.com/1000-%EA%B0%9C%EC%9D%98-%EC%BD%94%EB%93%9C-% EB% A6% AC% EB% B7% B0% EB% A5% BC-% ED% 86% B5% ED% 95% B4-% EB% B0% B0% EC% 9A% B4-% EC% A0% 90 -what-i-learned-f