Aprendizaje de Nuevas Tecnologias

En este vídeo, comparto un poco sobre mis ideas de como podemos atacar la necesidad de aprendizaje de nuevas tecnologías cuando ya tenemos experiencia en el mundo de la informática.

Enlaces a la Bibliografia:

Codigo Limpio
Effective Java 2nd Edition
Effective Unit Testing 
The Art Of Unit Testing
Practical Unit Testing with JUnit and Mockito 
ATDD By Example
Growing Object Oriented Software Guided By Tests


Como siempre espero haya sido de tu agrado y recuerda que cualquier comentario es bien recibido.

Hasta la próxima.

Publicado en Blogging | Etiquetado , , , , , , , , | Deja un comentario

Iniciando en C++: La Gran Hada del Poder

He sido un gamer toda mi vida, muchos de los mejores recuerdos que tengo en mi vida son con un control en la mano desde que tenia 4 años, por lo que veras que no puedo explicar de forma sencilla el impacto que los videojuegos han tenido en mi.

Si bien, empece a jugar a muy temprana edad en las consolas de mis amigos, como el Atari 5200 y el NES, puedo decir que mi mayor impacto como fanático lo recibí al ver a mi hermano mayor jugar The Legend Of Zelda: A Link To The Past en el Super Nintendo de un primo; el impacto que tuve en mi infancia de ver algo tan complejo en una consola me dejo sin aliento. Fue tanto el amor que desarrolle por la saga de Zelda que uno de los puntos mas importantes de mi adolescencia fue la espera por el lanzamiento de Ocarine Of Time en el Nintendo 64, a pesar de que mis expectativas de poder comprarlo era nulo.

Entre las tantas cosas que pudiese recalcar sobre la maravilla que son los juegos de Zelda, creo que uno de los puntos que mas me llamo la atención originalmente fue la capacidad que te daba A Link To The Past de nombrar a tu personaje, es decir, aunque el nombre oficial del héroe de los juegos es «Link«, un aspecto importante de la saga es la capacidad de otorgar un nombre que te identifique como jugador.

Nada de esto tiene una importancia real sobre nuestro tutorial o C++, excepto que este es un excelente ejercicio para el que he escogido como nuestro siguiente ejercicio.

La Gran Hada del Poder

La Gran Hada del Poder

La Gran Hada del Poder

La Gran Hada del Poder es un personaje que podemos conseguir en los juego de Ocarine of Time y Majora’s Mask, su función es otorgar al jugador el ataque circular con la espada.

Cuando encontramos a este personaje por primera vez, ella nos recibe con el siguiente discurso (extraído del guion del juego)

«Bienvenido, {Link}! Yo soy la
Gran Hada del Poder!{NEXT}
Voy a otorgarte una nueva técnica de la espada.{NEXT}
Recibela ahora!
{END}»

Como vemos, esta conversación tiene un par de características interesantes, el primero y mas obvio es que el nombre {Link} es variante, puede cambiar dependiendo de como el jugador decida llamar a su personaje; el segundo es que la información se van presentando de forma segmentada, es decir primero un bloque de información y al presionar un botón del control de juego debería ir apareciendo el resto por partes (esto corresponde a diferentes animaciones del personaje en el dialogo).

Ahora la pregunta de rigor es, como podemos reproducir este comportamiento en C++?

Veamos ambos requerimientos por partes

Capturando Información del Usuario

Anteriormente hemos utilizado la función std::cout de la librería iostream para mostrar información por pantalla (el Flujo de Salida Estándar), ahora si por el contrario quisiéramos tomar información desde el teclado (el Flujo de Entrada Estándar) podemos utilizar una función incluida en la misma librería llamada std::cin.

Un ejemplo de su funcionamiento seria

int numero;
std::cin>>numero;
std::cout<<numero;

Si estudiamos la sintaxis, podemos ver que la función opera casi como una inversa de cout y que para inyectar la información de la Entrada Estándar a la variable utilizamos el operador >>; esto funciona sin mayor problema con todos los tipos fundamentales, por lo que la lógica, y la experiencia de nuestros ejercicios anteriores, nos dice que si quisiéramos capturar el nombre del jugador deberíamos utilizar algo como

char* nombreJugador;
std::cin >> nombreJugador;
std::cout << nombreJugador;

Pero si intentaste ejecutar esto, recibirás un error de compilación, particularmente te dira que no has inicializado la variable nombreJugador; si intentas modificar la variable de forma inicializada como por ejemplo

char* nombreJugador="";

Igual recibirás un error de tiempo de ejecución del cin al intentar asignar valores a la variable.

Excepcion std::cin

Excepcion std::cin

Por qué ocurre esto?

La respuesta es un poco compleja, pero vamos a tratar de simplificarla para ilustrar la idea.

Si revisamos la lista de tipos fundamentales te mencione que char* era uno de ellos, pero en realidad el tipo fundamental es char, al utilizar el asterisco definimos que estamos manejando un arreglo de valores char, es decir, varios valores que se encuentran uno al lado del otro en memoria y a los cuales podemos acceder a través de una misma variable; pues bien, la función cin no puede hacer asignaciones a los diferentes valores de un arreglo, sino a un valor especifico por lo que su ejecución no es exitosa.

Entonces, como podemos hacer para capturar información de una cadena de caracteres?

Pues para esto utilizamos una librería especial llamada string, dentro de la cual conseguimos un tipo de dato llamado std::string.

El Tipo std::string

Es mucho lo que podemos decir sobre la librería string y las funciones que nos ofrece para manipular cadenas de caracteres, pero por hoy vamos a limitarnos a utilizar de forma básica el tipo de dato que nos ofrece para manipular cadenas de caracteres; primero que nada, es muy importante que en el area de declaracion de librerias agreguemos lo siguiente

#include <string>

Esto hará la debida inclusión de los diversos elementos de la librería principalmente el tipo de datos que vamos a utilizar, nuestro código podria ser ahora algo como

std::string nombreJugador;
std::cin >> nombreJugador;
std::cout << nombreJugador;

Si probamos este código vemos que ahora si funciona y que su ejecución ocurre sin inconvenientes.

NOTA: Hay un algo que tenemos que aclarar y es que si bien mencione que std::string era un tipo de datos, en realidad es una clase que maneja datos de secuencias de caracteres, por lo que existen diferentes funciones que podemos utilizar desde la misma variable para cambiar el estado de la misma, pero esto lo veremos a detalle mas adelante.

Segmentar la Ejecución de un Programa

Supongamos que queremos agregar pausas en un programa de manera que la ejecución de dos lineas de código ocurran de manera segmentada, por ejemplo las siguientes lineas se ejecutarían sin interrupción

std::cout<<"Linea 1";
std::cout<<"Linea 2";

Si quisiéramos crear una pausa entre las mismas, de forma tal que sea necesario presionar alguna tecla antes de que la ejecución del programa continué podemos utilizar una función de la librería conio.h llamada _getch() que frena la ejecución hasta que enviemos algún dato a la Entrada Estándar.

Para poder utilizarla es importante agregar al principio del fichero la inclusión

#include <conio.h>

Esto nos permitira agregar el siguiente código a para pausar el programa

std::cout<<"Linea 1";
_getch();
std::cout<<"Linea 2";

La manera en la que esto funciona es que veremos el mensaje «Linea 1» y la consola quedara en pausa hasta que presionemos alguna tecla (enviemos un dato a la Entrada Estándar) y en ese momento se mostrara el mensaje «Linea 2».

La Gran Hada del Poder – Código Fuente

Pues si has seguido la explicación de los dos conceptos anteriores pudieses intentar resolver el ejercicio por ti mismo (es lo mejor que puedes hacer) pero como siempre vamos a ver el código que resuelve el ejercicio

#include <iostream>
#include <string>
#include <conio.h>

int main()
{
std::string nombreJugador;
std::cout << "Cual es tu nombre? " << std::endl;
std::cin >> nombreJugador;
std::cout << "Bienvenido, "<< nombreJugador <<"! Yo soy la" << std::endl;
std::cout << "Gran Hada del Poder!" << std::endl;
_getch();
std::cout << "Voy a otorgarte una nueva tecnica de la espada." << std::endl;
_getch();
std::cout << "Recibela ahora!"<< std::endl;
_getch();
return 0;
}

Hay algunas maneras en la que puedes hacer este programa mas interesante, pudieses intentar crear una función que tome como parámetro el nombre y muestre el bloque de texto o buscar el resto de los diálogos de las otras hadas y adaptarlos en diferentes funciones.


Ya que hemos hecho ejercicios de entrada y salida de datos y a la vez hemos visto como generar funciones, me gustaría recomendarte un ejercicio bastante bueno para desarrollar tus habilidades en estas áreas: crea una calculadora; escribe un programa con una función para cada una de las operaciones aritméticas básicas. Si bien se desvía un poco de los ejercicios que hemos creado, es un excelente ejercicio para ejercitar tus habilidades.

Como siempre espero haya sido de tu agrado y recuerda que cualquier comentario es bien recibido.

Hasta la próxima.

Publicado en Blogging | Etiquetado , | Deja un comentario

La importancia de los Nombres en la Ingenieria del Software

beezow

Creo que ya hemos hecho este ejercicio antes pero, solo para recalcar el punto, te pregunto: cual es la actividad mas frecuente que realizamos como programadores?

Como ya te lo había mencionado en otras oportunidades la respuesta a esta pregunta es LEER!!!!!

Con «L» mayúscula, y todos los signos de exclamación que podamos adjuntarle.

En todo momento leemos: cuando revisamos los directorios donde se encuentran nuestros archivos, cuando distinguimos cual de estos archivos necesitamos, cuando evaluamos el código existente, cuando escribimos código, cuando hacemos revisión de código propio o ajeno; el quid del asunto es que siempre estamos leyendo.

Pero si te pregunto, cual es la segunda actividad que mas realizamos? cual seria tu respuesta? Considera por un momento y piensa detenidamente, que actividad hacemos en común para todo directorio, archivo, clase, atributo, método o variable?

Pues la respuesta es obvia, les asignamos nombres*.

*: El primero que mencione las funciones anónimas pierde.

Es por esto que en favor de impulsar los principios del Código Limpio y la Programación Limpia uno de los ejercicios mas importantes es acostumbrarnos a nombrar de forma correcta todos los componentes de nuestro sistema, no solo a aquellos que afectan directamente al código, sino también sus contenedores, y con esto me refiero a estructuras de directorios, archivos e inclusive los descriptores de implementación si utilizamos sistemas de distribución como Maven o Gradle.

Pensando en esto, quisiera compartir contigo algunas de las consideraciones de nomenclatura que he aprendido y me han sido útiles para desarrollar código de forma limpia.

Los Nombres deben transmitir Intención

Obvio, no es así?

De hecho, creo que es la cuarta vez que toco este punto en mi blog; pero esto debería ilustrarte la importancia de este punto.

Cuando vemos el nombre de un elemento, deberíamos saber de forma automática su propósito. No deberíamos verificar documentación externa o wikis o cualquier elemento adicional para entender lo que hace nuestro código.

