Hable el lenguaje Java sin acento

Fluidez nativa para programadores no nativos

Elliotte Rusty Harold explora los modismos, dialectos y acentos nativos del lenguaje y la comunidad Java™. Al seguir la orientación de este artículo, C/C++ y otros programadores no nativos pueden mezclarse adecuadamente con los hablantes Java nativos.

Elliotte Rusty Harold, Profesor adjunto, Polytechnic University

Elliotte Rusty HaroldElliotte Rusty Harold es originariamente de Nueva Orleans, a donde regresa periódicamente en busca de un tazón decente de gumbo. Sin embargo, reside en el barrio Prospect Heights de Brooklyn con su esposa Beth y sus gatos Charm (por el quark) y Marjorie (por su suegra). Es profesor adjunto de ciencias informáticas en la Polytechnic University, en donde enseña tecnología Java y programación orientada a objetos. Su website Cafe au Lait se ha convertido en uno de los sitios Java independientes más populares de Internet, sitio derivado, Cafe con Leche, se ha convertido en uno de los sitios XML más populares. Entre sus libros se incluyen Effective XML, Processing XML with Java, Java Network Programming y The XML 1.1 Bible. Actualmente está trabajando en el XOM API para procesar XML, el motor Jaxen XPath y la herramienta Jester de cobertura de pruebas.



10-12-2012

Desarrolle habilidades de este tema

Este contenido es parte de un knowledge path progresivo para avanzar en sus habilidades. Vea Conviértase en un desarrollador Java

Aprender un nuevo lenguaje de programación es más fácil que aprender un nuevo idioma hablado. Pero, en ambos intentos, requiere esfuerzo extra aprender a hablar el lenguaje nuevo sin acento. No es tan duro aprender el lenguaje Java cuando ya sabe C o C++. Es similar a aprender danés cuando ya habla sueco. Los lenguajes son diferentes pero mutuamente comprensibles. Sin embargo, si no es cuidadoso, su acento lo develará siempre como un hablante no nativo.

Los programadores C++ a menudo ponen ciertas inflexiones en el código Java que los marcan indudablemente como conversos en lugar de hablantes nativos. Su código todavía funciona pero suena mal al oído nativo. Como resultado, los nativos pueden menospreciar a los hablantes no nativos. Cuando se pasa del C o C++ (o Basic o Fortran o Scheme o cualquier otro) al lenguaje Java, es necesario erradicar ciertos modismos y corregir algunas pronunciaciones que usted enuncia de manera fluida.

En este artículo, exploro una cantidad de detalles de programación Java que a menudo se pasan por alto precisamente porque semánticamente no interesan demasiado, si es que interesan. Son cuestiones puramente de estilo y convención. Algunas de ellas tienen justificaciones plausibles. Algunas de ellas incluso carecen de eso. Pero todas ellas son fenómenos reales en el código Java como está escrito actualmente.

¿Qué lenguaje es este?

Comencemos con un poco del código para convertir las temperaturas en Fahrenheit a temperaturas en Celsius, que se muestra en el Listado 1:

Listado 1. ¿Un poco del código C?
 float F, C; float min_tmp, max_tmp, x; min_tmp = 0; max_tmp = 300;
                x = 20; F = min_tmp; while (F <= max_tmp) { C = 5 * (F-32) / 9;
                printf("%f\t%f\n", F, C); F = F + x; }

¿Qué lenguaje se usa en el Listado 1? Evidentemente, es el C — pero espere un minuto. Observe el programa completo en el Listado 2:

Listado 2. Un programa Java
class Test { public static void main(String argv[]) { float F, C;
                float min_tmp, max_tmp, x; min_tmp = 0; max_tmp = 300; x = 20; F = min_tmp; while (F
                <= max_tmp) { C = 5 * (F-32) / 9; printf("%f\t%f\n", F, C); F = F + x; } }
                private static void printf(String format, Object... args) {
                System.out.printf(format, args); } }

