Tag Archives: java

Introducción al mundo de la programación (en especial via Java)

Estimados,

LO QUE ME HUBIESE GUSTADO que me explicasen a manera de introducción en el mundo de la programación, en especial la de Java.

Analogía del proceso de construcción de software.

Suponga que ud. acaba de comprar una exitosa microempresa de Importaciones. Ahora para ud. trabaja un empleado excelente que le envía la mercancía desde Corea del Sur. Ese empleado tiene un sólo defecto: Ese empleado sólamente habla Coreano. No habla, ni entiende español, sólo lee vagamente el inglés. Y suponga que el inglés suyo, es también muy básico.

  • Se imagina como podrá entonces darle instrucciones a ese empleado ?
  • Se imagina que tipo de problemas podría surgir ?

… llevemos entonces ese ejemplo al contexto de construcción y codificación de software (programación).

Siguiendo el ejemplo, ud. es el dueño de la empresa, el programa que va a construir son las instrucciones que le va a dar al empleado … y el empleado sería el computador en donde se va a ejecutar dicho programa. El inglés (siguiendo el ejemplo), sería el lenguaje en el que se van a comunicar esas instrucciones, es decir, el programador (el dueño de la empresa) es el que decide qué es lo que el empleado (computador) debe realizar, y para ello, se necesita que estén dichas instrucciones en un lenguaje común (en el ejemplo, el inglés, y en el contexto vendría siendo el lenguaje de programación Java).

Problemas que pueden surgir:

  1.  El dueño NO sabe exactamente lo que quiere, por lo que las instrucciones se imparten mal (y a pesar que el empleado las siga al pié de la letra, el resultado será diferente a lo que el dueño requiere). Aquí podríamos decir que son errores al crear el Algoritmo, es decir ese boceto, plan inicial, o lógica de las instrucciones (que posteriormente se escribirán dentro de un programa).
  2.  El dueño SI sabe exactamente lo que quiere, pero las instrucciones las imparte mal pues no domina el lenguaje común (inglés, Java) (y a pesar que el empleado las siga al pié de la letra, el resultado será diferente a lo que el dueño requiere). Aquí podríamos decir que el programador ha cometido un error al codificar las instrucciones, a éste tipo de errores les podemos llamar Errores de Sintáxis.
  3. El dueño SI sabe exactamente lo que quiere, escribe adecuadamente usando el lenguaje común, pero el empleado NO las sigue al pié de la letra. Este tipo de problemas NO se presenta en programación, a menos que el propio lenguaje de programación (el software usado por ejemplo eclipse, bluej o la máquina virtual de java) tengan un error de programación (del fábricante).
  4.  El dueño SI sabe exactamente lo que quiere, escribe adecuadamente usando el lenguaje común, pero el empleado NO las sigue al pié de la letra. Este tipo de problemas NO se presenta en programación, a menos que el propio lenguaje de programación (el software usado por ejemplo eclipse, bluej o la máquina virtual de java) tengan un error de programación (del fábricante).
  5.  El dueño SI sabe exactamente lo que quiere, escribe adecuadamente usando el lenguaje común, el empleado SI las sigue al pié de la letra, pero aún así el dueño NO contempló casos como que la materia prima no pudo ser entregada a tiempo al empleado y éste NO pudo fabricar el producto. Este tipo de problemas SI se presenta en programación, sería el equivalente a errores de RUNTIME o errores en tiempo de ejecución. Por ejemplo, el programa necesita abrir un archivo de imagen para mostrarla en pantalla, pero se olvidó incluir instrucciones sobre qué hacer en caso de que dicha imagen no exista… entonces se generará un Error en tiempo de ejecución (en este caso lo generaría la máquina virtual Java pues el programador no contempló ese caso).

El Resumen hasta este punto:

El Dueño = El Programador ( cabe aclarar que el dueño también tiene su jefe, que sería el cliente, quien es el que pide algo específico. En este caso, el programador tendrá su jefe ya sea un ingeniero, el gerente de la empresa, o un cliente final quien usualmente es el que paga por el programa, o paga el sueldo del programador, o en general, decide qué debe hacerse en el programa a construir. Para nuestro caso si somos alumnos, pues el cliente sería el profesor o tutor que pide algo específico en el programa).

  • El Lenguaje = Lenguaje de Programación (para nuestro caso, sería el lenguaje Java).
  • El medio de comunicación = Nuestro programa, se codifica en archivos de texto con sintáxis específica del lenguaje y con extensión de archivo .java (a ésto sin importar el lenguaje de programación, usualmente se le llama Código Fuente del programa).
  • El Empleado = El (o los) computadores en donde se ejecutará el programa una vez esté en formato ejecutable. En nuestro caso el proceso completo sería, escribimos el código fuente en archivos .java, ejecutamos un proceso de Compilación (proceso en el que se revisa la sintáxis o forma en la que la máquina espera que se escriban las instrucciones de java, y si no hay ningún error de sintáxis se generará código en formato ejecutable -por java, se llama bytecode y son archivos con extensión .class).
  • Errores = Situaciones fuera de lo ideal, que pueden ser de lógica (errores en el algoritmo -es decir no está de acuerdo a la intención del programador o a lo que pidió el cliente- ), de sintáxis (se escribió mal alguna instrucción y al momento de Compilar la aplicación usada -bluej, eclipse, o la línea de comandos de java- no puede continuar), de tiempo de ejecución (un caso no contemplado o en el algoritmo o en el programa escrito, pero que de todas formas la máquina virtual de java lanza un error -llamado excepción- general o específica, pero que usualmente detiene la ejecución del programa inesperadamente).

Ejemplo de construcción de un programa

Hacer un programa en Java que cumpla las especificaciones (requerimientos, solicitud. En matemáticas se le llamaría Enunciado del problema):

a) El programa debe contar de 1 hasta diez.
b) El programa debe mostrar en pantalla el contador del punto a) y además, al finalizar debe mostrar la frase “Proceso Terminado.”

Nota: Existen muchas soluciones a un mismo problema y muchas variaciones para cada solución (por lo tanto lo que se evalúa al final es si el programa satisface o no las especificaciones, esto es, si cumple o no con lo que se pidió).

El primer paso es analizar las especificaciones, y determinar cuales son los datos de entrada (lo que se le pide al usuario o se lee por red o de un archivo para que el programa puede trabajar), cuales son los datos de salida (lo que el programa mostrará en pantalla o impresora, guardará en archivos, etc..).

Datos de Entrada -> En este caso No Hay (si hubieran pedido que el usuario sea capaz de decir hasta cuanto quiere que el programa cuente, ése sería un dato de entrada, pero aquí se dice que va a contar de 1 a 10 y ésto se hará sin intervención del usuario).

Datos de Salida -> En este caso el dato de salida sería el valor del Contador (No se considera dato de salida a la frase “Proceso Terminado.” puesto que NO va cambiar de valor durante el programa, es decir, será constante y NO se utilizará una variable para almacenar su valor -se podría pero sería inútil, pues no va a cambiar el valor-).

El segundo paso es pensar en la solución en lenguaje natural, es decir, para contar de 1 a 10 se necesitaría de alguna forma, incrementar el valor inicial de uno en uno hasta llegar a 10. Si el programa cuenta desde cero, estaría mal (no cumple con las especificaciones). Si el programa cuenta hasta 11, no cumpliría las especificaciones tampoco. Por lo tanto necesitamos escribir a la final un programa que comience desde 1 en incrementos de 1 (sumar de uno en uno), cada vez que sume mostrar el valor de ese contador, hasta que el contador sea 10. Luego de que termine, mostrar en pantalla la frase requerida.

El tercer paso es hacer el algoritmo (se le llama también pseudo-código), que no es mas que un punto intermedio entre el lenguaje natural y el código en lenguaje de programación. Ese algoritmo en teoría serviría como base para pasar ese programa a CUALQUIER lenguaje de programación, pues la LÓGICA del programa se expresa de una forma INDEPENDIENTE del lenguaje de programación. Como éste algoritmo NO va a ser tal cual copiado y pegado en un editor para ejecutarse (pues no está escrito en lenguaje de programación), se permiten ciertas libertades, pero igual hay ciertas normas o palabras que hay que manejar como Inicio, Fin, Para, Mientras Que, Lea, Escriba, etc… es decir, su SINTAXIS no es muy estricta, pero igual sería bueno familiarizarse con términos y buscar apoyo en algoritmos ya creados por ejemplo, disponibles en internet. A continuación el algoritmo propuesto para este caso:

Algoritmo:

Inicio
Para contador = 1, 10
Escriba contador
contador = contador + 1
Fin Para
Escriba “Proceso Terminado.”
Fin

El cuarto paso sería definir (si a éstas alturas no se ha hecho) el lenguaje de programación que se va a utilizar para codificar (escribir, crear el código fuente) éste programa. Como se nos pide que sea en Java, entonces obligatoriamente debemos estudiar, familiarizarnos y finalmente conocer la SINTÁXIS y reglas para programar en Java. La sintáxis se refiere a los términos, palabras especiales (reservadas), tipos de datos, forma en general de comunicar a la máquina, que éste es un programa en Java. Por ejemplo si en español decimos “¿Qué dices tu?” es lo mismo que decir “¿Tu que dices?”, sin embargo, en Java,

contador = contador + 1

NO es igual a escribir:

1 + contador = contador

… pues saldría un error de SINTÁXIS diciendo que esperaba una variable (contador) pero encontró fue un valor (el 1 ). Se dice que Java es un lenguaje fuertemente Tipado, con sintáxis muy estricta (o sea que en nuestra anología, al dueño, además de aprender/mejorar su inglés, le toca aprender cómo el empleado interpreta las instrucciones, o si no, el empleado NO va a entender lo que debe hacer).

Programa Contar.java (Basados en el algoritmo propuesto):