Como dice el Tio Bob «la verdad siempre radica en el código«.

Este es un problema que vemos muy recalcado en código de enseñanza en las universidades (por lo menos esa fue mi experiencia), donde vemos como la idea de descripción de una variable seria algo como

int d; // los dias activos del usuario

El problema radica en que la explicación de propósito a través de un comentario vive y muere en el comentario; en las siguientes oportunidades que consigamos a la variable d por si sola es irrelevante ya que no nos dice nada, ni mucho menos demuestra su intención, cuando muchos podremos inferir que su propósito esta relacionado a una palabra con la letra «d».

Si bien pareciera ahorrar tiempo y optimizar el programa, la realidad técnica es que no hay diferencias entre ese nombre y algo mas descriptivo como

int diasActivosUsuario;

Como vemos, el renombrar la variable nos permite eliminar el comentario (que en general son distracciones en el código fuente, pero ese tema lo tocaremos luego) ya que es redundante y a la vez en cada invocación de la variable nos permite saber a que nos estamos refiriendo.

NOTA: Es común, en ejercicio de mejorar la legibilidad, aplicar la técnica del Camel Case a los nombres de las variables que son compuestas de varias palabras para diferenciarlas entre si; esto consiste en iniciar en minúsculas y luego usar una letra mayúscula para el inicio de cada palabra. En mi experiencia esta es una buena practica que siempre recomiendo.

Ya vimos esto en un caso aislado, pero veamos como se eleva a nivel de un método

protected List findAllFiltered(CriteriaQuery criteria) throws NoResultException
{
List l=em.createQuery(criteria).getResultList();
if(l.size()==0)
{
throw new NoResultException(ConstantesEntidades.MENSAJE_LISTA_VACIA);
}
return l;
}

Cual es el propósito de  este método? Según el nombre del método (en ingles) debería «encontrar todo filtrado», pero encontrar qué? y cómo?

Si tratamos de descifrar estas dudas a través de los parámetros y las variables que funcionan dentro de  la misma, nos encontraremos con poca información, existe un objeto CriteriaQuery al que simplemente llamamos criteria y asumimos cumple con el objetivo de contener el filtro, pero esto solo lo podemos inferir porque es un parámetro; igualmente vemos a una variable llamada em que hace uso de una serie de métodos por los cuales podemos detectar que esta variable es de tipo EntityManager si y solo si conocemos el API de esta interfaz; vemos una variable l es el valor de retorno y que no nos dice nada sobre los tipos de datos que estamos manejando en este método.

Como vemos, a pesar de que se disimula tener una nomenclatura elaborada, al utilizar codificaciones en los nombres y dejar el método con una descripción tan abstracta de si mismo y utilizar una nomenclatura tan vaga, el autor (quien actualmente escribe este articulo) no nos dice nada sobre lo que ocurre en el método.

Mucho se puede justificar diciendo que estamos tratando de crear un método para una clase abstracta (el único indicio de esto es que es un método protected) y que debe ser lo mas genérico posible en su implementación o cualquier otra excusa; pero el punto final es que debido a malas practicas, el código que genere fue de carácter obtuso.

Veamos por el contrario un ejemplo de código que también tiene la finalidad de ser usado de forma genérica pero que expresa mucho mejor su intención.

public T findByIntKey(int key)
{
T entity=entityManager.find(entityClass, key);
if(entity==null || entity.getEstatusRegistro()==EstatusRegistro.ELIMINADO)
{
throw new NoResultException();
}
return entity;
}

En este caso, mucho de la descripción y nombre del método nos dice que es de carácter genérico (si conoces desarrollo en Java, la T es un indicador de tipos genéricos). Si vemos el nombre nos dice que va a hacer una búsqueda utilizando una clave de tipo int; esta idea es reforzada por el dato que se recibe como parámetro, pero si queremos adentrarnos al funcionamiento del mismo, vemos que el valor de retorno es una entidad (su nombre entity asi lo revela) a pesar de que su tipo de dato es genérico; igualmente, vemos que hace uso de un EntityManager y la clase de la entidad para realizar la búsqueda por el valor clave.

En este caso, vemos como el uso de una nomenclatura mas explicita revela mas del método con una lectura sencilla. Por lo que podemos decir que este método revela su intención de forma clara.

El Profesionalismo ante todo

Es muy importante mantener una actitud profesional en nuestros proyectos y al momento de nombrar los componentes de los mismo.

Para ilustrar esta idea, compara estos dos Enums

public enum Regiones
{
AMERICA_NORTE, AMERICA_SUR, EUROPA_ESTE, EUROPA_CENTRAL, EUROPA_OESTE, ASIA_MENOR, ASIA_CENTRAL
}

public enum Regiones2
{
GRINGOS, DROGOS, EUROPEOS, COMUNISTAS, COMUNISTAS_OTROS, CHINOS, GOKUS
}

Quizás el ejemplo es un poco extremo y ofensivo, pero la idea en general es que la codificación de nuestros proyectos, si bien es un arte y debemos disfrutar lo que hacemos, no es un chiste y mucho menos un lugar donde debemos demostrar ejemplos de ética tan vergonzosos como el que acabo de utilizar.

Los Nombres deben permitir Comunicación

Existe una diferencia clave entre el trabajo con Código Limpio y el trabajo con Código Sucio que va mas allá de la legibilidad y esta es la capacidad de establecer conversaciones ilustradas por el código.

Imagina que algún usuario te plantea la siguiente falla «estoy teniendo un problema con al autenticar mi usuario, me muestra por pantalla un error diciendo que no hay valor de password«, y al proceder a revisar el código del controlador de usuarios consigues un método identificado de la siguiente manera

public Usuario auntenticarUsuario(String email, String password) throws NoResultException, IllegalArgumentException, AuthenticationException

Si no eres la persona que mantiene ese código puedes inmediatamente establecer una conversación con la persona que lo mantiene o si es tu código puedes pedir un poco mas de información al usuario y seguir de forma mas clara que es lo que ocurre con el password en cuestión.

Ahora por el contrario imagina una misma situación en la cual en lugar de encontrar este método, consigas algo como

public Response usrAuth(String pwd)

Pues te puedo asegurar por experiencia propia que tu trabajo se acaba de complicar; a primera vista pareciese que el código esta bien identificado y que las variables están debidamente identificadas, pero es allí donde caemos en la trampa. Las abreviaciones (o Notación Húngara) son enemigas naturales de la comunicación; no es lo mismo «Auth» que «autenticar» al momento de establecer una conversación, de igual manera no es lo mismo «usr» o «pwd»que «usuario» o «password», podemos creer que esta conversión sera algo natural pero este no siempre es el caso.

Es importante no recaer en el uso de mnemónicos o siglas ya que oscurecen el significado de un código y obligan al programador a estar constantemente pensando en decodificar estos nombres (hay excepciones como por ejemplo al hablar de estándares como SQL o REST).

Un Nombre solo debe revelar Intención no Estructura

Siempre recuerdo en mis inicios profesionales como programador en Informix cuando me toco preguntar por una variable llamada «tbl_datausrs_col_password_str» en un procedimiento almacenado que me pidieron revisar.

Esto me llamo la atención no fue tanto por la complejidad de nomenclatura sino porque me dio a entender que mientras programara en ese equipo tendría que utilizar este tipo de convenciones, lo cual a ciencia cierta, es un procedimiento agotador y poco amigable.

Si bien existió una época en la que era necesario identificar en los nombre estructuras complejas por limitaciones en los editores e IDEs, la verdad es que en la actualidad estas decisiones tienden a involucrar a algún gerente formado en esas épocas que aún se resiste a reconocer los avances de las herramientas y que cree que esto es una buena practica.

No lo es.

Evitar Prefijos o Sufijos de Tipo

La idea de identificar los tipos de datos que estamos manejando en una variable tampoco es importante; cualquier editor moderno puede indicarnos el tipo que se maneja de ser necesario utilizando solo el mouse, y esto si estamos utilizando un lenguaje tipificado; si usamos lenguajes como PHP, Python o Ruby, esto ni siquiera tiene sentido.

Prefijos de Agrupación

Si tenemos datos que deban agruparse como por ejemplo

int usrCodigo;
char* usrNombre;

Entonces lo ideal es agregarlos a una estructura o clase que los agrupe y utilizarlos dentro de la misma.

Por ejemplo, asumiendo que trabajamos en lenguaje C++ pudiesemos utilizar un struct de la siguiente manera

struct usuario
{
int codigo;
char* nombre;
}
//el resto del programa
usuario.codigo=1;

Lo mismo ocurre si queremos especificar prefijos que agrupen variables en un ambito, por ejemplo si tenemos la siguiente clase

public class Usuario
{
private int m_codigo;
public Usuario(int Codigo)
{
m_codigo=codigo;
}
public getCodigo()
{
return m_codigo;
}
}

En este caso, utilizamos el prefijo m_ para definir los atributos (también conocidas como variables miembro) de la clase y diferenciarlos de parámetros con los que puede compartir el nombre; esta practica es innecesaria ya que con el mismo propósito pudiésemos utilizar el identificador this que es parte de la gran mayoría de los lenguajes modernos.

Quedaríamos con algo como esto

public class Usuario
{
private int codigo;
public Usuario(int Codigo)
{
this.codigo=codigo;
}
public getCodigo()
{
return codigo;
}
}

De esta manera no comprometemos la legibilidad del código en general por acomodar algunos escenarios puntuales.


Por ahora, dejaremos este punto hasta aquí ya que el post se esta extendiendo de forma significativa; pero te recalco que este la discusión sobre nomenclatura es muy importante y que solo hemos tocado la superficie de este tema.

Como siempre espero haya sido de tu agrado y recuerda que cualquier comentario es bien recibido.

Hasta la próxima.

Publicado en Blogging | Etiquetado , , , | Deja un comentario

Ejercicio de TDD: BeanValidation en una Entidad JPA

Como ya he mencionado antes, es mi objetivo publicar en el blog entre 2 o 3 veces por semana, a partir de esta semana, y como siempre en aras de brindar mas información, he decido incorporar a mi agenda de contenido al menos un vídeo en el que podamos hablar ya sea de contenido técnico o ver ejercicios o demostraciones.

Actualmente carezco de equipo de alto nivel por lo que el contenido tendrá un tono amateur y algo desaliñado, ya que lo mas probable es que me vea obligado a grabarlo a altas horas de la noche para evitar los ruidos de la calle (y aun así se notan fuertemente); de la misma manera, debido a restricciones de software por ahora veremos limitados los vídeos a un máximo de 10 minutos, espero mas adelante poder brindarte contenido un poco mas elaborado pero por ahora tendremos que lidiar con esto.

Dicho esto, les dejo a continuación el vídeo de esta semana


En este vídeo hacemos un breve ejercicio de TDD utilizando un atributo de una entidad JPA para demostrar como incorporamos elementos a nuestro código de producción mediante pruebas unitarias que garanticen su buen funcionamiento.