Créalo o no, los Listados 1 y 2 están escritos ambos en el lenguaje Java. Son solo códigos Java escritos en un modismo C (para ser justos, el Listado 1 también podría ser un código C real). Pero es un código Java de aspecto muy gracioso. Aquí una cantidad de modismos lo marcan como el trabajo de alguien que piensa en C y está simplemente traduciendo al lenguaje Java:

  • Las variables son floatsen lugar de doubles.
  • Todas las variables se declaran al comienzo del método.
  • La inicialización sigue a la declaración.
  • Se usa un bucle while en lugar de un bucle for.
  • printf se usa en lugar de println.
  • El argumento para el método main() se llama argv.
  • Los delimitadores de matriz vienen después del nombre del argumento en lugar de después del tipo.

Ninguno de estos modismos es erróneo en el sentido de producir un código que no compilará o que proporcione una respuesta incorrecta. Individualmente, ninguno de estos puntos es significante. Sin embargo, en conjunto resultan en un código muy extraño que es tan difícil de leer para un programador Java así como Geordie lo es para que un estadounidense lo entienda. Mientras menos modismos C use, más claro será su código. Con eso en mente, analizaré algunos de los modos más frecuentes en que los programadores C se develan a sí mismos y mostraré cómo pueden hacer su código más agradable para el ojo Java.


Convenciones de denominación

Según si viene de C y C++ o C#, usted puede haber internalizado diferentes convenciones de denominación para las clases. En C#, por ejemplo, los nombres de clase comienzan con letras minúsculas y los nombres de método y campo comienzan con letras mayúsculas. El estilo Java es exactamente al revés. No puedo justificar una convención u otro por cualquier motivo racional pero sí sé que mezclar las convenciones de denominaciones hace que el código se sienta terriblemente erróneo. También conduce a errores. Cuando sabe que cada nombre en mayúsculas sostenidas es una constante, lo trata de modo diferente. He encontrado muchos errores en programas al buscar simplemente lugares donde las convenciones de denominación no coincidían con el tipo declarado.

args, no argv

Este punto es uno de los más triviales, pero esas son las minucias por las que se libran las guerras de estilo. En la jerga Java, el argumento del método main() se llama args, no argv:

public static void main(String[] args)

Esto es, en el mejor de los casos, solo una mejoría increíblemente pequeña del nombre argv. Es ligeramente más evidente como una abreviación de argumentos. Por supuesto, las abreviaciones están habitualmente prohibidas en el código Java idiomático (vea No abrevie). La única razón por la que usamos args como el nombre del argumento para el método main() es la misma razón por la que los programadores C usan argv — es lo que Kernighan y Ritchie, las personas que escribieron el primer libro C, usaron. Gosling y Arnold usan args. No hay otra razón que esa. Aun así, todos los programadores Java de habla nativa prefieren argsy si usted quiere hablar sin acento, usted también lo preferirá.

Las reglas básicas para los nombres en la programación Java son bastante simples y valen la pena memorizarlas:

  • Los nombres de clase e interfaz comienzan con una letra mayúscula, como en Frame.
  • Los nombres de método, campo y variable local comienzan con una letra minúscula, como en read().
  • Los nombres de clase, método y campo usan todos bicapitalización, como en InputStream y readFully().
  • Las constantes — campos estáticos finales y ocasionalmente variables locales finales — se escriben todo en mayúsculas con subrayados que separan las palabras, como en MAX_CONNECTIONS.

No abrevie

Los nombres como sprintf y nmtkns son reliquias de un tiempo en el que las supercomputadoras tenían 32 KB de memoria. Los compiladores guardaban memoria al limitar los identificadores a 8 caracteres o menos. Sin embargo, esto no ha sido realmente un problema por más de 30 años. Hoy no hay excusa para no escribir totalmente nombres de variables y métodos. Nada marca un programa como el producto de un pirata informático C reformado de manera más evidente que los incomprensibles nombres de variables sin vocales, como en el Listado 3:

Listado 3. Abbrvtd nms r hrd 2 rd
 for (int i = 0; i < nr; i++) { for (int j = 0; j < nc; j++) {
                t[i][j] = s[i][j]; } }

