Sigo con la mini-serie con el original título “partes de un negocio”. Esta vez voy a hablar de algo más cercano a lo técnico, esto es, no me basaré en suposiciones ni en historietas del abuelo :).
Los desarrolladores tenemos la costumbre de incluir errores en las aplicaciones, algunos dicen que son bugs, otros pequeños errores… por lo general cuando un error llega a una versión release quiere decir que vas a perder dinero y es proporcional a la gravedad y al número de licencias vendidas.
Pongamos un caso real, yo vendo un sistema con un software a 10 personas, todo parece funcionar perfecto, así que incluyo algunas mejoras y vendo esta nueva versión a otras 10. Pasa un año y resulta que una de esas personas te reporta un error. No pasa nada, un error aislado no es un error, es un contratiempo… sin embargo te llama otro y te cuenta lo mismo, empiezas a sospechar. Haces tus pruebas y todo parece funcionar bien, por tanto echas la culpa al usuario. Por experiencia, cuando te llaman dos personas con el mismo problema el fallo es tuyo, con lo cual ponte a buscar el error como un loco.
Comos unos hachas desarrollando reproducimos el error con los ficheros de log que hemos guardado (somos unos bestias y no se nos escapa ni un dato), vemos que es una buena metedura de pata, lo arreglamos y se lo corregimos a los clientes que han llamado.
¿Cual es el problema? De las 20 versiones que hemos vendido, cuántas tienen el error y cuantas no? Les estará funcionando mal al resto y no se han dado cuenta? solo hemos vendido 3 licencias de esa versión?
Para tener esto controlado hay dos reglas muy simples que hay que seguir:
- Congela tú código y marcalo: da igual que sea un cambio de un espacio en una línea de código, un cambio en un script de compilación… lo que sea, lo marcas y lo congelas de alguna forma (con ficheros zip, con tags en subversion, lo que sea).
Corolario: Ten siempre a mano y usables TODAS las versiones. Esto es, en cualquier momento pueden venir unos datos de una versión y tienes que sacarla del baúl y usarla. Hay que ser muy muy estricto con esto, no hay que dejar pasar ni un solo cambio sin marcar.
Corolario: todos los datos que genere la aplicación deben llevar en alguna parte la versión que corresponde.
Si no haces esto vas a perder mucho tiempo en encontrar la versión que usaste, no vas a saber si es un error propagado por diferentes versiones, es decir, estás en pelotas.
Como ejemplo yo mantengo ahora mismo 3 ramas de desarrollo mas una estable, en las ramas pruebo cosas sin desestabilizar la estable. Además, todos los datos que recojo de mis pruebas o de clientes los tengo también en el repositorio convenientemente marcadas y asociadas a las versiones de las que partieron, todo eso junto a información de las pruebas.
- Mantén un mapeo cliente-versión: parece de sentido común, pero se suele dejar porque es un coñazo. Además ten un mapeo de cosas que creas que nunca van a afectar… por ejemplo, nosotros guardamos la versión del software, marca, modelo y números de serie de todos los componenetes, marca del tractor, zona de trabajo, metros de las máquinas que tiene, cuantos tractores tiene la persona, etc, etc.
De esa forma puedes obtener una relación directa si te llama más de una persona.
Subversion es una herramienta básica para cualquier persona que use un PC y tenga que mantener versiones de datos, la gente se rie cuando le dices que usas subversion hasta para el currículum, pero es una de esas herramientas que deberían venir por defecto instaladas en el sistema operativo. Con un sistema de control de versiones con muy poco trabajo tendrás todo etiquetado, con un histórico envidiable, acceso a cualquier cosa, puedes ver el diferencial, mantener copias de seguridad… no es necesario mantener un tracker ni complejos scripts si no tienes demasiado tiempo como es mi caso. No me cansaré de hablar bien de subversion.
A mi me han robado pocas veces, pero la verdad es una sensación mala, te sientes desprotegido y sin saber muy bien qué hacer. Sin embargo hay veces que ver que te intentan robar es algo que reconforta y que te anima a seguir.
Me encuentro con lo siguiente en los foros de todo Pocket PC. Sí señor, alguien está interesado en robar agroguía, eso quiere decir que a la gente le está gustando… :).
De todas formas no es la primera vez, ya he visto a gente buscandolo por los foros, por ejemplo en este y lo más patético, en este que el fulano tiene los cojonazos de pedirlo incluso sabiendo que el autor escribe líneas más arriba :)
Lo más será el día que estén en el emule :)
Propongo un contexto real: estamos programando bajo una plataforma asquerosa difícil de trata, pongamos una PDA. Tenemos un módulo, por ejemplo una clase que carga un fichero de configuración, que queremos probar y no queremos crear un programa específico para PDA que use la clase, cargue un fichero que hemos tenido que copiar y luego muestre resultados. Es mucho más cómodo hacerlo haciendo un “make” desde la línea de comandos.
Hay diferentes frameworks para hacer test unitarios en C++, cada uno con sus ventajas, se puede ver un análisis (bastante pragmático) en games from whitin. Yo he escogido cppunitlite, por las siguientes razones:
- tiene todo lo que necesito: fixtures, asserts
- no tiene dependencias, se compila con un solo make y a funcionar
- apenas son 10 ficheros
Una vez bajado para arrancar a funcionar solo es necesario tener instalado un compilador. Para windows me gusta usar Mingw ya que además trae make. Además conviene tener instaladas las herramientas de línea de comandos de linux para windows (si no las tienes intaladas ya mereces un castigo).
Bueno, vamos a crear el primer test unitario (formateo patrocinado por el conversor a HTML de vim):
//
#define GLOBAL_CONFIGURATION “configuration.txt”
#define DEBUG_INFO
#include “lib/TestHarness.h”
#include “../../src/configuration.h”
class ConfigurationFixtureSetup : public TestSetup
{
public:
void setup()
{
entries.push_back(conf_entry(“LOG_PROY_DATA”,0));
entries.push_back(conf_entry(“GGA”,1));
entries.push_back(conf_entry(“GGL”,1));
entries.push_back(conf_entry(“RMC”,1));
entries.push_back(conf_entry(“RMZ”,1));
entries.push_back(conf_entry(“VTG”,0));
entries.push_back(conf_entry(“GSA”,1));
entries.push_back(conf_entry(“LOG_REAL_DATA”,0));
entries.push_back(conf_entry(“SMOOTH_DIR”,0));
entries.push_back(conf_entry(“RATE”,10));
entries.push_back(conf_entry(“THRESHOLD_VEL”,0));
entries.push_back(conf_entry(“SHOW_CALC_DIR”,0));
entries.push_back(conf_entry(“SHOW_VELOCITY”,0));
entries.push_back(conf_entry(“SHOW_SAT_INFO”,1));
}
void teardown()
{
entries.resize(0);
}
protected:
Configuration fixture;
struct conf_entry
{
conf_entry(const char *n, int v):
varName(n),
value(v)
{}
const char* varName;
int value;
};
std::vector<conf_entry> entries;
};
/**
*/
TESTWITHSETUP (ConfigurationFixture,Test_ReadConf)
{
for(int i = 0; i < entries.size(); ++i)
{
int value;
CHECK(Configuration::GlobalConfiguration()->getValue(entries[i].varName, value));
printf(“%s-> %d\n”,entries[i].varName, value);
CHECK( value == entries[i].value);
}
}
En resumen lo que hace es cargar un fichero de configuración y testear que todos los valores cargados son los esperados.
Es un test muy simple y se puede lanzar desde la línea de comandos después (o antes) de la compilación sin necesidad de meterlo en la PDA, que es un coñazo terrible.
Si de verdad quieres saber un detalle como hacer test unitarios en C++ recomiendo que leas Pruebas unitarias con C++, extenso y completo artículo de como hacer test en C++ con CPP unit escrito pon JM, un compañero de Unkasoft.
Sí, de nuevo esta semana otra solicitud de distribución que paso a reproducir eliminando los datos menos importantes:
”””
Buenos dias:
Estamos interesados en el sistema de guiado gps, somos concesionario de XXXXX XX para las provincias de Zamora y Leon, y vendemos recambios en toda España, quisiera que me pasasen informacion detallada a si como el precio que tendriamos para su comercializacion en nuestras tiendas.
Atentamente:
Fulanito J. de Tal
Subdirector de Algo importante
Direccion de Algo más importante aún
Grupo Internacionalísimo
“””
No me lo explico, no es él el que está interesado? ¿no debería tratar de comprarme? ¿no debería él hacer el esfuerzo por que yo estuviera interesado en hacer que ellos ganen dinero sin haber matado ni una neurona? ¿No somos nosotros los que estamos haciendo la parte difícil?
España es así amigos, haces el trabajo y luego otros quieren venderlo… no se dan cuenta que son muchos los que venden y pocos los que producimos? ¿se habrán dado cuenta que la ley de oferta y la demanda funciona?
Para empezar deberían haberme llamado por teléfono. Como bien dice Jesús de la Torre, si alguien está de verdad interesado en tu producto te llamao por teléfono y estas personas nisiquiera se han dignado a busca un teléfono de contacto o a poner alguno para contactar con ellos.
Soy muy bruto y mucha gente me dice que debería contactar con alguien para distribuirlo, pero es que no me apetece, no me parece bien introducir intermediarios que no quieran hacer nada. Hasta ahora los únicos que me han propuesto algo decente y se han molestado han sido las personas de Argentina. Sé que las cosas no funcionan así, que posiblemente dentro de unos años me arrepentiré, pero es que me niego a entrar en esa dinámica. No sé hasta donde llegaremos así, quizas no muy lejos, pero no pasa nada, no tendré la espinita clavada de que una persona sin hacer nada se lleve un euro, máxima de la persona triunfandora en España. Me gustan las personas que trabajan duro por algo, sea para correr 100m. en 10 segundos o para conseguir cualquier soplapollez y esas son las que se merecen mi respeto.
Hace unos meses pensé que estabamos en pleno boom, pero me equivoqué, el boom aún no ha comenzado :D
Pues dos cosas:
- que el coche te queda así (está desmangado):
- que los HIJOS DE LA GRAN PUTÍSIMA del seguro te pones pegas para todo. Son unos HIJOS DE PUTA sin escrúpulos cabrones, eso dejando a un lado la incompetencia, llegando al límite de no saber ni leer lo que puse en el formlario web con el agente de la compañía.
“Suerte” que me toca renovar el seguro ahora para no volver a topar con gentuza de este tipo.