Como siempre espero haya sido de tu agrado y recuerda que cualquier comentario es bien recibido.

Hasta la próxima.

Publicado en Blogging | Etiquetado , , , , | Deja un comentario

Creando Buenas Pruebas Unitarias

En casi todas sus charlas, Misko Hevery dice que hay una sola razón valida por la que un programador no debería escribir pruebas automatizadas del software que este desarrollando, y esta es que no sepa como hacer pruebas de software.

Toma en cuenta que por mas experimentados que podamos ser en el desarrollo de software, realizar pruebas automatizadas es una habilidad particular y si nunca la hemos ejercido no podemos esperar saber utilizarla como por arte de magia.

Considera cuales habilidades has adquirido como programador:

  • Validar algoritmos
  • Conocer estructuras de datos
  • Escribir software en un lenguaje
  • Diseñar aplicaciones en un modelo de programación
  • Etcetera

Ahora pregúntate de forma sincera como hiciste para obtener el nivel de dominio que tienes actualmente:

  • Cuantas horas de estudio requirió cada una de ellas?
  • Cuantos libros compraste?
  • Cuantas clases tomaste?
  • Cuantos tutoriales buscaste en Internet?

Y ahora pregúntate, por qué creemos que hacer pruebas automatizadas es diferente?

Si alguien te entrega un sistema por primera vez y te dice «necesito que pruebes el funcionamiento del modulo de registro de usuarios de forma manual«, te sentirías cómodo en ese rol? Quizás no tanto.

Te tomaría tiempo familiarizarte con el sistema y determinar como lo vas a probar, hacer planes de que vas a probar y entender como vas a reportar lo que has descubierto; esto es, si aceptas hacer la actividad en primer lugar.

Parece mentira, pero no todos los programadores se sienten cómodos indagando el funcionamiento de software ya en producción de forma manual.

Creo que aquí se esconde el secreto de lo que ocurre, nos engañamos al confundir el proceso de escritura de software con el proceso de realizar pruebas automatizadas de software, ya que pensamos que hacer código de prueba es lo mismo que hacer código de producción, ya que comparten la idea de que es código lo que se esta haciendo; pero su propósito final determina la diferencia fundamental que muchas veces ignoramos.

Si te pido que hagas un código de producción para un sistema contable, lo primero que debes hacer es familiarizarte con ese proceso contable para entender que vas a programar, igualmente si vas a escribir código de pruebas, no solo debes familiarizarte con la tecnología de escritura de código (un framework como jUnit o TestNG en el caso de pruebas unitarias), sino también con el proceso de como realizar buenas pruebas.

Es por esto que he decidido que siguiendo las ideas de mi post anterior sobre TDD, exploremos juntos como implementar buenas pruebas.

Qué hace a una prueba automatizada buena?

Si bien, cada uno de los diferentes tipos de pruebas maneja sus propios estándares, pero comparten en general una definición base de cuales son los factores que hacen a una prueba automatizada buena

  • El nivel de lectura del código
  • La capacidad de mantenimiento del código
  • Cómo se encuentra organizado, tanto en el proyecto como dentro del archivo fuente
  • Qué esta chequeando
  • Cómo maneja las dependencias del Sistema Bajo Prueba (el termino técnico es SUT por sus siglas en ingles).

Dicho esto, nosotros nos enfocaremos en el post de hoy en evaluar que hace a una prueba unitaria «buena». Recordemos primero la definición que utilizamos en nuestro post sobre TDD.

Qué es una Prueba Unitaria?

La idea de realizar pruebas unitarias viene desde los años 70, impulsadas por Kent Beck (creador de la metodología XP y uno de los padres del Movimiento Agil) en el lenguaje Smalltalk y esta demostrado que es una de las maneras mas seguras de mejorar la calidad del código del desarrollo.

Wikipedia define como prueba unitaria «a una porción de código (comúnmente un método) que que invoca otra porción de código y chequea diversas presunciones sobre el mismo; si estas presunciones están erradas, entonces la prueba ha fallado«.

Pero esta definición a mi parecer es un poco escueta, veamos entonces que mas podemos considerar sobre las pruebas unitarias para poder calificarlas como buenas.

Propiedades de una Buena Prueba Unitaria

Roy Osherove (mi autor favorito en la materia) en su excelente libro The Art of Unit Testing nos dice que no solo es importante conocer técnicamente que es una prueba unitaria sino también conocer las propiedades una buena prueba unitaria.

  • Debe ser automatizada y repetible.
  • Debe ser fácil de implementarse.
  • Una vez que sea escrita debe mantenerse para uso a futuro.
  • Cualquiera debe ser capaz de ejecutarla (a no ser que estemos desechando la funcionalidad a la que corresponde la prueba).
  • Debe correrse de forma sencilla.
  • Debe correr rápidamente.

Y si me permito agregar una propiedad adicional seria que el propósito de toda prueba es pasar.

successkid

Qué es una Prueba Unitaria Buena?

Conociendo ya la definición técnica y las propiedades de una buena prueba, podemos tratar de definir las pruebas unitarias.

Las pruebas unitarias buenas son las que evaluan de forma automatizada un punto especifico del código, ya sea un método, una propiedad o una función definiendo lo que esperamos sea el resultado y/o comportamiento del mismo; estas pruebas se realizan de forma aislada al resto de los programas o clases que conforman el sistema.

De igual manera, al implementarse utilizando un Framework de pruebas las mismas deberían poder crearse de forma sencilla, siendo su ejecución confiable y veloz, mientras que al mismo tiempo su código debe ser legible y mantenible.

Como punto adicional, hay una convención sobre la estructura que debe tener una buena prueba unitaria, y es lo que se conoce como el modelo «AAA«, esto viene de los términos «Arrange, Act, Assert» o «Preparar, Actuar, Asegurar» (la palabra asertar también existe en español, es sinónimo de aseverar y asegurar algo).

Es decir, en toda prueba, primero preparamos los elementos a probar, ejecutamos alguna acción y luego nos aseguramos nuestras suposiciones sean correctas.

A qué se llama Olores de Pruebas?

Cuando se dice que tenemos un «olor» en una prueba, nos referimos a un indicio, algún indicador de que quizás la prueba no sea buena o de que hay algo en el código de producción que no funciona como debería.

Es importante hacer notar, que no porque una prueba te de «olores» de un tipo, es automáticamente mala, hay ciertos compromisos a los que debemos llegar con nuestro código que en algunos casos nos llevan a hacer excepciones y concesiones transitorias; lo importante es que un olor nos hace parar por un momento y revisar una prueba para comprobar su comportamiento y entender si su código puede ser optimizado o hay alguna falla en la misma.

De igual manera, hay que destacar que nuestras pruebas deberían estar tan libre de olores como sea posible, y la única manera de lograr esto es sabiendo como reconocer estos indicios.

En mi opinión, Lasse Koskela, en su libro Effective Unit Testing, plantea la mejor separación de olores al plantearlos en 3 grandes categorías

  • Olores de Legibilidad
  • Olores de Mantenibilidad
  • Olores de Confiabilidad

Es en el estudio de estos olores que haremos énfasis en nuestros próximos posts. Por ahora quiero enfocarme en mostrarte un ejemplo de como se ven malas pruebas unitarias y como se ven las buenas pruebas unitarias.

NOTA: Los ejemplos que veremos a continuación se encuentran desarrollados en Java utilizando el Framework JUnit.

Malas Pruebas Unitarias

Quizás en este punto te plantearas, como reconocemos una mala prueba unitaria?

Pues sencillamente, si captamos problemas de legibilidad, mantenibilidad o confiabilidad podemos empezar a sospechar que una prueba puede ser mala. Una vez que hemos pausado para revisar la prueba, podemos determinar si es solo un indicio de error o una falla en el código de prueba o en el código de producción.

NOTA: La excepción a esto es cuando una prueba falla de forma aleatoria o requiere condiciones especiales para pasar, esto es un indicador sine qua non de que hay un error en la implementación del código, ya sea de producción o de prueba.

Quiero mostrarte un terrible intento de prueba unitaria, el mismo es de mi autoría y fue sobre un proyecto en el que di mis primeros pasos de lleno en el TDD.

Veamos el código:

public class EntitiesFactoryJSONTest {

private EntitiesFactoryJSON factoryJSON;
private EntitiesFactory factory;

@Before
public void setUp() throws Exception
{
factory=new EntitiesFactory();
factoryJSON=new EntitiesFactoryJSON();
}

@Test
public void debeCrearPedidos()
{
Pedido pedido=factory.crearPedido();
PedidoJSON pedidojson=factoryJSON.parsePedido(pedido);
assertEquals(true, pedido.getHora()==pedidojson.getHora());
assertEquals(true, pedido.getFecha()==pedidojson.getFecha());

Usuario usuario=factory.crearUsuarioFinal();
usuario.setCedula("V17230971");
usuario.setNombre("jorge");
usuario.setDireccion("sanfra");
usuario.setTelefono("02617623790");

Catalogo catalogo=factory.crearCatalogo();
catalogo.setNombre("test");

ElementoCatalogo elemento1=factory.crearElementoCatalogo(catalogo);
ElementoCatalogo elemento2=factory.crearElementoCatalogo(catalogo);
ElementoCatalogo elemento3=factory.crearElementoCatalogo(catalogo);
elemento1.setPrecio(10.0f);
elemento2.setPrecio(20.0f);
elemento3.setPrecio(50.0f);

List<ElementoCatalogo> elementos=factory.listaElementosCatalogo();
elementos.add(elemento1);
elementos.add(elemento2);
elementos.add(elemento3);

pedido=factory.crearPedido(usuario, elementos);
pedidojson=factoryJSON.parsePedido(pedido);

assertEquals(usuario.getNombre(), pedidojson.getCliente().getNombre());
assertEquals(usuario.getDireccion(), pedidojson.getDireccionEntrega());
assertEquals(usuario.getTelefono(), pedidojson.getTelefonoEntrega());
assertEquals(true,pedidojson.getSubTotal()==80.0f);
}
}

Esto esta tan mal que casi me da risa al ver el código; para ilustrar la idea de que esta mal en esta prueba te pregunto: que estoy probando?

Parecería obvio por el nombre del método que estoy probando que EntitiesFactoryJSON debe ser capaz de crear pedidos, entonces

  • Por qué evaluó tantas cosas con las funciones assertEquals?
  • Por qué preparo tantos valores con esos elementos en particular?
  • Por que involucro a EntitiesFactory en el proceso?

Hay otras preguntas que se pueden hacer pero para mantener la brevedad te las responderé todas con una sola respuesta: esta prueba esta mal.

Cada una de estas preguntas indica un olor particular, incluyendo mas que no hemos expresado; cuando una prueba presenta varios olores en conjunto, casi siempre es señal de que la prueba esta mal.

Una Prueba Unitaria Buena

Veamos por el contrario el código de una prueba unitaria que pudiésemos considerar como buena, también de mi autoría.