Los nombres sin abreviar en bicapitalización son mucho más legibles, como es posible observar en el Listado 4:

Listado 4. Los nombres sin abreviar son fáciles de leer
 for (int row = 0; row < numRows; row++) { for
                (int column = 0; column < numColumns; column++) { target[row][column] =
                source[row][column]; } }

El código se lee más a menudo de lo que se lo escribe y el lenguaje Java se optimiza para la lectura. Los programadores C tienen una atracción casi machista por el código ofuscado; los programadores Java, no. El lenguaje Java prioriza la legibilidad sobre la concisión.

Algunas abreviaciones son tan comunes que es posible usarlas sin culpa.

  • max de máximo
  • min de mínimo
  • in de InputStream
  • out de OutputStream
  • e o ex para una excepción en una cláusula catch (aunque en ningún otro lado)
  • num de número, aunque solo cuando se usa como prefijo como en numTokenso numHits
  • tmp para una variable temporal usada muy localmente — por ejemplo, cuando se intercambian dos valores.

En otros casos, y tal vez en algunos otros, usted debería escribir todas las palabras completas usadas en los nombres.


Declaración de la variable, inicialización y (re)utilización

Las primeras versiones de C necesitaban que todas las variables se declaren al comienzo del método. Esto permitió ciertas optimizaciones en el compilador que le dejó ejecutarse en entornos que eran bastante míseros con RAM: Así los métodos en C tienden a comenzar con varias líneas de declaraciones de las variables:

int i, j, k; double x, y, z; float cf[], gh[], jk[];

Sin embargo, este estilo tiene una cantidad de efectos negativos. Separa la declaración de la variable de su uso, lo que hace que el código sea un poco difícil de seguir. Además, hace mucho más probable que una variable local sea reutilizada para varios fines diferentes, posiblemente de modo involuntario. Esto puede introducir errores inesperados cuando una variable posee un valor sobrante que una parte del código no estaba esperando. Combine esto con la inclinación de C por los nombres de variables cortos y crípticos y obtendrá una receta para el desastre.

En el lenguaje Java (y versiones más recientes de C), las variables pueden declararse en o cerca del punto de primer uso. Haga esto cuando escriba el código Java. Hace que su código sea más seguro, menos propenso a errores y más fácil de leer.

En una nota relacionada, el código Java normalmente inicializa cada variable cuando y donde se declara. Los programadores C a veces escriben el código del siguiente modo:

int i; i = 7;

Los programadores Java casi nunca escriben un código de esa forma, aunque sea sintácticamente correcta. Ellos lo escriben de esta forma:

int i = 7;

Esto ayuda a evitar errores que resultan del uso involuntario de variables sin inicializar. La única excepción común sucede cuando una sola variable necesita ser registrada en un bloque try y un bloque catch o finally . Esto muy frecuentemente surge cuando el código trata con corrientes de entrada y corrientes de salida que necesitan cerrarse en el bloque finally , como se muestra en el Listado 5:

Listado 5. El manejo de excepciones puede hacer que sea difícil registrar variables adecuadamente
                InputStream in = null; try { in = new FileInputStream("data.txt"); // read from
                InputStream } finally { if (in != null) { in.close(); } }

Sin embargo, ese es casi el único momento en que esto sucede.

Finalmente, el último efecto colateral de este estilo es que los programadores Java normalmente declaran solo una variable por línea. Por ejemplo, inicializan tres variables del siguiente modo:

int i = 3; int j = 8; int k = 9;

Tienden a no escribir el código de esta forma:

int i=3, j=8, k=9;

Esta sentencia es sintácticamente correcta, pero los programadores Java a tiempo completo habitualmente no hacen eso, excepto en un caso especial que mencionaré a continuación.

Un programador C de estilo antiguo puede incluso escribir el código en cuatro líneas:

int i, j, k; i = 3; j = 8; k = 9;

Así, el estilo Java habitual es en realidad un poco más conciso en solo tres líneas porque combina declaración e inicialización.

Empuje las variables dentro de los bucles

