¿Qué errores deben evitarse al programar en Java? En el siguiente artículo responderemos a esta pregunta.
Java es un lenguaje popular con una posición consolidada en el mundo del desarrollo de software. Es un lenguaje de programación potente y versátil. Alrededor de 3.000 millones de dispositivos en todo el mundo funcionan con Java y, por tanto, se han cometido al menos 3.000 millones de errores al utilizarlo. En este artículo, vamos a centrarnos en cómo no cometer más.
1. Obtención de una excepción de modificación concurrente
Este es, con diferencia, el error más común con el que me he encontrado. Al principio de mi carrera, yo también lo cometí muchas veces. Este error ocurre cuando intentas modificar la colección mientras iteras a través de ella. El ConcurrentModificationException también se puede plantear cuando se trabaja con múltiples hilos, pero por ahora, vamos a centrarnos en un escenario base.
Supongamos que tiene un Colección de usuarios donde algunos son adultos y otros no. Tu tarea consiste en filtrar a los niños.
for (Usuario : usuarios) {
if (!user.isAdult()) {
users.remove(usuario);
}
}
Ejecutando el mencionado código termina en obtener ConcurrentModificationException. ¿En qué nos equivocamos? Antes de terminar nuestra iteración, intentamos eliminar algunos elementos. Eso es lo que desencadena la excepción.
¿Cómo puedo evitarlo?
Hay un par de enfoques que pueden ayudar en ese caso. En primer lugar, aproveche Java La bondad del 8 - Corriente.
List adultos = usuarios.stream()
.filter(Usuario::esAdulto)
.toList();
Utilizando un Predicado hemos hecho la inversa de la condición anterior: ahora determinamos los elementos que hay que incluir. La ventaja de este enfoque es que es fácil encadenar otras funciones después de la eliminación, por ejemplo mapa. Pero por el amor de Dios. por favor, no trate de hacer algo como lo siguiente:
También podría acabar en el ConcurrentModificationException porque está modificando la fuente del flujo. También puede dar algunas excepciones más que no será fácil de depurar.
Para resolver ConcurrentModificationException en un escenario de un solo hilo. también podría cambiar a utilizar directamente Iterador y su eliminar() o simplemente no eliminar elementos durante la iteración. Sin embargo, mi recomendación es utilizar Corrientes - estamos en 2022.
2. Almacenamiento de contraseñas como cadenas
Como cada vez estoy más involucrado en la ciberseguridad, no sería fiel a mí mismo si no mencionara al menos una Error de Java que puede dar lugar a un problema de seguridad. Almacenar las contraseñas recibidas de los usuarios en un Cadena objeto es exactamente algo que deberías temer.
El problema (o quizá la ventaja) de Cadena es que es inmutable. En el mundo cibernético, crea una amenaza potencial ya que no se puede borrar el valor de una vez crear Cadena objeto. El atacante que consiga acceder a la memoria de su ordenador puede encontrar allí contraseñas en texto plano.
En segundo lugar, las cadenas en Java son internados por la JVM y almacenados en el espacio PermGen o en el espacio heap. Cuando se crea un Cadena se almacena en caché y sólo se elimina cuando el Recolector de Basura empieza a hacer su trabajo. No puedes estar seguro de cuándo se elimina tu contraseña del pool de cadenas ya que el Recolector de Basura trabaja de forma no determinista.
¿Cómo evitarlo?
Se recomienda utilizar char[] o, mejor aún, la biblioteca que admite el almacenamiento de contraseñas como char[]por ejemploContraseña4j. En char[] es mutable y puede modificarse una vez inicializado. Después de procesar una contraseña, puede simplemente borrar el array char[] escribiendo caracteres aleatorios en ella. En caso de que los atacantes consigan acceder a la memoria de su ordenador, sólo verán algunos valores aleatorios que no tienen nada que ver con las contraseñas de los usuarios.
3. (Des)gestión de excepciones
Los novatos y también los programadores más avanzados no saben cómo manejar correctamente las excepciones. Su principal pecado en esa materia es simplemente ignorarlas. NUNCA ES UN BUEN ENFOQUE.
Lamentablemente, no podemos ofrecerle una solución milagrosa que se adapte a todas las necesidades. Excepcións que te encuentres. Hay que pensar en cada caso por separado. No obstante, podemos darte algunos consejos para empezar con ese tema.
¿Cómo puedo evitarlo?
Ignorar Excepcións nunca es una buena práctica. Excepciónpor alguna razón, por lo que no debe ignorarlos.
try {...} catch(Exception e) { log(e); } rara vez es el enfoque correcto para Excepción manejo.
Lanza Excepciónmostrar un cuadro de diálogo de error al usuario o, al menos, añadir un mensaje exhaustivo al registro.
Si has dejado las excepciones sin tratar (que no deberías), al menos explícate en el comentario.
4. Uso de nulos
Desafortunadamente, es bastante común encontrar una función Java que en algunos casos devuelve un null. El problema es que una función de este tipo obliga a su cliente a realizar una comprobación nula del resultado. Sin ella, el NullPointerException se lanza.
La otra cosa es pasar un null valor. ¿Por qué se te ha ocurrido? En tal caso, la función tiene que realizar una comprobación de nulos. Cuando utilizas librerías de terceros, no puedes cambiar el interior de las funciones. ¿Qué ocurre entonces?
Y lo que es más importante, otros desarrolladores que lean tu código y vean que pasas null probablemente estará desorientado en cuanto a por qué eliges una forma tan extraña de implementar tu función.
¿Cómo puedo evitarlo?
No devuelva un null ¡valor! ¡Nunca! En caso de que su función devuelva algún tipo de Colecciónpuede devolver un Colección. Si trabaja con objetos individuales, puede utilizar el patrón de diseño de objetos nulos. Dado que Java 8, se aplica como Opcional. Aparte de eso, lo menos recomendable es plantear un Excepción.
5. Concatenación de cadenas pesadas
Esperemos que no sea un error que cometa, ya que es la pregunta más popular (o quizá la segunda más popular después de FizzBuzz) de las entrevistas. Como ya debería saber, una Cadena es inmutable en Java - una vez creada, no puede modificarse. Por tanto, la concatenación de Cadena se traduce en una asignación de memoria innecesaria. Concatenar Cadena cada vez requiere la creación de un StringBuilder y volver a convertirlo en una cadena. Por lo tanto, esta solución no es en absoluto adecuada si queremos combinar un gran número de caracteres.
¿Cómo puedo evitarlo?
Para resolver este problema, utilice StringBuilder. Crea un objeto mutable que puede manipularse fácilmente. Por supuesto, siempre se puede utilizar StringBuffer si su proyecto se utiliza en un contexto concurrente.
6. No utilizar las soluciones existentes
Cuando se desarrolla software, conocer los fundamentos del lenguaje en el que se escribe es imprescindible, pero no suficiente. Muchos problemas algorítmicos con los que te encuentras mientras implementas una nueva función ya han sido resueltos por otra persona. Demasiadas veces he visto a alguien implementar un algoritmo de seguridad desde cero. Este enfoque es propenso a errores. Una sola persona no puede probar a fondo una solución tan compleja. El conocimiento colectivo de los equipo formado por programadores de nivel medio-avanzado es casi siempre mejor que la grandeza de un prodigio. Desarrollador Java. No hace falta que reinvente la rueda: basta con adaptar la solución existente a sus necesidades.
¿Cómo puedo evitarlo?
Intenta buscar bibliotecas que aborden el problema en el que estás trabajando. Intenta encontrar soluciones similares. Muchas de las bibliotecas que están disponibles en la web son gratuitas y han sido pulidas y probadas por desarrolladores experimentados y por toda la comunidad Java. No tengas miedo de utilizarlas.
7. No encontrar tiempo suficiente para escribir pruebas
Es tentador creer que nuestro código siempre funcionará a la perfección. No escribir pruebas para el código es el peor pecado de Java desarrolladores de software. Muchos de nosotros preferimos pruebas manuales y exploratorias en lugar de pruebas unitarias, lo cual es una locura. ¿Por qué perder el tiempo escribiendo pruebas cuando puedes centrarte en proporcionar el mejor código del mundo para tu proyecto, que DEFINITIVAMENTE no tiene bugs?. Resulta que la realidad es brutal y no podemos proporcionar código de alta calidad sin escribir pruebas.
¿Cómo puedo evitarlo?
Siempre deberías preparar pruebas para tu código. Sé que el enfoque TDD no es tan fácil de mantener, pero al menos deberías proporcionar pruebas que cubran todas las condiciones en las que se puede ejecutar tu código. Esto incluye probar situaciones excepcionales. Las pruebas unitarias son necesarias. Tienes que proporcionarlas para cada característica de tu proyecto si quieres asegurarte de que tu código es fácil de refactorizar y extensible en futuros desarrollos.
Una cosa más. Mantén un alto nivel en tu código de pruebas: merecerá la pena. Es el consejo del tío Bob y estoy totalmente de acuerdo con él.
Además, no te olvides de otros tipos de pruebas. Las pruebas de integración son algo que debes tener en cuenta en todos tus proyectos.
8. Olvidar los modificadores de acceso
Privados y públicos, ¿verdad? Cómo vamos a olvidarnos de ellos. Resulta que hay más. Cuando empezó a aprender Javaseguro que se ha enterado de la existencia de los modificadores de acceso protegidos. Pueden ser útiles en algunos casos, por lo que vale la pena conocer su existencia.
Desarrolladores Java A menudo parece que nos olvidamos del ámbito del paquete. Es fácil no acordarse de utilizarlo, ya que está implícito y no requiere ningún tipo de información. Java palabras clave. El ámbito del paquete es importante. Le permite probar un método protegido. Los elementos protegidos son accesibles desde la ruta de la clase de prueba, siempre y cuando el paquete sea el mismo.
¿Cómo puedo evitarlo?
Recuerda lo del modificador protected y que el ámbito del paquete te permite probarlo.
9. Utilizar JavaEE puro en lugar de Spring
El siguiente paso después de aprender Java SE es aprender a dirigir Java en servidores, cómo hacer una aplicación de nivel empresarial.
Los novatos a menudo caen en la trampa de aprender JavaEE ya que hay un gran número de tutoriales sobre ello. Incluso 'Thinking in Java', el Programadores Java', menciona JavaEE y no dice nada sobre las otras opciones.
¿Cómo puedo evitarlo?
JavaEE es una canción del pasado. Hoy en día, Spring es algo a lo que hay que recurrir y Java EE es simplemente algo que está bien tener. Todas las aplicaciones empresariales modernas utilizan Spring, por lo que deberías considerar seriamente aprender aquí.