@RunWith(MockitoJUnitRunner.class)
public class UsuariosServiceAuthenticateUsuarioTest extends AbstractUsuarioServiceTest
{
private String testLogin;
private String testPassword;

@Before
public void setUpInstanciacion()
{
instanciacion();
testLogin=TestEntitiesFactory.VALID_LOGIN;
testPassword=TestEntitiesFactory.VALID_PASSWORD;
}

@Test
public void AuthenticateUsuario_Success_ReturnsResponseOK() throws Exception
{
when(administradorUsuariosMock.auntenticarUsuario(TestEntitiesFactory.VALID_LOGIN,TestEntitiesFactory.VALID_PASSWORD)).thenReturn(TestEntitiesFactory.validUsuario());
Response responseCheck = usuarioService.authenticateUsuario(testLogin, testPassword);
assertOK(responseCheck);
}
}

Una vez mas te pregunto: que estoy probando?

Si vemos el nombre de la prueba es AuthenticateUsuario_Success_ReturnsResponseOK() (recordemos que la prueba es el método, no la clase), esto nos permite leer de forma clara el propósito de la prueba; cuando AuthenticateUsuario se ejecute con exito, deberíamos obtener un Response de tipo OK.

Esta es una muy buena practica de legibilidad que he adquirido de Roy Osherove y les recomiendo al momento de nombrar sus pruebas.

Quizás veas código que a primera vista parezca mas complicado que el que implementamos en lo que consideramos la prueba mala, especialmente el que esta relacionado con la herramienta Mockito, posiblemente a primera mano pensaras que el código es difícil de leer y te dispara un olor, también veras referencias a cosas no declaradas en la clase (una clase con pruebas unitarias se conoce como Test Fixture o traducido de forma muy rustica Accesorio de Pruebas), este es otro olor.

Pero con una inspección mas cercana, notaras que este fixture es una clase heredada, por lo que deben haber mas fixtures que compartan elementos con este, si tenemos muchos elementos comunes utilizar herencia es valido para simplificar el código de cada clase.

Igualmente podemos decir que el uso de Mockito, o cualquier otra herramienta de Dobles de Pruebas (o Mocks) optimiza el manejo de dependencias, permitiendo a la prueba ejecutarse de forma aislada, esto garantiza la ejecución veloz de nuestra prueba (si no estamos familiarizados con lo que hace esta herramienta, pues mas que un olor de la prueba es una habilidad pendiente por adquirirse).

De la misma manera, podemos ver que la prueba en si sigue la estructura AAA, otra señal de que la prueba es buena.

Es perfecta esta prueba? no lo creo, a pesar de que la considero una buena prueba unitaria, la verdad es que aún hay código que puede optimizarse para mejorar su calidad; y este es un punto muy importante a comprender:

  • Debemos tratar nuestro código de pruebas con la misma atención y cuidado que nuestro código de producción. 

Es decir, una prueba puede refactorizarse y cambiar su estructura para buscar la optimización con el tiempo, siempre y cuando sigamos garantizando que sea buena y que cumpla su función.

Esta es la señal de un buen ingeniero de software.


Con esto cerramos por ahora, en nuestros siguientes posts expandiremos la idea de los olores, el uso de Mocks, la cobertura de código y otros puntos importantes para cuando implementamos el desarrollo con pruebas unitarias.

Como siempre espero haya sido de tu agrado y recuerda que cualquier comentario es bien recibido.

Hasta la próxima.

Publicado en Blogging | Etiquetado , , , , | Deja un comentario

Iniciando en C++: GameStats – Parte 2

Continuemos con la segunda parte de nuestro ejercicio de GameStats. Antes de comenzar veamos como ha quedado nuestro código luego de la primera parte:

#include <iostream>

void mostrarAtributosArma()
{
std::cout << "================== ATRIBUTOS DEL ARMA ==================" << std::endl;
std::cout << "Nombre: RW1" << std::endl;
std::cout << "Variante : Guardian" << std::endl;
std::cout << "Clase : Profesional" << std::endl;
std::cout << "Descripción : Arma de riel de mano, capaz de detener el combate.La mejor en su clase para causar daño" << std::endl;
std::cout << "Daño : " << 16 << std::endl;
std::cout << "Precisión : " << 7 + 1 << std::endl;
std::cout << "Cadencia de Fuego : " << 2 << std::endl;
std::cout << "Rango : " << 6 << std::endl;
std::cout << "Manejo : " << 7 - 1 << std::endl;
std::cout << "Movilidad : " << 12 << std::endl;
std::cout << "--------------------------------------------------------" << std::endl;
}

int main()
{
mostrarAtributosArma();
return 0;
}

Listo? Continuemos entonces.


En esta parte del ejercicio evaluaremos como mostrar los datos de un clan multijugador de Call Of Duty: Advanced Warfare, así que lo primero que deberíamos hacer es analizar los datos que vamos a presentar.

Perfil de Clan

Perfil del Clan

Perfil del Clan

  • Nombre: ATLAS
  • Diminutivo (tag): ATL
  • Lema: El poder lo cambia todo
  • Estadísticas del clan:
    • Nivel: 11
    • Experiencia Acumulada: 90000
    • Experiencia para Siguiente Nivel: 20000
    • Miembros: 13
    • Relación Muertes/Muertos: 0.91
    • Relación Victorias/Derrotas: 0.37

Si bien no son todos los datos que aparecen en pantalla, creo que son suficientes para ilustrar la idea que vamos a plantear con la función mostrarFichaClan().

Función mostrarFichaClan()

En esta función mostraremos los datos del clan que ya hemos definido anteriormente. NOTA: Para no tener que hacer una impresión completa del código cada vez que modifiquemos la estructura del mismo, me limitare a mostrar los cambios según las funciones que queramos modificar. Primero que nada procedamos a modificar la función main() de la siguiente manera:

int main()
{
mostrarAtributosArma();
mostrarFichaClan();
return 0;
}

Luego, procedamos a definir la función propiamente dicha, recuerda que esta definicion debe colocarse antes que la de la función main(); veamos el código:

void mostrarFichaClan()
{
char* nombre = "ATLAS";
char* tag = "ATL";
char* lema = "El poder lo cambia todo";
int experienciaAcumulada = 90000;
int experienciaSiguienteNivel = 20000;
short int nivel = 11;
unsigned short int miembros = 13;
float relacionMuertesMuertos = 0.91f;
float relacionVictoriasDerrotas = 0.37f;

std::cout << "================== PERFIL DEL CLAN =====================" << std::endl;
std::cout << "Nombre : " << nombre << std::endl;
std::cout << "Tag : [" << tag << "]" << std::endl;
std::cout << "Lema : " << lema;
std::cout << "Estadísticas : " << std::endl;
std::cout << " - Nivel : " << nivel << std::endl;
std::cout << " - Experiencia Acumulada : " << experienciaAcumulada << std::endl;
std::cout << " - Experiencia para Siguiente Nivel : " << experienciaSiguienteNivel << std::endl;
std::cout << " - Miembros : " << miembros << std::endl;
std::cout << " - Relacion Muertes/Muertos : " << relacionMuertesMuertos << std::endl;
std::cout << " - Relacion Victorias/Derrotas : " << relacionVictoriasDerrotas << std::endl;
std::cout << "--------------------------------------------------------" << std::endl;
}

Intimidante, no es así? Veamos el programa en ejecución y confirmemos su funcionamiento

mostrarPerfilClan()

mostrarPerfilClan()

El shock en el código viene de que hemos decidido implementar variables para manejar los valores que se mostraran en los diferentes cout que utilizamos, esto ha sido un cambio radical en el modo en el que venimos desarrollando nuestros programas. Estudiemos un poco como funcionan las variables en C++ para luego apreciar que hemos hecho en esta función.

Variables en C++

Entendamos que una variable no es mas que la representación de un valor a través de un nombre; dicho esto entendamos que en los lenguajes de programación tipificados (es decir que manejan tipos) comúnmente una variable consta de tres partes

  1. Tipo de dato
  2. Etiqueta o nombre
  3. Valor de la variable.

De esta manera cuando en C++ declaramos una variable como: int X = 0; El tipo seria int, el nombre es X y su valor es 0. Es muy importante que entendamos los tipos que estamos utilizando en nuestro programa, por lo que vamos a ver los diferentes tipos de datos que podemos usar de forma nativa en C++.

Tipos Fundamentales en C++

Al mínimo de los niveles, todas las variables que definimos en C++ son valores numéricos; conforme vamos A nivel básico podemos decir que C++ maneja dos tipos de datos fundamentales:

  • Caracteres Alfanuméricos y Especiales .
  • Escalares o Numéricos.

El resto de los tipos son derivados  de estos dos valores. NOTA: Existe una tercera categoría de punteros y referencias a memoria, pero estos los estudiaremos a nivel mas avanzado.

Tipos Caracter

Los valores de tipo caracter se definen con la palabra clave char; y si comprendemos su propósito, son muy sencillos de entender:

  • Un caracter es cualquier valor que no se puede utilizar en una operación aritmética.

De esta manera si te digo que la letra ‘a’ es un caracter, pero también el numero ‘1’ lo es, una coma, un espacio en blanco, el signo de ‘+’, todos estos son caracteres. Simplemente son cualquier símbolo cuyo propósito no sea una operación matemática.

Estoy seguro que esta no es la definición que normalmente vemos en un libro, pero a nivel practico es la manera mas clara en la que podemos verlo.

Permiteme ilustrarte esta idea con un sencillo ejemplo, escribe rápidamente un programa en el que hagas solo la siguiente operación en el main():

char a = '1'; std::cout << a + 1;

El valor que obtendrás por pantalla no es 2, de hecho en mi sistema me muestra 50 (si manejamos el mismo sistema operativo y codificación de sistema deberíamos obtener el mismo valor). Te preguntaras que es lo que ocurre? pues que sencillamente el caracter ‘1’ es un valor de muestra, que en el trasfondo tiene un valor numérico que le permite a C++ trabajar con él. El ‘1’ que manejamos en el valor no es un valor numérico según lo entiende el lenguaje, es un caracter numérico.

NOTA: Existen funciones especiales que permiten realizar conversiones de caracteres numéricos en valores numéricos. No estoy seguro si las estudiaremos pero te garantizo que están disponibles en el estándar C++.

Hay dos maneras de declarar variables de caracteres:

char a = 'b';

char* cadena = 'una cadena de caracteres';

A nivel practico, vemos que char a nos permite almacenar solo un caracter en su variable, mientras que char* cadena nos permite almacenar tantos caracteres como el compilador y la memoria permitan (comúnmente se habla de 256 caracteres).

A nivel programático, podemos decir que char a es una variable simple, mientras que char* cadena es un arreglo de valores; esta diferencia es considerable cuando estudiemos distribución de memoria mas adelante.

Tipos Escalares

Los valores numéricos son un poco mas complejos pero tampoco son nada del otro mundo. Hay dos clasificaciones claras en los valores que se manejan:

  • Valores enteros, es decir que no manejan decimales
    • int, bool
  • Valores de punto flotante, es decir que manejan decimales
    • float, double