Un caso especial que aparece frecuentemente es la declaración de variables fuera de los bucles. Por ejemplo, considere el bucle simple for en el Listado 6, que calcula los primeros 20 términos de la secuencia Fibonacci:

Listado 6. A los programadores C les gusta declarar variables fuera de los bucles
int high = 1; int low
                = 1; int tmp; int i; for (i = 1; i < 20; i++) { System.out.println(high); tmp =
                high; high = high+ low; low = tmp; }

Las cuatro variables se declaran fuera del bucle y, por lo tanto, tienen un ámbito excesivo aunque solo se usan dentro del bucle. Esto está propenso a errores porque las variables pueden reutilizarse fuera del ámbito en el que se destinó para ser usadas Esto es especialmente cierto para las variables con nombres comunes tales como i y tmp. Los valores de un uso pueden perdurar e interferir con el código posterior en maneras inesperadas.

La primera mejoría (que también está respaldada por versiones modernas de C) es mover la declaración de la variable de bucle i dentro del bucle, como se muestra en el Listado 7:

Listado 7. Mueva variables de bucle adentro del bucle
int high = 1; int low = 1; int tmp; for (int i = 1; i
                < 20; i++) { System.out.println(high); tmp = high; high = high+ low; low = tmp;
                }

Sin embargo, no se detenga ahí. Los programadores Java experimentados también moverán la variable tmp dentro del bucle, como en el Listado 8:

Listado 8. Declare variables temporales dentro de bucles
int high = 1; int low = 1; for (int i = 1;
                i < 20; i++) { System.out.println(high); int tmp = high; high = high+ low; low =
                tmp; }

Los estudiantes universitarios sin una obsesión excesiva por la velocidad a veces objetan que esto reducirá la velocidad del código al realizar más trabajo de lo que es necesario dentro del bucle. Sin embargo, al tiempo de ejecución, una declaración no realiza absolutamente ningún trabajo. No hay sanción de rendimiento alguna en la plataforma Java por mover una declaración dentro de un bucle.

Muchos programadores, que incluyen a programadores Java experimentados, se detendrán aquí. Sin embargo, hay una técnica que se ha usado poco que mueve todas las variables dentro del bucle. Es posible declarar en realidad más de una variable en la fase de inicialización de un bucle for sencillamente al separarlas con comas, como se muestra en el Listado 9:

Listado 9. Todas las variables dentro del bucle
for (int i = 1, high = 1, low = 1; i < 20; i++) {
                System.out.println(high); int tmp = high; high = high+ low; low = tmp; }

Esto ha pasado ahora más allá del código fluido meramente idiomático a un código verdaderamente experto. Esta habilidad para limitar rigurosamente el ámbito de las variables locales es una gran razón por la que usted ve mucho más bucles for y muchos menos bucles while en código Java que en el código C.

No recicle las variables

Un corolario de lo anterior es que los programadores Java raras veces reutilizan las variables locales para valores y objetos diferentes. Por ejemplo, el Listado 10 programa algunos botones con ActionListeners asociados:

Listado 10. Reciclado de variables locales
Button b = new Button("Play"); b.addActionListener(new
                PlayAction()); b = new Button("Pause"); b.addActionListener(new PauseAction()); b =
                new Button("Rewind"); b.addActionListener(new RewindAction()); b = new
                Button("FastForward"); b.addActionListener(new FastForwardAction()); b = new
                Button("Stop"); b.addActionListener(new StopAction());

Los programadores Java experimentados reescriben esto con cinco variables locales diferentes, como se muestra en el Listado 11:

Listado 11. Variables no recicladas
Button play = new Button("Play"); play.addActionListener(new
                PlayAction()); Button pause = new Button("Pause"); pause.addActionListener(new
                PauseAction()); Button rewind = new Button("Rewind"); rewind.addActionListener(new
                RewindAction()); Button fastForward = new Button("FastForward");
                fastForward.addActionListener(new FastForwardAction()); Button stop = new
                Button("Stop"); stop.addActionListener(new StopAction());

