java - Confiar en la inicialización de campo predeterminada: ¿es un mal estilo de programación?
default-value instance-variables (3)
Me dieron un enlace a la documentación oficial de Oracle: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
donde se dice:
Valores predeterminados
No siempre es necesario asignar un valor cuando se declara un campo. El compilador establecerá los campos declarados pero no inicializados en un valor predeterminado razonable. En términos generales, este valor predeterminado será cero o nulo, según el tipo de datos. Sin embargo, confiar en estos valores predeterminados generalmente se considera un mal estilo de programación.
Quiero enfatizar esta parte:
Sin embargo, confiar en estos valores predeterminados generalmente se considera un mal estilo de programación.
Pero, vaya, esto es, yo diría, una parte fundamental de la especificación del lenguaje sabiendo que las variables de instancia tienen valores predeterminados. ¿Por qué demonios es una mala práctica de programación si se usa ampliamente incluso en el código fuente de las bibliotecas Java SE?
¿Por qué demonios es una mala práctica de programación?
La idea es que si confía en un valor predeterminado, no está claro de inmediato para cualquiera que lea el código si lo dejó deliberadamente como el valor predeterminado, o si simplemente olvidó asignarlo.
... si se usa ampliamente incluso en el código fuente de las bibliotecas Java SE?
El código fuente de Java no es realmente algo en lo que deba confiar como un ejemplo de práctica de codificación ejemplar. Hay muchos casos en los que se violan dichas reglas (a veces intencionalmente por mejoras menores de rendimiento, y a veces accidentalmente o porque el estilo aceptado ha cambiado con los años).
El texto citado es:
"Sin embargo, confiar en esos valores predeterminados generalmente se considera un mal estilo de programación".
Cínicamente: "generalmente se considera que" es a menudo una forma de decir que el autor no ha tratado de encontrar una fuente autorizada para la declaración que se presenta.
En este caso, la afirmación es claramente cuestionable. Evidencia: 5 de las 5 Guías de estilo Java muestreadas NO dicen nada sobre si debe o debe confiar en los valores predeterminados:
- Guía de estilo de Google Java
- Guía de estilo Java de Twitter
- Guía de estilo de programación Java - JavaRanch (dudoso)
- Pautas de estilo del código Java - Cornell University CS.
- La guía de estilo Java OpenJDK Draft
(Tenga en cuenta que mi metodología para el muestreo fue mirar los primeros 5 resultados distintos de búsqueda de Google para "guía de estilo java". Luego busqué en cada documento el "valor predeterminado". Este no es un análisis exhaustivo, pero sirve para aclarar mi punto. )
OKAY. Entonces, ¿realmente ayuda a la legibilidad del código Java?
Esto es discutible.
Por un lado, un programador novato de Java que no ha aprendido sobre la inicialización predeterminada puede estar desconcertado acerca de dónde provienen los ceros o los valores nulos. Pero si se molestan en buscar una inicialización explícita y encuentran que no hay una, eso debería ser suficiente para que lean un tutorial o libro para averiguar sobre la inicialización predeterminada. (¡Lo esperarías!)
Por otro lado, normalmente no esperamos que los programadores Java novatos mantengan bases de código de producción. Para un programador Java experimentado, una inicialización redundante no mejora la legibilidad. Es (en el mejor de los casos) ruido.
En mi opinión, lo único que se logra mediante una inicialización redundante de un campo es indicar a un futuro lector de su código que ha pensado en el valor inicial. (Como lo expresó @GhostCat, la inicialización predeterminada no comunica la intención).
Pero, por el contrario, si fuera ese lector, no necesariamente confiaría en el pensamiento del autor del código. Entonces el valor de esta "señal" también es cuestionable.
¿Qué pasa con la fiabilidad?
En Java no hay diferencia. El JLS especifica que la inicialización predeterminada ocurre para los campos. Y, por el contrario, para las variables locales es un error de compilación intentar usar una variable que no se ha inicializado definitivamente.
En resumen, el comportamiento en tiempo de ejecución de una variable que no se inicializa explícitamente es completamente predecible.
Por el contrario, en lenguajes como C o C ++, donde las variables pueden no inicializarse, el comportamiento no se especifica y puede provocar bloqueos y diferencias de comportamiento en diferentes plataformas. El caso de siempre inicializar explícitamente las variables es mucho más fuerte aquí.
¿Qué pasa con el rendimiento?
No debería hacer ninguna diferencia. El compilador JIT debería poder tratar una inicialización redundante y una inicialización predeterminada de la misma manera.
Simple: confiar en valores predeterminados no comunica intención.
¿Realmente quería que ese campo comenzara con 0, o se olvidó de asignar un valor?
Y, por supuesto, una referencia nula es la mitad de las dos cosas que necesita para encontrarse con una excepción de puntero nulo.
Finalmente, el uso de valores predeterminados implica que tiene campos no finales. Que evitas siempre que sea posible.
El único argumento contrario es: ¿por qué escribir cosas que no tiene que hacer? Pero creo que las desventajas enumeradas anuncian que, por lo tanto, asignar 0 a un campo explícitamente es mejor que dejarlo en el compilador.