Booleanos

Primero que nada tengo que aclarar algo, si bien bool es la palabra clave para determinar valores booleanos (es decir valores que definen VERDADERO o FALSO), su verdadero valor es un entero. De esta forma podemos decir que el valor true es igual a 1 y false es igual a 0; bool variable = 1; bool otravariable = true; Ambos casos son validos y ambas variables tienen el mismo valor.

Integers

Las variables int nos permiten trabajar los valores numéricos simples, es decir sin valores decimales. Estas variable son capaces de almacenar 4,294,967,296 valores. Existen también dos formas en las que podemos aplicar a los valores enteros, los mismos son:

  • short, delimita el rango de valores a 65,536 valores
  • long, que por defecto mantiene los 4,294,967,296 valores aunque teóricamente puede reservarse mas espacio para sus valores.

Es posible omitir la palabra int al declarar las variables si usamos los modificadores de tamaño; de esta manera podemos decir que: short int variableCorta; long int variableLarga; Es lo mismo que short variableCorta; long variableLarga; Igualmente hay dos modificadores adicionales

  • signed, la variable manejara valores positivos y negativos, esta es la forma por defecto en la que funciona int.
  • unsigned, para manejar valores sin signo de menos, esto le permite al compilador obviar los valores negativos e incrementar el valor de positivos en rango.
Float y Double

Estos son los tipos de variables que manejan decimales, la diferencia primordial que existe entre ellos es la cantidad de decimales que son capaces de manejar.

  • float maneja 3.4E +- 38 (es decir 7 dígitos significativos en el punto decimal)
  • double maneja 1.7E +- 308 (es decir 15 dígitos)

Un punto importante a tomar en consideración es que para C++; todas las expresiones que involucren un entero, se resuelven en forma de enteros, es decir si declaramos la siguiente variable:

float a = 1/2;

El valor de a sera 0, ya que C++ desechara el valor decimal que corresponde a esa operación (esto es valido para todas las operaciones aritméticas). Este inconveniente lo resolvemos facilmente si implementamos los valores escalares con numéros decimales

float a = 1.0/2.0;

Aunque de esta manera el compilador entiende que 1.0 y 2.0 son valores de tipo double, por lo que asigna mas recursos de memoria que los quizás sean necesarios.

Es por esto que en mi opinión personal es mejor especificar estos valores directamente como float utilizando una «f» luego del valor como vemos en el siguiente ejemplo:

float a = 1.0f/2.0f;

Valores Fundamentales

Me gustaría dejarte esta tabla de valores para los tipos fundamentales como referencia futura.

Tabla de Valores de Tipos Fundamentales

Tabla de Valores de Tipos Fundamentales

Función mostrarFichaClan() – Parte 2

Ya que hemos aprendido los diferentes tipos de variables y la forma en la que las mismas se declara, volvamos a ver el código de mostrarFichaClan()

void mostrarFichaClan()
{
char* nombre = "ATLAS";
char* tag = "ATL";
char* lema = "El poder lo cambia todo";
int experienciaAcumulada = 90000;
int experienciaSiguienteNivel = 20000;
short int nivel = 11;
unsigned short int miembros = 13;
float relacionMuertesMuertos = 0.91f;
float relacionVictoriasDerrotas = 0.37f;

std::cout << "================== PERFIL DEL CLAN =====================" << std::endl;
std::cout << "Nombre : " << nombre << std::endl;
std::cout << "Tag : [" << tag << "]" << std::endl;
std::cout << "Lema : " << lema;
std::cout << "Estadísticas : " << std::endl;
std::cout << " - Nivel : " << nivel << std::endl;
std::cout << " - Experiencia Acumulada : " << experienciaAcumulada << std::endl;
std::cout << " - Experiencia para Siguiente Nivel : " << experienciaSiguienteNivel << std::endl;
std::cout << " - Miembros : " << miembros << std::endl;
std::cout << " - Relacion Muertes/Muertos : " << relacionMuertesMuertos << std::endl;
std::cout << " - Relacion Victorias/Derrotas : " << relacionVictoriasDerrotas << std::endl;
std::cout << "--------------------------------------------------------" << std::endl;
}

Vemos entonces como en la primera parte declaramos nuestras variables, utilizando los diferentes tipos (char*, int, short int, unsigned short int, float) y luego sencillamente invocamos sus valores usando sus nombres donde queramos utilizarlas.

Ya que entendemos los diferentes tipos y su forma de declararse, no es tan intimidante o si?

GameStats

Para cerrar veamos la forma en la que todo el código se ve en conjunto:

#include <iostream>

void mostrarAtributosArma()
{
std::cout << "================== ATRIBUTOS DEL ARMA ==================" << std::endl;
std::cout << "Nombre: RW1" << std::endl;
std::cout << "Variante : Guardian" << std::endl;
std::cout << "Clase : Profesional" << std::endl;
std::cout << "Descripción : Arma de riel de mano, capaz de detener el combate.La mejor en su clase para causar daño" << std::endl;
std::cout << "Daño : " << 16 << std::endl;
std::cout << "Precisión : " << 7 + 1 << std::endl;
std::cout << "Cadencia de Fuego : " << 2 << std::endl;
std::cout << "Rango : " << 6 << std::endl;
std::cout << "Manejo : " << 7 - 1 << std::endl;
std::cout << "Movilidad : " << 12 << std::endl;
std::cout << "--------------------------------------------------------" << std::endl;
}

void mostrarFichaClan()
{
char* nombre = "ATLAS";
char* tag = "ATL";
char* lema = "El poder lo cambia todo";
int experienciaAcumulada = 90000;
int experienciaSiguienteNivel = 20000;
short int nivel = 11;
unsigned short int miembros = 13;
float relacionMuertesMuertos = 0.91f;
float relacionVictoriasDerrotas = 0.37f;

std::cout << "================== PERFIL DEL CLAN =====================" << std::endl;
std::cout << "Nombre : " << nombre << std::endl;
std::cout << "Tag : [" << tag << "]" << std::endl;
std::cout << "Lema : " << lema;
std::cout << "Estadísticas : " << std::endl;
std::cout << " - Nivel : " << nivel << std::endl;
std::cout << " - Experiencia Acumulada : " << experienciaAcumulada << std::endl;
std::cout << " - Experiencia para Siguiente Nivel : " << experienciaSiguienteNivel << std::endl;
std::cout << " - Miembros : " << miembros << std::endl;
std::cout << " - Relacion Muertes/Muertos : " << relacionMuertesMuertos << std::endl;
std::cout << " - Relacion Victorias/Derrotas : " << relacionVictoriasDerrotas << std::endl;
std::cout << "--------------------------------------------------------" << std::endl;
}

int main()
{
mostrarAtributosArma();
mostrarFichaClan();
return 0;
}


Con esto hemos concluido el código por ahora, quería implementar un par de conceptos adicionales (como las funciones que devuelven valor y funciones parametrizadas) en el ejercicio, pero he decidido que seria mezclar demasiadas cosas en un solo post por lo que por ahora lo dejaremos hasta acá. Pero no te preocupes que apenas vamos empezando el tutorial y aun nos quedan muchos ejercicios por hacer.

Como siempre espero haya sido de tu agrado y recuerda que cualquier comentario es bien recibido.

Hasta la próxima.

Publicado en C++ | Etiquetado , | Deja un comentario

Iniciando en C++: GameStats – Parte 1

En este ejercicio desarrollaremos un programa que muestre aspectos numéricos comúnmente relacionados con un juego.

Para esto dividiremos el ejercicio en dos partes, ambas relacionadas con el juego Call Of Duty: Advanced Warfare.

  • Primero veremos como mostrar los atributos de un arma llamada «RW1 – Guardian«.
  • Luego veremos como podemos mostrar los datos del perfil de un clan multijugador.

Esta información se mostrara por consola de forma sencilla.

Ya que tenemos delineado el ejercicio, allons y.

Preparación de Proyecto

Primero que nada crea un proyecto al que llamaras GameStats, dentro del mismo nuestro archivo principal lo llamaremos gamestats_main.cpp; si notas, hemos cambiado la nomenclatura (forma de llamar las cosas) que veníamos utilizando, esto es para identificar de mejor manera a que proyecto pertenece nuestro archivo «.cpp» e identificar que allí tenemos nuestra función main() de una forma un poco mas clara.

Dentro de este archivo prepararemos nuestra función principal utilizando el siguiente código
#include <iostream>
int main()
{
return 0;
}

La RW1 – Guardian

Veamos cuales son los atributos de esta arma

RW1 - Guardian

RW1 – Guardian

Descompongamos los datos de la misma

  • Nombre: RW1
  • Variante: Guardian
  • Clase: Profesional
  • Descripción: Arma de riel de mano, capaz de detener el combate. La mejor en su clase para causar daño
  • Atributos Numéricos: Todos los datos son números enteros, es decir, no manejan valores decimales.
    • Daño: 16
    • Precisión: 8 (podemos ver de que este valor es un variante por su coloración especial y porque al final de la linea se nota el simbolo de  «+1»)
    • Cadencia de Fuego: 2
    • Rango: 6
    • Manejo: 6 (otro valor variante, esta vez con el símbolo de «-1»)
    • Movilidad: 12

La idea es que toda esta información se despliegue  en pantalla, como crees que lograremos esto? Obviamente haremos uso de la función cout que hemos estudiado antes

Veamos como implementamos esto en código:
#include <iostream>
int main()
{
std::cout << "Nombre: RW1" << std::endl;
std::cout << "Variante : Guardian" << std::endl;
std::cout << "Clase : Profesional" << std::endl;
std::cout << "Descripción : Arma de riel de mano, capaz de detener el combate.La mejor en su clase para causar daño" << std::endl;
std::cout << "Daño : " << 16 << std::endl;
std::cout << "Precisión : " << 7 + 1 << std::endl;
std::cout << "Cadencia de Fuego : " << 2 << std::endl;
std::cout << "Rango : " << 6 << std::endl;
std::cout << "Manejo : " << 7 - 1 << std::endl;
std::cout << "Movilidad : " << 12 << std::endl;
return 0;
}

La ejecución de este programa nos arrojara el siguiente resultado

Atributos RW1

Atributos RW1

Obviemos lo inconforme que es el CMD de Windows con los caracteres especiales como la «ñ» y los acentos y concentrémonos en lo nuevo que vimos aquí.

Si precisas en toda la linea en la que hacemos uso de valores numéricos, separamos la inyección de los caracteres de la inyección de los números, como por ejemplo:
std::cout << "Daño : " << 16 << std::endl;

Esto nos muestra algo simple pero muy interesante, y eso es que cout acepta como parámetros valores numéricos sin necesidad de utilizar métodos de inserción especiales; veamos como seria la ejecución de esta misma linea utilizando printf y notemos la diferencia:
printf("Daño : %d \n",16);