La reutilización de una variable local para varios valores u objetos lógicamente diferentes está propensa a errores. Esencialmente, las variables locales (aunque no siempre los objetos a los que señalan) están libres de asuntos de memoria y tiempo. No tenga miedo de usar tantas variables locales diferentes como sea necesario.

Confíe en el recopilador de basura para gestionar la memoria

Los programadores que vienen del mundo C++ a menudo se preocupan excesivamente sobre el consumo de memoria y las fugas de memoria. Existen dos síntomas comunes de esto. Uno de ellos es la configuración de variables como nulas cuando termina de usarlas. El otro es la invocación de finalize()o su utilización como un tipo de pseudodestructor. Ninguno es necesario normalmente. Aunque hay momentos en los que realmente necesita liberar memoria manualmente en código java, son pocos momentos y muy espaciados en el tiempo. La mayoría del tiempo es posible simplemente contar con el recopilador de basura para hacer algo sensato y razonablemente rápido. Como sucede con la mayoría de las optimizaciones, la mejor regla general es: no las haga a menos, y hasta, que sea posible demostrar que son necesarias.

Utilice los tipos de datos primitivos preferidos

El lenguaje Java tiene ocho tipos de datos primitivos pero solo se utilizan seis de ellos. En el código Java, floatsson mucho menos comunes que en el código C. Casi nunca ve variables o literales floats en el código Java; doublesse prefieren más. El único momento en que se usan floatses en el manejo de grandes matrices multidimensionales de números de punto flotante con precisión limitada en que el espacio de almacenamiento sería importante. Aparte de eso, solo haga todo un doubles.

Incluso menos común que los floatsson los shorts.Raras veces he visto una variable short en el código Java. En el único momento en el que aparece — y esto es extremadamente raro, le advierto —, es cuando se leen formatos de datos externamente definidos que incluyen un tipo entero firmado de 16 bits. En esa situación, la mayoría de los programadores solo leen eso como un int.


Ámbito de privacidad

¿Alguna vez ha visto un método equals() como el ejemplo en el Listado 12?

Listado 12. Un método equals() escrito por un programador C++
public
                class Foo { private double x; public double getX() { return this.x; } public boolean
                equals(Object o) { if (o instanceof Foo) { Foo f = (Foo) o; return this.x ==
                f.getX(); } return false; } }

Este método es técnicamente correcto pero puedo prácticamente garantizarle que esta clase fue escrita por un programador C++ recalcitrante. La señal delatora es el uso del campo privado x y el método getter público getX() en el mismo método y efectivamente en la misma línea. En C++, esto es necesario porque la privacidad se registra en el ámbito del objeto en lugar de la clase. Es decir, en C++, los objetos de la misma clase no pueden ver las variables asociadas privadas de uno y otro. En cambio, deben usar métodos accessor. En el lenguaje Java, la privacidad se registra en el ámbito de la clase en lugar del objeto. Dos objetos, cada uno de tipo Foo pueden acceder directamente a los campos privados de uno y otro.

Algunas consideraciones sutiles — y más a menudo irrelevantes — sugieren que usted puede preferir el acceso de campo directo antes del acceso getter o viceversa dentro del código Java. El acceso de campo puede ser ligeramente más rápido, pero en raras ocasiones. Algunas veces, el acceso getter puede brindar un valor un poco diferente del acceso de campo directo, especialmente cuando las subclases están en juego. Sin embargo, en el lenguaje Java, nunca hay ninguna excusa para usar ambos, acceso de campo directo y acceso getter, para el mismo campo de la misma clase en la misma línea.


Modismos de puntuación y sintaxis

Aquí hay algunos modismos de Java que discrepan de sus homólogos C, en algunos casos para aprovechar ciertas características del lenguaje Java.

Ubique delimitadores de matriz en el tipo

El lenguaje Java declara matrices del mismo modo que se hace en C:

int k[]; double temperature[]; String names[];

Sin embargo, el lenguaje Java también ofrece una sintaxis alternativa en la que los delimitadores de matriz se ubican luego del tipo en lugar de luego del nombre de la variable:

int[] k; double[] temperatures; String[] names;