public class Contar
{
public Contar()
{
for(int contador=1; contador<=10 ; contador++){
System.out.println(contador);
}
System.out.println(“Proceso Terminado.”);
}

… Vemos que NO es EXACTAMENTE igual al algoritmo, pues obviamente ahora es un código fuente en Java, o sea, un archivo de texto con extensión .java, que contiene instrucciones en lenguaje de programación Java. Línea por Línea hagamos la comparación contra la versión en algoritmo. Para ello adicionemos (solo para éste ejemplo, si lo hacemos en el archivo .java el programa NO va a ejecutarse):

1. public class Contar
2. {
3. public Contar()
4. {
5. for(int contador=1; contador<=10 ; contador++){
6. System.out.println(contador);
7. }
8. System.out.println(“Proceso Terminado.”);
9. }
10.
11.}

Línea 1. public class Contar => Estamos diciendo que éste archivo Contar.java va a contener una Clase (ver mas adelante explicación del paradigma 2. Programación Orientada a Objetos.), esa Clase obligatoriamente DEBE llamarse igual al archivo .java para que pueda funcionar ésta forma de trabajar (hay otras formas de trabajar que no miraremos en este punto, por ahora, si mi archivo se llama Contar.java, dentro de el archivo debe haber una Clase llamada Contar). Se define como public para que pueda (si fuera necesario) ser llamada o utilizada desde otro .java diferente.

Línea 2. { => la llave indica que se empieza un bloque de código, en este caso, se empieza a definir el contenido de la mencionada Clase Contar. Note que en el algoritmo NO hay por ningún lado ni definición de clase ni en Java hay sección Inicio, precisamente porque el algoritmo se pretende que lo interprete adecuadamente un programador (humano), y el código fuente una máquina (en éste caso, luego del proceso de compilación -proceso de verificación de sintáxis y creación de un código ejecutable- lo interpreta la máquina virtual de java).

Línea 3. public Contar() => Realmente los espacios extra antes de cada línea (o usar la tecla Tab) no los necesita el código, pero se añaden para mayor legibilidad del HUMANO. Los espacios por ejemplo para separar public de Contar() SÍ se necesitan, pues forman parte de la sintáxis para reconocer palabras reservadas o instrucciones, de variables y métodos. Entonces public Contar() lo que está diciendo es que de esa Clase Contar, cuando se vaya a ejecutar, la construya mediante un método (procedimiento o bloque de código que se puede llamar desde algún punto del programa, mas adelante se explica su utilidad pero piénsenlo como un mini-programa con sus datos de entrada, proceso y salida). Por lo tanto, con ésta línea, Java sabe que de ahí en adelante el bloque de código que viene encerrado entre llaves, se le va a poner un nombre específico, en este caso, Contar. Para nuestra clase Contar, hay que definir entonces un método con el MISMO NOMBRE, Contar, de ésta forma Java sabe que ése método (al que se llama método contructor) es el que se debe ejecutar apenas se cargue la clase Contar.

Línea 4. { => Llave que abre, indica comienzo del bloque de código.

Línea 5. for(int contador=1; contador<=10 ; contador++){ => Aquí se reemplaza la línea Para del algoritmo, por un comando o instrucción de Java, que permite de una vez definir un ciclo o “loop”, en especial para trabajar con valores numéricos en la condición (a diferencia del mientras que -while en java- que se usa mas que todo para hacer ciclos que interactúan con condiciones no-numéricas). Lo que estamos diciendo aquí es que Abra un ciclo usando como contador la variable contador (para abreviar muchas veces se usa la variable con nombre i). Como no hemos definido la variable contador, el for permite de una vez definirla sobre la marcha antes de iniciar los ciclos, es por eso que ponemos for(int contador=1; es decir, de una vez le decimos que es de tipo de datos int (entero, para almacenar números enteros). luego después del punto y coma se le dice que ese ciclo se va a ejecutar hasta que la variable contador sea MENOR o IGUAL a 10 , y luego del punto y coma, se le está diciendo que por cada vez que vaya a repetir ese ciclo, se le sume 1 a la variable contador (contador++ es equivalente a decir contador = contador + 1). Se termina de una vez abriendo la llave (se podría haber insertado una línea en blanco, no es obligatorio que se abra llave en la misma línea del for. Abriendo la llave indica entonces que a continuación, las líneas que siguen son del bloque de código (líneas) que se ejecutarán cada vez que se ejecute ese ciclo for según las condiciones de la variable usada en este caso, la variable contador.

Línea 6. System.out.println(contador); => Note que casi todas las instrucciones (las que no tienen luego bloques de código encerrados en llaves) terminan en un punto y coma (;) .. se debe utilizar el punto y coma al final, para indicar que ahí termina la instrucción. System.out.println(contador); lo que hace es (léa todas las instrucciones de izquierda derecha, pues así las lee Java) Referenciar internamente una Clase externa (diferente a mi archivo .java actual), usualmente dentro de un paquete o librería (que es un conjunto de programas relacionados entre sí para hacer algo, por ejemplo, para interactuar con la pantalla, o para ejecutar operaciones matemáticas avanzadas, para trabajar con archivos, etc..) y de ahí ejecutar un método (procedimiento, pero en java se le llama método) específico. En éste caso, la Clase se llama System y dentro tiene varias funcionalidades, aquí se usará el paquete out (para interactuar con las salidas a la pantalla) y dentro un método llamado println. Note que System se escribe con la primera en Mayúscula al ser una Clase, out se escribe todo en minúsculas, y el método usualmente (por mejores prácticas de codificación, legibilidad y seguir algún tipo de estándar de desarrollo) comienza por minúscula y sigue la forma de “camello” o camelCase, en donde por ejemplo, si quiero crear un método que imprima en pantalla, podría llamarlo imprimaPantalla, de ésta forma queda mas legible. System.out.println(contador); lo que hace entonces, es que le pasa la variable contador al método System.out.println para que se imprima en pantalla el valor ACTUAL de la variable contador. En términos más técnicos, se le pasa como PARÁMETRO la variable contador al método println de la clase System.out

Línea 7. } => Se cierra la primera llave, de ésta forma Java interpreta que el bloque de código más interno (el último que se abrió, en este caso, el bloque de contenido del ciclo for) se acaba aquí. Como es un ciclo for, entonces la ejecución del programa regresará a la línea for, Incrementará el valor de la variable contador en uno (contador++ que es lo mismo que contador = contador + 1 ) y evaluará la variable contador (ya no se inicializa int contador = 1 porque ésto sólo se hace la primera vez que se ejecuta el ciclo), lo que se evaluará es si contador <= 10 .. y en caso de que la condición sea verdadera (de que se devuelva un valor de tipo boolean con valor true), ejecutará DE NUEVO TODO el bloque de código de ese ciclo (líenas de código siguiente encerrado entre llaves). Obviamente se ejecutará de nuevo, pero el valor de la variable contador, ha sido incrementada o sea que el resultado será diferente. Ésto se repite (por eso le llamamos ciclo o loop) siempre y cuando se cumpla la condicipon que pusimos en el for, es decir, se imprimirá del 1 al 10 y luego terminará el ciclo, pasando a la línea 8.

Línea 8. System.out.println(“Proceso Terminado.”); => En esta ocasión no le pasamos como PARÁMETRO una variable, sino una constante, es decir, un valor que no cambia y en este caso es de tipo String, y el valor es “Proceso Terminado.” … si se están preguntando porque escribo String en vez de string, es porque string NO existe, int, boolean, char y otros son tipos de dato PRIMITIVOS de Java, mientras que String es una … si, una Clase de Java (así como System…) que almacena una cadena de caracteres, es decir, un arreglo de datos de tipo char. En cristiano sería algo como “Proceso Terminado.” (que es un objeto de tipo String) en realidad está conformado por varios valores (uno por cada letra o caracter que contiene) tipo char “P”, char “r”, char “o” .. etc… pero por lo pronto no enrredemos más y ya sabemos que la Línea 8 lo que hace es imprimir por pantalla la frase solicitada.

Línea 9. } => Se cierra la segundaa llave, de ésta forma Java interpreta que el bloque de código más interno abierto (que ahora sería el bloque del método public Contar) se acaba aquí. Como NO es un ciclo ni nada, la ejecución entonces simplemente avanza a la siguiente línea ejecutable.

Línea 10. => Si, línea en blanco, se hace mas por legibilidad / estándares de codificación, para facilidad del HUMANO y NO de la máquina.

11. } = > Se cierra la última llave… que corresponde a la definición de la clase Contar abierta en la línea 1 .. como no hay mas instrucciones para ejecutar, terminaría el programa. Hay casos en los que un ciclo for o similar, No encuentran condición de salida (es decir, si por ejemplo, añadiésemos una instruccion contador = contador – 1 (note que se estaría restando en vez de sumar), justo antes de cerrar el ciclo for … en un caso como éste, contador arrancaría con valor 1, luego ejecutaría el bloque de código del ciclo (imprimiría 1 en la pantalla), luego restaría contador = contador – 1 llevándonos a tener un valor de 0 en el contador, luego iría a la línea del for, y haría contador++ lo que nos deja nuevamente el valor 1 en contador, para lo cual se ejecuta de nuevo el ciclo, mostrando 1 en pantalla, se vuelve a restar ….. es decir, NO hay condición de salida así se ejecutaría INFINITAMENTE … salvo que se cancele el proceso por el BlueJ, Eclipse o se cancele con control+C si está ejecutándose desde la línea de comando del sistema operativo .. o hasta que se apague el computador / se acabe la batería o se pierda la energía… por lo tanto SIEMPRE hay que verificar que tengamos una condición de salida en los ciclos ya sea for, while, do while, etc… para evitar esos ciclos infinitos (usualmente se le llama a ésta condición “se quedó en un loop” ).

 Cuando ya tenemos el Contar.java creado, Luego hay que ejecutar el programa y ver si hace lo que se nos pidió que hiciéramos, para eso, ántes de ejecutarlo lo debemos COMPILAR. Ahí pueden salir o no, errores de sintáxis.. un nombre no reconcido, que falte al gún caracter, faltó ponerle un punto y coma, cosas así. Para resolverlos => Google es tu amigo… pero debe uno de ir aprendiendo a reconocer la línea y el caracter que se muestran con error, la razón y como se arregla, y si ese arreglo afecta o no lo que queríamos hacer en esa línea (de acuerdo a las especificaciones y al algoritmo). O sea, no es cosa de arreglar para que no salga el error de sintáxis solamente, sino mirar si no producimos un error lógico (en tiempo de ejecución, al momento de ejecutar el programa). Por ejemplo, si simplemente ponemos en comentario la línea 8, algo así como

// System.out.println(“Proceso Terminado.”);

.. porque nos saliera un error (suponiendo), entonces el programa correría PERO NO CUMPLIRÍA la especificación completa, pues claramente se nos pide que al final, imprimamos la frase mencionada. Ahí hay que intentar razonar según como la máquina se comporta, no se asume ni se presume nada, si no está codificado, si se me olvidó cerrar una llave, en tiempo de compilación aparecerá el error correspondiente, pero no puedo solucionarlo simplemente quitando o poniendo en comentario entonces (de manera definitiva) un bloque de código problemático, salvo que sea temporal (para ver si es allí el problema), y luego proceder a solucionar la sintáxis sin crear problemas en la lógica.

Descripción del Proceso normal o habitual de construcción de software:

Pondremos el ejemplo de crear un programa desde cero (es decir, que no es modificación o complementar o corregir uno existente). … Aunque existen varios modelos de construcción de software y muchas teorías y enfoques al respecto, en general son muy parecidas, puesto que se contemplen o no formalmente metodologías, termina pareciéndose al siguiente proceso :

  1. Surge una necesidad de hacer un programa que supla una o varias necesidades existentes.
  2. Usualmente hay un cliente (o profesor o jefe), un ingeniero o programador líder junto con uno o mas programadores.
  3. Se establecen ciclos de trabajo : Verificar requerimientos, crear/actualizar algoritmos, revisar algoritmos (no necesariamente el algoritmo se revisa con el cliente, pero al menos se verifica que se entendió bien qué es lo que se quiere solucionar con el programa, es decir, las Especificaciones del programa).
  4. Se procede a diseñar los subprogramas necesarios y su interconexión (aquí aparecen muchos otros tanto diagramas como términos, como clases, métodos, propiedades, definiar las tablas de la base de datos, protocolos de comunicación, etc..).
  5. Se valida el diseño entre programadores (el lider, responsable, ingeniero o arquitecto de software -como se le llama recientemente- es quien tendría la visión global de todo el proyecto, y partes del diseño del proyecto podría en ocasiones delegarse a programadores experimentados.
  6. Se distribuye el trabajo de programación, se fijan tiempos de entrega y se da el visto bueno para comenzar a codificar (aquí es donde se empezarían a crear los archivos .java).
  7. Cada programador entonces, tiene su propio ciclo de escribir, probar, modificar, probar, tantas veces sea necesario para cumplir con su parte de las especificaciones. En las empresas/proyectos grandes, se tienen personas específicas para realizar las pruebas al programa, y así garantizar la calidad del mismo (que cumpla con las especifiaciones). A éste grupo de personas se les dice que son los de QA (Quality Assurance) o los Testers, en general, los que hacen el Testing.
  8. Cuando cada parte distribuida en módulos, o funcionalidades, o sea cual sea la distribución, pero usualmente cuando la mayoría de las partes ha sido Testeada o probada, ahí se hace una prueba general antes de entregar esa fase del proyecto (un proyecto muy largo puede tomar Años por lo que se divide en fases, y se designan especificaciones a cumplir fase por fase). Usualmente es el cliente el que al final aprueba o no, la culminación de la fase. Pero es muy común que el cliente en cualquier punto de cualquier fase, se dé cuenta que faltó algo por incluir o que quiera cambiar las especificaciones, o que no está a gusto con la solución o parte de un módulo o programa en específico. Aquí entonces se devuelve uno al punto 3. para ver si en realidad el cliente tiene la razón, o si modificar lo que se pide acarreará costos adicionales (y si el cliente está de acuerdo, pues se hacen los cambios – actualizando el cronograma- y se cobra adicional).

Después de muchos ciclos desde el punto 3. al punto 8 (dependiendo del proyecto y de qué tan claros hayan sido los requerimientos, las especificaciones, el diseño, la codificación – programación – y en especial de las pruebas o Testing del software), vendrá un visto bueno o firma de recibido del programa a satisfacción del cliente. Éste es el logro máximo pues el proyecto (o la fase específica) se puede decir que está terminado. Sin embargo, usualmente se hacen contratos de mantenimiento del software, para que cualquier modificación -normalmente mínimas- solicitada por el cliente pueda llevarse a cabo. O por ejemplo, se pueda beneficiar el cliente recibiendo mejoras o actualizaciones del software.

Espero que haya sido de utilidad, y no duden en compartirlo con quienes crean les puede llegar a interesar.