Vemos que hay que utilizar el comodín %d el cual sera reemplazado por el valor numérico que colocamos luego del texto (el símbolo \n es el equivalente del std::endl), una vez mas tengo que recalcar que si bien printf es la opción adecuada en algunos casos y es bueno conocer su sintaxis, nosotros utilizaremos cout como función para enviar información a la pantalla.

También es interesante que estudiemos las siguientes lineas:
std::cout << "Precisión : " << 7 + 1 << std::endl;
std::cout << "Manejo : " << 7 - 1 << std::endl;

Si bien vemos podemos realizar operaciones aritméticas sobre los parámetros que estamos pasando al cout, en este caso particular las operaciones responden al análisis que hemos hecho de los valores que hemos visto en la pantalla de información.

Hablemos un poco mas sobre las operaciones aritméticas que podemos utilizar.

Aritmética en C++

En el lenguaje C++ disponemos de las cuatro operaciones aritméticas básicas (suma, resta, multiplicación y división) para trabajar con valores escalares (numéricos), adicionalmente contamos con una operación llamada modulo, la misma es un estándar en la programación aunque no esta definida en la matemática estándar como una operación independiente. Veamos como podemos utilizar estas operaciones:

  • Suma. Esta operación esta representada por el símbolo «+«; como ya hemos visto si uso puede ser algo tan simple como 7+1 cuyo resultado es 8.
  • Resta. Esta representada por el símbolo ««, ya hemos visto el ejemplo 7-1 que retorna 6.
  • Multiplicación. Se representa con el símbolo «*«, un ejemplo sencillo puede ser 2*2 que retorna 4.
  • División. Se representa con el símbolo «/«, un ejemplo sencillo es 10/5.
    • Como en las matemáticas comunes, debemos tener en consideración que la división entre 0 genera un error; de hecho, si tratamos de incluir una operación como 1/0, esto genera un error de compilación.
  • Modulo. Esta operación, representada por el simbolo «%«, nos retorna el residuo de una división, es decir el modulo de 3%2 es 1, 20%3 es 2, 103%13 es 12, etc.
    • El uso mas común de esta operación (pero no el único) es para determinar si un número es par, ya que por regla matemática si el modulo de cualquier numero entre 2 es igual a 0, ese número es par.

Orden de Operaciones

Cada operación aritmética forma parte de lo que se conoce como una expresión, es decir cada operación devuelve un valor especifico que luego puede utilizarse en otra expresión para mostrar un valor mas complejo.

Al igual que en el álgebra tradicional, las expresiones en C++ son evaluadas de izquierda a derecha, pero algunos valores tienen un orden de precedencia superior, es decir, algunas operaciones se ejecutan primero que otras, esto puede alterar el resultado que obtenemos al expresar una formula matemática en C++.

La precedencia de la multiplicación, la división y el modulo es mayor que la de la suma y la resta; de esta manera, la operación 7+3*5 es igual a decir 7+15 lo cual se resuelve en 22.

Si queremos alterar el orden de precedencia para darle prioridad a la suma, podemos utilizar el símbolo de paréntesis para  encerrar una expresión aritmética; por ejemplo, si evaluamos (7+3)*5 es igual a decir 10*5 lo cual se resuelve en 50.

Procedimiento mostrarAtributosArma()

Para cerrar esta primera parte del ejercicio, hagamos un cambio en como funciona nuestro programa.

Veamos el código:
#include <iostream>
void mostrarAtributosArma()
{
std::cout << "================== ATRIBUTOS DEL ARMA ==================" << std::endl;
std::cout << "Nombre: RW1" << std::endl;
std::cout << "Variante : Guardian" << std::endl;
std::cout << "Clase : Profesional" << std::endl;
std::cout << "Descripción : Arma de riel de mano, capaz de detener el combate.La mejor en su clase para causar daño" << std::endl;
std::cout << "Daño : " << 16 << std::endl;
std::cout << "Precisión : " << 7 + 1 << std::endl;
std::cout << "Cadencia de Fuego : " << 2 << std::endl;
std::cout << "Rango : " << 6 << std::endl;
std::cout << "Manejo : " << 7 - 1 << std::endl;
std::cout << "Movilidad : " << 12 << std::endl;
std::cout << "--------------------------------------------------------" << std::endl;
}
int main()
{
mostrarAtributosArma();
return 0;
}

Saquemos primero lo mas sencillo, hemos agregado dos cout puramente estéticos, uno para mostrar un encabezado con el titulo «ATRIBUTOS DEL ARMA» y un cierre con una serie de «» para dar la sensación de bloque de información.

Estos cambios no alteran para nada el funcionamiento de nuestro programa o la manera en la que se ejecuta; pero aparte de estos, hemos hecho un cambio significativo, puedes notar cual es?

Correctamente te debes haber dado cuenta que hemos creado una función sin retorno llamada mostrarAtributosArma(), y es en esta función donde realizamos el proceso de mostrar la información del RW1.

Comúnmente, en lenguajes como C++, cuando denotamos que una serie de acciones están relacionadas en su propósito (en este caso los cout con los atributos del arma), creamos una función que identifique el propósito general de la acción; a este proceso de programación se le conoce como Extracción de Función, o por lo menos ese es el termino técnico.

Un aspecto importante del proceso de extracción es determinar el tipo de valor a retornar, en nuestro caso no necesitamos especificar un retorno, ya que la actividad de mostrar los mensajes que estamos realizando con los cout, lleva la información hacia el flujo de salida estándar, no hacia el método main().

Otro aspecto interesante de tener un tipo de retorno vacío es que al momento de invocar la función solo tenemos que especificar su nombre y el listado de parámetros que requiere (que en este caso también es vacío).

Así como instintivamente sabemos que main() es la función principal del ejecutable, el truco para entender el propósito de una función es que el nombre que le asignemos este directamente relacionado a la acción que se ejecuta de forma general, por ejemplo: mostrarAtributosArma, leerArchivoConfiguracion, asignarPermisosUsuario.

C++ es uno de los lenguajes donde los programadores son mas propensos a obviar esta regla, no te permitas caer en esta trampa.

NOTA: el orden en el que las funciones se declaran y se invocan es importante, no podemos declarar primero main() y dentro de ella invocar a mostrarAtributosArma() ya que generaría un error de compilación (si no me crees puedes intentarlo, es un buen ejercicio). De todas maneras este punto lo elaboraremos a detalle mas adelante.

mostrarAtributosArma()

mostrarAtributosArma()


Con esto cerramos la primera parte de este ejercicio para que puedas evaluar lo que has aprendido e interiorizar lo que hemos visto hasta ahora.

Espero lo hayas disfrutado, en la segunda parte veremos como declarar nuestras variables, hablaremos sobre los tipos de datos fundamentales y crearemos una función que si retorna valores.

Hasta la próxima.

Publicado en C++ | Etiquetado , | Deja un comentario

Iniciando en C++: GameOver

Ha llegado el momento de iniciar a estudiar la sintaxis de C++, pero antes quiero recordarte que los ejercicios que utilizaremos están directamente adaptados del excelente libro Beginning C++ Through Game Programming, el cual recomiendo que adquieras si esta en tus posibilidades, este libro presenta todos los ejercicios en el contexto de programación de juegos, por lo que si bien estudiaremos todo el material requerido para conocer C++, los ejercicios son algo originales.

Así que sin mas preámbulos y como dirían los franceses: allons y!


Nuestro proyecto gira en torno de la frase mas odiada en el mundo de los juegos, si alguna vez has tenido afecto por los videojuegos seguramente hasta detestado verla y hoy estudiaremos cuales son los pasos necesarios para hacer a otros sentir de esa manera.

Me refiero al terrible mensaje «Game Over«.

Primero que nada crea un proyecto en Visual Studio, al mismo llamaremos «GameOver«, en el mismo incluyamos un archivo de código fuente al que llamaremos «Main.cpp«. Quiero que notes como a cada uno de los elementos que involucramos en el proyecto, le asignaremos un nombre descriptivo de su propósito.

La función main()

Ahora, hay algunas cosas que tenemos que tomar en cuenta al escribir un programa en C++.

  • C++ en su corazón es un lenguaje orientado a procedimientos, y exige que exista un procedimiento (o función) llamado main() en algún archivo para poder crear un ejecutable.
    • Es importante que en todo proyecto ejecutable exista un solo main() de lo contrario existirían conflictos en el proceso de vinculación.
  • C++ diferencia mayúsculas y minúsculas, así que aunque el archivo se llame «Main.cpp» es importante que el nombre del procedimiento sea «main«, no «Main» o «mAin» o «MAIN«.

Aclarado esto procedamos a crear este procedimiento:

void main()
{
}

No estuvo difícil, o si?

Te garantizo que así como esta, tu programa se compila y se ejecuta, aunque también te garantizo que no hace nada ya que no le hemos dado ninguna instrucción.

La estructura de todo procedimiento o función es la misma en lenguaje C++:

  • Primero el tipo de dato que debe devolver la función cuando es invocada. En el ejemplo usamos el tipo void.
  • Luego indicamos el nombre de la función.
  • Seguido la lista de parámetros de la función va entre paréntesis. En este caso hemos creado una función sin parámetros por lo que se coloca solo los paréntesis.
  • Las instrucciones de la función o el bloque de cuerpo se encierra entre los símbolos de llaves, «{» y «}«.
  • Todas las instrucciones que no sean bloques (estos los veremos mas adelante), deben terminarse con un punto y coma «;«.

El tipo de datos void es un tipo especial, que significa que «vació» es decir, esta función no retorna valor alguno; esta practica si bien es académica no es común en la practica; el estándar es decir que la función main responda con (el termino técnico es «retorne«) un valor numérico. Veamos como podemos modificar el código para esto.

int main()
{
return 0;
}

Como vemos, cambiamos void por el tipo int, este tipo representa números enteros, por lo que el programa ahora espera que la función le retorne un valor de este tipo. Igualmente, hemos agregado la clausula de retorno de valor return y hemos especificado que la función retorna el valor cero.

Pero esto solo es el principio, aun nos falta realizar la verdadera función de nuestro programa.

Mostrando un mensaje por pantalla

Si bien C++ nos permite crear nuestra propia función de bajo nivel que imprima información a la pantalla, dicha función ya existe en las librerías estándar de C++, es mas, existen varias funciones en el estándar que hacen esta tarea.

Para nuestro programa, utilizaremos una función que escriba directamente en el «flujo estándar de salida«.

NOTA: Existen diversos «flujos» hacia los que podemos enviar información, comúnmente el estándar envía su información a la consola o pantalla, mientras que el resto (como por ejemplo el flujo de errores) envía la información a archivos o registros para su almacenamiento.

Primero que nada vamos a incluirla librería que contiene la función que vamos a utilizar.

#include <iostream>
int main()
{
return 0;
}