La mayoría de los programadores Java han adoptado el segundo estilo. Esto dice que k tiene la matriz de tipo de int, temperatures tiene la matriz de tipo de doublesy names tiene la matriz de tipo de Strings.

También, como con otras variables locales, los programadores Java tienden a inicializar la matriz en el punto en el que se declara:

int[] k = new int[10]; double[] temperatures = new double[75];
                String[] names = new String[32];

Use s == null, no null == s

Los cuidadosos programadores C han aprendido a colocar literales en el lado izquierdo de los operadores de comparación. Por ejemplo:

if (7 == x) doSomething();

La meta aquí es evitar accidentalmente utilizar el operador de la asignación de iguales solos en lugar del operador de comparación de iguales dobles:

if (7 = x) doSomething();

Ubicar el literal en el lado izquierdo hace que esto sea un error de tiempo de compilación. Esta técnica es una buena práctica de programación en C. Ayuda a prevenir errores reales porque al ubicar el literal en el lado derecho hace que esto siempre devuelva true.

Sin embargo, el lenguaje Java, a diferencia de C, tiene tipos separados int y boolean . El operador de asignación devuelve un int, por cuanto el operador de comparación devuelve un boolean. Por consiguiente, if (x = 7) ya es un error de tiempo de compilación, por lo que no hay razón para utilizar la forma anormal if (7 == x) para sentencias de comparación y los programadores Java fluidos no lo hacen.

Las cadenas concatenadas en lugar de formatearlas

Por muchos años, el lenguaje Java no tenía una función printf() . Esto se agregó finalmente en Java 5 y tiene algunos usos ocasionales. En particular, las series de formato son un lenguaje de dominio específico conveniente para los casos raros cuando usted quiere formatear números para anchuras particulares o con una cierta cantidad de lugares luego del separador decimal. Sin embargo, los programadores C tienden a usar excesivamente printf() en su código Java. Generalmente, no se lo debería usar meramente como una sustitución de una concatenación de cadena simple. Por ejemplo:

