jueves, 7 de julio de 2011

El Valor del Software

El Valor del Software

En todos los desarrollos software, hay un tira y afloja con el usuario sobre lo que tiene que hacer el sistema. Una de estas fuentes, de estos tiras y aflojas, son la complejidad de los requisitos software que pide el usuario.

En estas situaciones, en mi opinión, hay que tener cuidado, ya que, si se tira mucho por parte del equipo de desarrollo sobre un requisito, es posible que el usuario, devalue la aplicación tanto, que no quede contento.
Si el usuario está solicitando un requisito que para el es de un gran valor para su trabajo, y finalmente, se modifica tanto ese requisito. Ese requisito no va a portar el valor que esperaba el usuario.
Esto me recuerda a un programilla que desarrolle para una amiga abogada. Este programa contaba a partir de una fecha y un plazo, el día en que vencía ese plazo (dies ad quem). Programar esto, es fácil, pero el valor para el usuario era grande. Pero al poco de ver como la aplicación calculaba el día que vencía el plazo, quiso que el programa se comunicara con su calendario de Google, de forma que le enviase un aviso por correo un día antes de que cumpliera.

Esto se vio pronto que era de un gran valor añadido, ya que ahorraba tiempo, y así, sería más díficil que un plazo se pasase. Pero había una complejidad técnica. Tenía que mirar la API de google. Entonces, tenía dos opciones (al menos en ese momento pensé):

a) Convencer al usuario para que la herramienta  implementara un envio de correo a su cuenta de correo y asi, lo tendría almacenado. La complejidad técnica es menor, ya que en .net esto se hace con unas cuantas lineas.

b) Mirar la API de google y tratar de comunicar el programa, CuentaPlazos, con el calendario de Google.
La opción a) deja al usuario sin centralidad en su calendario toda su actividad. Corriendo el riesgo de bajar el valor de la aplicación, y por consiguiente su uso.

La opción b) , aunque cuesta algo más de tiempo, añade valor a la aplicación, y así lo percibe el usuario.
Con este ejemplo creo que el identificar y mantener los requisitos con más valor para el usuario son fundamentales en el desarrollo software, ya que si no, es posible que no use el futuro software.

En el caso del CuentaPlazos, es posible, que si muestro un calendario con colorines de forma muy vistosa, pero luego, no se comunica con el calendario de google, la aplicación perdería valor para el usuario ya que no se ha implementado un requisito para él fundamental.

Y es que, en definitiva, un software que pide un cliente, debe de satisfacer a dicho cliente, y en el desarrollo habrá que poner los medios para alcanzar dicho objetivo.


sábado, 2 de julio de 2011

Codificando para depurar

Codificando para depurar


En la codificación es muy normal al codificar una función o método de una clase, esperar que funcione como debe de funcionar. Creo que esto es debido a que cuando implementamos un método, sabemos desde donde va a ser llamado y sabemos perfectamente cual será el escenario de esa llamada. Por ejemplo, si estoy implementando.

void CTriangle::create(Point *pPoints);

Desde donde será llamada, siempre el puntero pPoints será distinto de null, y los tres puntos serán distintos. Ya que algoritmo de creación de triangulos, si funciona al 100% correctamente, pasará siempre un array de puntos correctos.


¿Pero que pasa, si ese algoritmo tiene algún bug? crearemos algún triangulo incorrectamente y entonces, en pantalla o no se verán o veremos cosas raras en la pantalla.


Aquí, en este punto, es donde es el motivo de este post. El codificar para depurar. Podemos tener, una función de chequeo dentro del método Create para que inmediatamente que se cree un triangulo, comprobar que es correcto, y si no lo es, hacer saltar un assert. De esta forma, se va, SIN perdida de tiempo, al fallo y no gastar un tiempo precioso en depurar. 
Cierto, esto ralentiza la ejecución, pero después, cuando no salta ningún assert, estás comprobaciones, se pueden comentar en código.


Un ejemplo de ello. Cuando estaba implementando la "Triangulación Restringida de Delaunay", tenía este método que llamaba cada vez que creaba un objeto de la clase CTriangle.



// cheque que el triangulo está construido correctamente
// true si tiene algun error.
bool CTriangle::checkError(void)
{
bool bError = false;


if (isRepeatVertex())
bError = true;
if (isRepeatVertexPoint())
bError= true;
if (checkAdyacents())
{
bError = true;
}


if ( !bError )
{
//TRACE("---------------- ERROR TRIANGULO ------------\n");
//debugView();
}



return bError;
}


checkError comprobaba que el triangulo estaba bien construido, tanto en sus indices al array de puntos, como que los puntos eran distintos entre sí, y en sus triangulo adyacentes. De esta forma, al saltar este chequeo, era un signo de que algo mal estaba en el algoritmo de Triangulación.

Otra forma que ayuda para depurar, es identificar de forma única a cada objeto que se crea. De esta forma, puedes trazar la evolución de un objeto y centrarte en el solamente. Por ejemplo, en CTriangle tenía:

int m_id;

Así, si saltaba el método checkError, con el id del triangulo, podía centrarme en como se creaba este triangulo y su relación con sus adyacentes.


Con todo esto, creo que no debemos de pensar al codificar, que todo saldrá bien, sino debemos pensar, que algo irá mal y tendremos que depurar. Entonces, tendremos que codificar para que dicha depuración sea más fácil, eficaz y productiva.






Aquí, os dejo una demo de un programa que utiliza dicho algoritmo