El comando #include se utiliza para «incluir» la información de un archivo descriptor de funciones (o archivo de cabeceras) en otro, comúnmente una librería consta de uno o varios archivos de cabecera que permiten utilizar las funciones que ellas proveen. En este caso particular, estamos utilizando la librería estándar iostream y su nombre se identifica entre los simbolos «<» y «>«. Dentro de dicha librería, encontraremos una serie de funciones que nos permiten interactuar con los flujos de entrada y salida (su nombre en ingles es Input/Ouput Stream o Flujos de Entrada/Salida).

Veamos el código de la funcion tal como lo vamos a implementar.

#include <iostream>
int main()
{
std::cout << "Game Over";
return 0;
}

El espacio de nombres std

Veamos una vez mas lo que hemos agregado:

std::cout << "Game Over";

Vaya linea!

La gran mayoría de la gente empieza a aterrarse al ver cosas como esta.

Muchos dicen que la programación son solo símbolos raros, comas, puntos… QUE ENREDO! (mi esposa me lo dice a todo momento), pero tengo confianza en ti y se que este código, mas que dejarte en shock, te ha despertado la curiosidad.

La verdad es que si bien es cierto que en la programación (y particularmente en lenguajes como C++) vemos una gran cantidad de símbolos, al saber su significado podemos hacer una lectura bastante clara de lo que esta ocurriendo; al punto de que sin mucho esfuerzo podemos traducir esa linea a lenguaje humano:

  • Usar la función «cout» del espacio de nombres «std» para mostrar el mensaje «Game Over».

Pero, qué es eso de «espacio de nombres» que acabo de mencionar?

Simple, un espacio  de nombres (o namespace) no es mas que la asociación de funciones u elementos de programación dentro de una librería, esto permite separarles según su propósito. En este caso usamos el espacio de nombre std o estándar.

Cuando queremos utilizar elementos que se encuentran dentro de un espacio de nombres, utilizamos los dobles dos puntos «::» de la siguiente manera «namespace::elemento«.

Una manera gráfica en la cual podremos ver como funciona la idea de los espacios de nombre es la siguiente.

Uso del namespace std

Uso del namespace std

Así como tenemos la función cout dentro de std, existen también otros elementos que podemos utilizar, pero estos los veremos mas adelante.

El operador «<<«

Regularmente cuando usamos funciones en C++, los valores que la misma utilizara se expresan en forma de parámetros, que se pasan entre los símbolos de paréntesis; un ejemplo de este tipo de funciones es printf, otra función de iostream que también muestra mensajes por pantalla y que es heredada de C.

Veamos como quedaría nuestro código si utilizáramos esta función.

#include <iostream>
int main()
{
printf("Game Over");
return 0;
}

Simple, cierto?

Si bien, printf es la función apropiada en algunas oportunidades, la convención moderna es utilizar cout al momento de enviar datos al flujo de pantalla; la diferencia radica en que printf imprime la información mientras que cout la «inyecta» al flujo (y esto es algo de muy bajo nivel). Es por esto que cuando usamos cout no pasamos el valor de lo que queremos en pantalla, sino que mas bien lo inyectamos o enviamos usando el operador «<<«.

A nivel practico, basta con que sepamos que esto nos permite enviar varios mensajes o elementos especiales al flujo de salida de manera mas sencilla que si utilizáramos printf.

El ejemplo básico es el salto de linea, que si bien en printf es posible ingresarlo, hay que usar un carácter especial (que no siempre se traduce correctamente entre diferentes plataformas), mientras que si empleamos cout podemos usar un elemento especial del namespace std para inyectar un salto de linea.

Veamos como seria nuestro código al implementar esta caracteristica:

#include <iostream>
int main()
{
std::cout << "Game Over" << std::endl;
return 0;
}

Y con esto obtendríamos nuestro resultado final

Game Over

Game Over

Excelente, no lo crees?


Con esto terminamos nuestra primera entrada directa a la sintaxis de C++, hemos visto el funcionamiento de una de las funciones primordiales del lenguaje así como la estructura de un programa y los elementos que lo componen; en la siguiente entrada estaremos hablando sobre las funciones aritméticas y el uso de tipos numéricos.

Espero este post haya sido de tu agrado.

Hasta la próxima.

Publicado en C++ | Etiquetado , | Deja un comentario

Desarrollo Profesional: La Mentoría

Yo provengo de una familia de educadores, este es un aspecto muy importante sobre mi, ya que desde joven me he encontrado rodeado de gente que se ha dedicado en un 100% a la tarea de formar otras personas en diferentes etapas de su vida; por mucho tiempo, hice mi mayor esfuerzo por no involucrarme en el mundo de la enseñanza, de ser un tecnócrata consumado, preocupado exclusivamente en el desarrollo de software y la consultoría profesional.

Hay un decir popular en mi país que dice «lo que es del cura, va para la iglesia«, y ciertamente por mas que en mis periodos universitarios trate de escaparme del proceso de la enseñanza al llegar al mundo profesional me vi en medio de un proyecto que exigía que formara profesionales de la informática en una tecnología de alta innovación en el momento.

El año era 2006 y la tecnología PostgreSQL 8.

Decirte que estuve aterrado durante mis primeras sesiones es decir poco; allí estaba yo, a mis 22 años y al frente de un salón con no menos de 15 personas por sesión, enseñando sobre servidores de bases de datos a personas con mucha mas experiencia que y mucha mas experticía en el área que la que yo pudiese imaginar; recuerdo que hasta tuve participantes que certificados como DBAs Oracle y algunos que tenían en la informática mas tiempo del que yo tenia vivo. Algo que me sorprendió fue ver como estas personas llegaban a la clase siempre con la expectativa de aprender algo nuevo, que yo dijera algo que no sabían y aprender como desarrollarse mas como profesionales.

No te voy a mentir y decir que me enamore de la enseñanza inmediatamente, o que milagrosamente me desarrolle como un instructor estrella e impresione al máximo a todos; de hecho, esas primeras sesiones (y mi primer año como instructor) fueron bastante terribles en retrospectiva.

Pero siempre ocurría algo.

Quizás un nuevo detalle técnico se asomaba, un aspecto de PostgreSQL que no conocía asomaba la cabeza y lo explorábamos en conjunto, así fuesen cosas tan puntuales o sencillas como detalles de la sintaxis de un ALTER TABLE o un SELECT, surgían temas que no hubiese afrontado con el mismo ahínco sin la necesidad de explicarlo o el apoyo de mis alumnos.

Durante mi época como educador siempre fui aprendiendo cosas nuevas en el área, hasta llegar a tener un nombre medianamente establecido en la materia. Había gente que buscaba mi consejo y yo me sentía cómodo dándolo.

Luego de un par de años como instructor, tuve una conversación con un familiar sobre como mi conocimiento había crecido exponencialmente mientras compartía aquello que ya sabia, el me miro entretenido y sin pensarlo mucho me dijo algo que siempre he tenido presente desde ese entonces

  • «Solo puedes ser experto en algo cuando se lo haz enseñado a alguien«.

Esto me llego profundamente y me hizo pensar en la gente con la que me había cruzado en mi formación académica y en mi carrera profesional y note un patrón: hubo gente que me ofreció mucho, me enseñaron tanto en practica como en teoría; inclusive en algunos casos fueron mas allá y obtuve mentores sin darme cuenta, gente que me apoyo cuando la lógica indicaba lo contrario y me di cuenta que había una reciprocidad en ello.

Al ayudar a otros se ayudaban a si mismos, no solo en un nivel espiritual o algo fuera de nuestro contenido practico, sino que al asesorarme o explicarme también refrescaban sus propios conocimientos y podían explorarlos desde otro ángulo; no con esto quiero decir que lo hicieron por mero interés, sino que como producto de su ayuda, recibían también un impulso propio.

Esto me hizo decidir a asumir el mismo rumbo y me dedique con esmero no solo a mejorar mis aptitudes técnicas sino también a convertirme en un mejor instructor, al punto que procure tanto las actividades del salón de clases que me ofrecieron ocupar el cargo de Coordinador de Adiestramiento de la empresa en la que trabaje.

Ahora te debes estar preguntando: y esto que tiene que ver con todo lo que hemos venido conversando en el blog?

Pues la verdad es que debo confesarte que desde hace unas semanas he tenido la oportunidad de recibir el coaching de un excelente mentor, su nombre es John Sonmez, tambien conocido como el «SimpleProgrammer«. Con su ayuda, he conseguido retomar mucha de mi voluntad profesional e inclusive desarrollar la convicción de volver a la enseñanza, si bien no de forma directa, si a través de mis publicaciones.

Te explico un poco lo que ocurre, John es un partidario de dos cosas muy particulares:

  1. Todo profesional de la industria debe mantener un blog que actualice al menos una vez por semana con sus ideas y opiniones.
  2. Es necesario especializarse y ser muy especifico en tu área de especialización, esto se debe mostrar en el contenido de tu blog.

Creo que lo mas importante que he recibido hasta ahora por parte de John han sido sus herramientas para la constancia, si prestas atención en el transcurso de 3 semanas ya llevo 8 posts, todos con información desarrollada y en tópicos muy puntuales.

En sus propias palabras, John trata de convertir en simple lo complejo, pero a nivel un poco mas desarrollado, John se dedica a impulsar las carreras de la gente involucrada en el mundo del software, indistintamente de su área, mientras que al mismo tiempo se mantiene activo en el mundo del desarrollo de software.

Pensando en esto, descubrí que aunque mi carrera pueda seguir evolucionando en el área del desarrollo, igualmente siento la necesidad de compartir lo que he descubierto y aprendido en mi carrera, es decir, sin importar hacia donde se dirija de ahora en adelante, quiero hablar de lo que se y quiero compartir este conocimiento.

Esto me inspiro a descubrir como quería llevar mi blog:

  • Enseñar a Programar desde Cero con C++
  • Compartir la Programación Limpia en Java.
  • Publicar Exclusivamente en mi Idioma.

Ya tenía mi especialidad y ya tenía mi blog, pero como llevar esto a la practica de manera exitosa?

Quizás pudiese haber hecho lo que hice en las veces anteriores que me dedique al blogging, es decir, conforme vayan surgiendo temas en mi área de interés, hacer publicaciones; pero ya esto lo intente varias veces y nunca funciono.

Einstein nos enseño que hacer lo mismo múltiples veces y esperar resultados diferentes es la definición de la locura, por lo que recurrí a mi mentor en esta materia y John una vez mas me tendió la mano.

El ha diseñado un curso gratuito con una duración de 3 semanas, durante las cuales iras recibiendo correos con instrucciones sobre como empezar a trabajar en tu blog y como desarrollar consistencia en tu habito de publicación; no estoy hablando de nada vago o técnicas mentales para ser un mejor escritor o articulista, estoy hablando de ejercicios prácticos y con resultados específicos que el mismo verifica y hace comunicación uno a uno con los participantes. Esto sin contar los múltiples posts que hay en su sitio sobre como impulsar tu productividad, e inclusive John nos muestra las técnicas que el mismo utiliza para obtener mejores resultados y que puedes explorar de forma gratuita.