System.out.println("There were " + numErrors + " errors
                reported.");

es preferible antes que:

System.out.printf("There were %d errors reported.\n",
                numErrors);

La variante que usa la concatenación de cadena es más fácil de leer, en especial en casos simples, y menos propenso a error porque no hay peligro de no coincidencia entre marcadores en la serie de formato y la cantidad o el tipo de los argumentos variables.

Preferencia del incremento posterior antes que el incremento previo

Hay lugares donde la diferencia entre i++ y ++i es importante. Los programadores Java tienen un nombre especial para estos lugares. Se llaman "errores".

Usted nunca debería escribir un código que dependa de la diferencia entre el incremento previo y el incremento posterior (y eso también es válido para C). Es simplemente muy difícil de seguir y muy propenso al error. Si usted está escribiendo un código donde la diferencia sí importa, entonces reorganice el código en sentencias separadas para que no importe más.

Donde la diferencia entre el incremento previo y el incremento posterior es insignificante — por ejemplo, como en el paso de incremento de un bucle for—, los programadores Java prefieren el incremento posterior antes que el incremento previo alrededor de 4 a 1. i++ es mucho más común que ++i. No puedo justificar eso pero es así. Si escribe ++i, cualquiera que lea su código va a perder tiempo preguntándose por qué lo escribió así. En consecuencia, debería usar siempre el incremento posterior a menos que tenga una razón particular para usar el incremento previo (y nunca debería tener una razón para usar el incremento previo).


Manejo de errores

El manejo de errores es una de las cuestiones que más se confunden en la programación Java y una que realmente separa a los diseñadores maestros del lenguaje de los gruñones y murmuradores. Efectivamente, podría fácilmente ser la base de un artículo en sí mismo. En pocas palabras, use las excepciones adecuadamente y nunca devolverá códigos de error.

El primer error de los hablantes no nativos es devolver un valor que indica un error, en lugar de arrojar una excepción. Efectivamente, puede incluso ver esto en algunos de los API propios del lenguaje Java que se remontan a los primeros días de Java 1.0, antes de que todos los programadores en Sun hubieran internalizado completamente el lenguaje nuevo. Por ejemplo, considere el método delete() en java.io.File:

public boolean delete()

Este método devuelve true si el archivo o directorio se suprime con éxito. Si no, devuelve false. Lo que debería hacer es no devolver nada cuando se finaliza con éxito y arrojar una excepción si el archivo existe pero no se puede suprimir por alguna razón:

public void delete() throws IOException

Cuando los métodos devuelven valores de error, cada llamada de método está rodeada por un código de manejo de errores. Esto hace que sea difícil de seguir y entender el flujo normal de ejecución del método cuando, como normalmente es el caso, no hay problema y todo está bien. En cambio, cuando las condiciones de error se indican por excepciones, el manejo de errores puede sacarse del camino en un bloque de código separado más tarde en el archivo. Se lo puede mover incluso a otros métodos y otras clases si existe un lugar más adecuado para manejar el problema.

Esto me lleva al segundo antipatrón en el manejo de errores. Los programadores que vienen de un ambiente C o C++ a veces intentan manejar excepciones tan cerca como sea posible hasta el punto que se arroja la excepción. Tomado al extremo, puede resultar en un código como el Listado 13:

Listado 13. Manejo de excepciones muy temprano
public void readNumberFromFile(String name) {
                FileInputStream in; try { in = new FileInputStream(name); } catch
                (FileNotFoundException e) { System.err.println(e.getMessage()); return; }
                InputStreamReader reader; try { reader = new InputStreamReader(in, "UTF-8"); } catch
                (UnsupportedEncodingException e) { System.err.println("This can't happen!"); return;
                } BufferedReader buffer = new BufferedReader(reader); String line; try { line =
                buffer.readLine(); } catch (IOException e) { System.err.println(e.getMessage());
                return; } double x; try { x = Double.parseDouble(line); } catch
                (NumberFormatException e) { System.err.println(e.getMessage()); return; }
                System.out.println("Read: " + x); }

Esto es tan difícil de leer e incluso más intricado que las pruebas if (errorCondition) que el manejo de excepciones fue diseñado para sustituir. El código Java fluido mueve el manejo de errores fuera del punto de falla. No mezcla el código de manejo de errores con el flujo normal de ejecución. La versión en el Listado 14 es mucho más fácil de seguir y entender:

Listado 14. Mantenga junto el código para la ruta principal de ejecución
public void
                readNumberFromFile(String name) { try { FileInputStream in = new
                FileInputStream(name); InputStreamReader reader = new InputStreamReader(in,
                "UTF-8"); BufferedReader buffer = new BufferedReader(reader); String line =
                buffer.readLine(); double x = Double.parseDouble(line); System.out.println("Read: "
                + x); in.close(); } catch (NumberFormatException e) { System.err.println("Data
                format error"); } catch (IOException e) { System.err.println("Error reading from
                file: " + name); } }

Ocasionalmente, usted puede necesitar usar bloques anidados try-catch para separar diferentes modos de fallas que producen la misma excepción pero esto no es común. La regla general es que si hay más de un valor de código del bloque tryen un método, entonces el método es muy grande y probablemente debería dividirse en métodos más pequeños de todos modos.

Finalmente, los programadores nuevos en la programación Java de todos los lenguajes a menudo cometen el error de asumir que deben obtener excepciones verificadas en el método donde se arrojan. En muchas ocasiones, el método que arroja la excepción no es el método que debería obtenerla. Por ejemplo, considere un método que copie secuencias, como en el Listado 15:

Listado 15. Manejo de excepciones muy temprano
public static void copy(InputStream in, OutputStream out)
                { try { while (true) { int datum = in.read(); if (datum == -1) break;
                out.write(datum); } out.flush(); } catch (IOException ex) {
                System.err.println(ex.getMessage()); } }

El método simplemente no tiene suficiente información para manejar plausiblemente las IOExceptionsque pueden ocurrir. No sabe quién lo llamó y no sabe cuáles son las consecuencias de una falla. Lo único razonable para que este método haga es dejar que la IOException burbujee hasta el interlocutor. El modo correcto para escribir este método se muestra en el Listado 16:

Listado 16. No todas las excepciones tienen que obtenerse en el primer momento posible
public
                static void copy(InputStream in, OutputStream out) throws IOException { while (true)
                { int datum = in.read(); if (datum == -1) break; out.write(datum); } out.flush();
                }

Es más corto. Es más simple. Es más comprensible y transmite la información del error a la parte del código que es más adecuado para manejarla.


¿Cuánto importa esto en realidad?

Ninguno de estos son problemas críticos. Algunos de ellos tienen motivo para la convención: Declarar las variables en el punto del primer uso, arrojar excepciones cuando no sabe qué hacer con ellas. Otros son de convención puramente estilística (args, no argv; i++ en lugar de ++i). No voy a asegurar que seguir cualquiera de estas reglas hará que su código se ejecute más rápido y solo algunas de ellas le ayudarán a evitar errores. Sin embargo, todas ellas son necesarias para convertirse en un hablante Java con fluidez nativa.

Para bien o para mal, hablar (o escribir un código) sin acento causará que otros lo respeten más, le presten más atención a lo que dice e incluso le paguen más para que lo diga. Además, hablar el lenguaje Java sin acento en realidad es mucho más fácil que hablar francés, chino o inglés sin acento. Una vez que usted haya aprendido el lenguaje, vale la pena hacer el esfuerzo extra para hablarlo como lo haría un nativo.

Recursos

Aprender

  • Code Conventions for the Java Programming Language: Aunque es un poco anticuada, esta referencia todavía sirve como la base para el estilo Java moderno.
  • The Java Language Specification (James Gosling et al., Addison Wesley, 2005): Ahora en su tercera edición, esta fue tal vez la primera especificación de lenguaje para reconocer que se necesitaba debatir el estilo, así como también la sintaxis y la semántica. Es una razón importante que el lenguaje Java tenga un estilo mucho más estándar a través de grupos y proyectos que el que tienen los primeros lenguajes, como C++ y Basic.
  • Effective Java, 2.º ed. (Joshua Bloch, Prentice Hall, 2008): El libro de Bloch cubre muchos de los aspectos más semánticos del estilo Java.
  • "Java programming for C/C++ developers" (James Stricker, developerWorks, mayo del 2002): Este tutorial está diseñado para programadores C o C++ que quieren aprender cómo programar en el lenguaje Java.
  • Lo nuevo en la programación Java: Lea una visión general de los conceptos básicos de la tecnología Java y descubra cómo la tecnología se integra en el contexto del desarrollo de software contemporáneo.
  • Explore la technology bookstore para encontrar libros sobre estos y otros temas técnicos.
  • Libreria Java en developerWorks: Encuentre cientos de artículos acerca de cada aspecto de la programación Java.

Comentar

Comentarios

developerWorks: Ingrese

Los campos obligatorios están marcados con un asterisco (*).


¿Necesita un IBM ID?
¿Olvidó su IBM ID?


¿Olvidó su Password?
Cambie su Password

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


La primera vez que inicie sesión en developerWorks, se creará un perfil para usted. La información en su propio perfil (nombre, país/región y nombre de la empresa) se muestra al público y acompañará a cualquier contenido que publique, a menos que opte por la opción de ocultar el nombre de su empresa. Puede actualizar su cuenta de IBM en cualquier momento.

Toda la información enviada es segura.

Elija su nombre para mostrar



La primera vez que inicia sesión en developerWorks se crea un perfil para usted, teniendo que elegir un nombre para mostrar en el mismo. Este nombre acompañará el contenido que usted publique en developerWorks.

Por favor elija un nombre de 3 - 31 caracteres. Su nombre de usuario debe ser único en la comunidad developerWorks y debe ser distinto a su dirección de email por motivos de privacidad.

Los campos obligatorios están marcados con un asterisco (*).

(Por favor elija un nombre de 3 - 31 caracteres.)

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


Toda la información enviada es segura.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=90
Zone=tecnologia Java
ArticleID=963230
ArticleTitle=Hable el lenguaje Java sin acento
publish-date=12102012