Entiendo que mi compromiso ha sido el de proveerte información en nuestro idioma, y que quizás el ingles sea una traba para algunos, pero como profesional en el área con mas de diez años de experiencia y que se de primera mano lo que es contar con figuras de apoyo para fortalecerte como profesional puedo decir que el trabajo de John Sonmez vale la pena difundirlo.

Comparto una vez mas los enlaces al trabajo de John:

Espero que este post haya sido de tu agrado.

Hasta la próxima.

Publicado en Blogging | Etiquetado , , , | Deja un comentario

Qué es el Código Limpio?

Antes de que arranquemos a hablar del Código Limpio, quiero que hagamos un pequeño ejercicio.


Si te presento el siguiente código puedes determinar de que se trata sin necesidad de ver mas nada?

public ArquillianCucumber(final Class<?> klass) throws InitializationError {
   super(klass);
}

Aquellos que conocen Java pueden inferir que estamos viendo un método constructor (es un metodo publico sin especificar tipo de retorno), igualmente sabemos que es posible que este método retorne una excepción de tipo InitializationError y que el constructor utiliza el método constructor heredado por su padre para hacer una tarea.

Adicionalmente, si conoces suficiente sobre BDD y Testing con Java Enterprise Edition pudieses adivinar que forma parte del proyecto CukeSpace, que busca mezclar los proyectos de Cucumber con Arquillian.

Si nos damos cuenta pudimos entender mucho de la formación técnica del código sin entender su intención o el propósito de su ejecución.

Veamos que dudas quedaron en el aire:

  • Qué hace la clase ArquillianCucumber?
  • Que hace el argumento «klass«?
  • Es importante que su tipo sea parametrizado de forma indeterminada? (esto lo hace la aplicación del símbolo «?» en tipos genéricos)

Quizas si exploramos en la herencia y ubicamos al padre de ArquillianCucumber esto se aclare; veamos ahora el código del constructor padre que esta clase esta invocando.

public Arquillian(Class<?> klass) throws InitializationError {
super(klass)
}

Pues no ayuda mucho!

Seguimos prácticamente con las mismas incógnitas, solamente que ahora sabemos que ArquillianCucumber es hijo de Arquillian, pero aun no sabemos mucho de su propósito. Dicho esto, podemos empezar a sospechar un patrón (muy común en la programación moderna):

  • La intención del código heredado es propensa a perderse en el camino.

Veamos al constructor padre de Arquillian a ver si podemos por fin descifrar este misterio.

public BlockJUnit4ClassRunner(Class<?> testClass) throws InitializationError {
   super(testClass);
}

Pues aquí tenemos un progreso significativo, vamos a repasar un poco lo que hemos descubierto

  • Las clases son Runners, es decir se encargan de la ejecución de código
  • Particularmente se encargan de la ejecución de clases completas
  • Funcionan con el framework JUnit en su version 4
  • Podemos inferir que el parámetro que reciben, llamado «testClass«, es la clase de prueba que se va a ejecutar.
  • Y por ultimo al saber que el parámetro es una clase de prueba sabemos que puede ser de cualquier tipo, por lo tanto debe utilizar el comodín «?» en el tipo Class.

Ahora mi pregunta es: cual es la diferencia entre estos tres bloques de código?

La respuesta es evidente, uno nos revela su intención y propósito de forma clara, a través de los nombres que define, mientras que los otros no.

Es tanto así, que no tuvimos necesidad de seguir subiendo en clases padres para entender por completo el constructor; confiamos en la descripción que obtuvimos, y esta es una señal clara que acabamos de ver Código Limpio.

NOTA: El código de estos métodos se extrajo de sus respectivos repositorios Github.

Código Limpio y Programación Limpia

Quizás puedas decirme que es injusto juzgar el propósito de una clase a partir de uno de sus métodos, las clases deben juzgarse en un todo y debemos hacer estudio e interpretación de todo lo que tenemos para determinar el propósito.

Déjame responderte a esto con una sola frase: Patrañas.

Todo código debe revelar de forma clara su intención, y si el método constructor es en el que nos basamos para construir la clase, entonces el mismo debe revelar la intención de la clase, si no de manera especifica, debe darnos ideas a groso modo que luego podemos explorar a detalle. De esta forma, debemos tomar en consideración que nuestro código esta hecho no solo para ser ejecutado sino también para ser leído e interpretado, y cada método/procedimiento/función sirve un propósito que varia según el tipo de orientación pero que igual debe expresarse de forma clara.

De esta forma cuando un código, sin importar el lenguaje en el que se escriba o la orientación que reciba (objeto, procedimental o funcional), expresa claramente sus propósito e intenciones recibe el nombre de Código Limpio, y a la practica de desarrollar el mismo se le conoce como Programación Limpia.

Si queremos entender el movimiento del Código Limpio, hace falta conocer un poco a su fundador Robert C. Martin, alias el Tío Bob.

El Tío Bob

Robert C. Martin

Robert C. Martin

El Tío Bob es una leyenda dentro del mundo de la informática, no solo por sus amplios conocimientos técnicos, aunque no esta de mas decir que en mas de 40 años de carrera ha utilizado TODO lo que se puede utilizar para programar, sino por ser también uno de los fundadores del movimiento ágil (es uno de los autores del Manifiesto Ágil), baluarte del profesionalismo en el mundo de la Ingeniería del Software, y defensor de la optimización del trabajo de equipos de desarrollo.

Durante los años ha utilizado su capacidad de explicar practicas y conocimientos técnicos de alto nivel a profesionales como manera de impulsar el profesionalismo de nuestra carrera; es conocido como el autor de algunos de los libros mas valorados en nuestra área y por dar extensas charlas sobre lo que el considera las practicas profesionales que debe seguir un ingeniero de software (una búsqueda rápida en Youtube nos muestra algunas de las mas interesantes).

Dicho todo esto, se puede decir que su trabajo mas famoso es su libro «Código Limpio: Manual de Estilo para el Desarrollo Ágil de Software«.

En este libro, de forma bastante precisa y autoritaria, el Tío Bob describe cual debe ser el comportamiento de un profesional ágil de la Ingeniería de Software y nos plantea lo que para mi ha sido una revelación profesional cuando dice (y parafraseo):

  • Cualquiera que sea capaz de escribir programas en un lenguaje de programación es un «programador«; la diferencia entre un «programador» y un «ingeniero de software» radica en las practicas, la estandarización y el cuidado que damos a nuestro trabajo, no solo para nuestro consumo sino el de los demás. Es decir, la principal diferencia radica en el PROFESIONALISMO.

De esta manera el Tío Bob nos da a entender que no es solo la capacidad técnica lo que guía a un profesional de la ingeniería del software, sino el desarrollo apropiado de software a través de medidas muy puntuales que impulsan el desarrollo ÁGIL de software. Igualmente, nos explica cuales son los elementos necesarios para reconocer el trabajo de un Profesional (con P mayúscula) de la industria del software.

Qué factores determinan al Código Limpio?

Según el Tío Bob, hay 3 factores esenciales para el Código Limpio

  1. Legibilidad de la Fuente, o capacidad del código de explicar su propósito sin necesidad de recurrir a nada mas que el código.
  2. Organización de Elementos, es decir, la estructuración correcta de los elementos de un sistema donde uno espera que estén.
  3. Certeza de Funcionamiento, que se obtiene a través de la implementación de diferentes pruebas que verifiquen nuestros sistemas. El Tío Bob lo lleva un paso mas allá asegurando que «los verdaderos ingenieros de software prueban su código y la mejor manera de garantizar esto es implementando TDD«.

Ahora bien, cual de estos tres puntos podemos considerar como el mas importante?

Factor Principal: Lectura

Nuestro código esta hecho para ser leído.

Es una declaración muy importante y poco valorada ya que como técnocratas que somos, consideramos que el propósito de un código fuente no es ser leído, sino ejecutado por una maquina; aun así puedo asegurarte que eso no es del todo cierto.

Sin duda alguna, el código debe funcionar correctamente; un código sin funcionalidad es inútil, pero en el mundo del desarrollo profesional también debemos considerar de forma consciente la Legibilidad del Código.

Te preguntaras el por qué? pues si lo pensamos de forma técnica, el código fuente nunca es ejecutado, es el código interpretado por un compilador el que se ejecuta. De esta manera no es lo que escribimos sino su interpretación en lenguaje de maquina lo que va al hardware (si programas en Assembly esto no aplica)

Si no me crees, te pido que me digas cual es la diferencia entre los siguientes métodos:

public void recorridofor(int c) { for(int i=0;i<c;++i){System.out.println(arr[i]);} }

public void recorridoDeConfiguracion(int cantidadDeElementos)
{
   for(int indiceElemento=0; indiceElemento<cantidadDeElementos; ++indiceElemento)
   {
      System.out.println(elementosDeConfiguracion[indiceElemento]);
   }
}

A nivel de ejecución(código compilado) son prácticamente idénticos, su velocidad técnicamente es la misma, no hay mayor diferencia al ejecutarse. Es decir, a nivel técnico son iguales, pero cuando nos vamos al nivel humano, aquel en el que se requiere una comprensión un poco mas abstracta de que hace el código, pues es obvio a la vista que el primer método cuesta entenderse, hay una mezcla entre declaraciones, símbolos especiales, palabras claves, etc; mientras que en el segundo método no solo hemos nombrado correctamente los elementos involucrados de manera que revelamos su intención sino que hemos ordenado vertical y horizontalmente el código permitiendo seguir la secuencia de lo que se esta haciendo y entender de manera mas sencilla el propósito del código.

Pregúntate cual de los dos métodos nos da un mayor aire de profesionalismo? cual parece haber sido hecho «de golpe» y sin consideración? cual denota un análisis, así sea momentáneo, por parte de su autor? Las respuestas saltan a la vista.

Una vez hayamos analizado esto, nos damos cuenta que el código fuente profesional no esta pensado exclusivamente para el consumo de la maquina, sino que también se desarrolla pensando en como lo va a utilizar el resto del equipo de desarrollo (rara vez un profesional trabaja solo) o nosotros mismos en un futuro.

Te invito a hacer la siguiente reflexión

  • Cuando estas desarrollando una función nueva, cuantas veces vuelves a leer las funciones que invoca o las estructuras que utiliza? cuantas veces chequeas las variables que utiliza? cuantas veces haces lectura de tu código una vez esta listo? o lo lees conforme lo vas escribiendo?

Ahora que lo dijimos en voz alta y lo consideramos parece obvio, pero normalmente no lo damos por hecho. Es por esto que creo que no exagero cuando digo que leemos mas de lo que escribimos al desarrollar software.


Por ahora dejaremos hasta aquí nuestro estudio del Código Limpio, pero este es un tema que me apasiona mucho y el cual exploraremos en mayor detalle a futuro. Por ahora puedo adelantarte que cuando retomemos el tema de la Programación Limpia, hablaremos de las buenas practicas de lectura y como crear código auto-comentado. Como siempre, espero que este post haya sido de tu agrado.

Hasta la próxima.

Publicado en Blogging | Etiquetado , , , | Deja un comentario