Molan los telefonos con wifi :)
Cuando programas una aplicación, por pequeña que sea, siempre tienes la necesidad de almacenar ciertos datos que permanecerán durante las sucesivas ejecuciones. Lamentablemente los requisitos y diseños de las aplicaciones cambian y normalmente se ven reflejados en el modelo de datos que tenemos, con el consecuente cambio en la forma de almacenar los datos.
Esto se eleva a la máxima potencia cuando además esos datos son de usuario y se añaden varios problemas más:
- el primero y más importante es que para el usuario sus datos son importantes y no puede perderlos.
- el segundo es que los datos ya no están tranquilamente resguardados en un sitio calentito, van a salir a la calle, VAN A SER MANIPULADOS POR EL USUARIO, serán comprimidos, copiadas, borrados y transferidos.
Hay una serie de puntos que pueden salvarnos de muchos problemas, no son desde luego axiomas, pero a mi me han salvado de más de un problema, aquí van:
- Elige un formato: texto o binario, por un lado el texto nos permite hacer debug rápidamente, hacer cambios a mano, tiene la pega que es más complejo de leer ya que requiere un parseo. Por el contrario el binario para debug es un infierno pero permite una lectura más rápida y además evita que los usuarios sepan más de lo que quieres. Esta pequeña guía es para formatos binarios
- Usa un magic al comienzo del fichero: esto es, unos bytes prefijados por los cuales sepas nada más leer los primers bytes que de verdad es tu fichero. Esto es condición necesaria, pero no suficiente, aunque te quitará de problemas. Un detalle más, el MAGIC si puede ser ascii mejor, de esta forma cuando abrimos el fichero con un editor de texto veremos nuestro magic ahí, lo primerito y sabremos si es un hijo nuestro o no. Probadlo con un PNG, ZIP o similar, todos tienen un magic ascii.
- Usa un número de versión. De esta forma cuando tus datos vayan cambiando tus loader sabrán que hacer con ese fichero en función del número de versión. Además, conviene que tengas dos números de versión, uno que indique que cambia tu formato y otro que diga que el fichero ha cambiado pero que el formato sigue siendo el mismo. En este punto hay un tema bastante interesante: qué hacemos con ficheros que son de versiones anteriores a la actual? tenemos varias opciones, personalmente he usado dos, por un lado tener algo así:
loader = loaderFactory.getLoader(fileVersion);
loader.load(file);
o por otro:
if(fileVersion != currentFileVersion) {
migrateFile(fileVersion, currentVersion);
}
loader.load(file);
Sinceramente no sabría decir cual de las dos es mejor, en agroguía uso la primera y no me cuesta mucho mantenerla.
- guarda siempre más datos de los que necesites. Salvo que el dispositivo esté muy limitado normalmente dará igual tener un fichero de 500kb que de 600kb y te puede ayudar una burrada. Para qué puede servir esos datos extra? pues por ejemplo para almacenar datos de debug, acciones del usuario, datos internos que es posible que dentro de 4 días te puedan servir. Personalmente a mi los datos de más que guarda la aplicación me han servido para poner la cara roja a más de uno y me ha evitado problemas.
- No te cierres puertas, deja el formato abierto al futuro (pero tampoco demasiado), esto es, organizalo por secciones de forma que dejes secciones para uso futuro, te ahorrás tiempo haciendo conversores y loaders, aunque será un poco más complejo crear el loader la primera vez.
- Utiliza serializer si puedes, en pocas palabras, intenta que el código que guarda y salva ser el mismo siempre, así no habrá problemas de incoherencias entre lo que guardas y lo que cargas. No es fácil hacer un sistema así, sobretodo cuando hay objetos de por medio, el código público del unreal tiene un ejemplo a lo bestia. La idea sería más o menos así:
class serializer {
public:
bool isReading;
bool serialize(int &i) {
if(isReading)
i = readIntFromFile();
else
writeIntToFile(i);
}
};
class MyClass {
int data;
void serialize(Serializer s) { s.serialize(data); }
}
No es lo más óptimo, pero te soluciona la vida :). También se puede implementar al modo cutre con una macro de c++. Otra forma de verlo en la web de chaos^fr.
- Puede que tus datos ocupen mucho, intenta que cuando lo guardes sean lo más fácilmente comprimibles, un codificador de deltas no es prácticamente nada en código y puede resultar en un ahorro de espacio considerable una vez se ha comprimido el fichero, para por ejemplo enviar por correo.
Seguro que hay mucho más, pero estos son para mi los más importantes. A mi me habría venido muy bien a la hora de no perder el tiempo cuando he tenido que modificar el fichero de save.
Ayer estuvimos todo el día en un stand en innovaduero, un feria que mezcla de una forma un tanto extraña tecnología y turismo y que se desarrolló en Zamora, más concretamente en IFEZA . Nosotros estuvimos allí grancias al foro info rural que nos contactó (gracias a Jaime Gómez Gil).
Nunca había ido a una feria así que fuimos un poco al tuntun, con un proyector, unos videos preparados días antes a toda prisa, unas pda y unos GPS para hacer bulto. Por suerte la organización de innova (los mismos que foro info rural) nos había impreso unos carteles en grande que me preparó Juanma Zarza, aka mr koala (un nuevo compañero de trabajo) a toda prisa y casi sin material, lo cual le agradezco de verdad.
Al llegar nisiquiera estabamos en las listas de inscripción y aquella tenía toda la pinta de que iba a ser un desmadre… menos mal que al final no fue así, la organización nos traó de lujo, nos invitó a un café a media mañana, a comer, unas botellas de vino, etc.
Lo siguiente fue montar el stand, no digo más, una foto:
En el rato de preparación del stand preparé una versión de agroguía para poder enseñar una demo de una parcela y preparé unas transparencias (en powerpoint, claro) para una charla que teníamos que dar horas después y de la que nos enteramos horas antes ;)
La mañana pasó divertida, hablando con los compañeros de stand de los que luego hablaré y explicando una y otra vez en que consistía nuestro proyecto, me entrevistaron en la radio, unos 3 minutos, en los cuales mi “habilidad” no me dejó nisiquiera decir la página web ni un teléfono de contacto. Total… te dejan hablar 3 minutos en la radio y no hacer un mínimo de publicidad es para llamarme tonto hasta aburrirte. Una foto de las presentaciones de por la mañana, están aburridos:
Por la tarde más demostraciones y explicaciones, aquello se conviritó en un coñazo terrible, pero bueno. De compañeros de stand tuvimos a:
- fundación médico rural, una fundación que trata de transmitir la necesidad de aplicar la tecnología a las urgencias médicas en poblaciones alejadas. En resumen, tenían un acuerdo con philips que había creado un monitor de esos del corazón que transmitía los datos a un pc remoto gracias a GPRS y de esa forma un equipo especializado podría ayudar al médico o enfermero de la zona rural a salir del apuro. Lo que me contaron los dos señores que estuvieron allí era muy curioso y la verdad es que da que pensar. Tenemos a alcaldes en la cárcel, se están gastando dinero en gilipolleces y para algo que realmente es interesante y puede ayudar a salvar vidas no hacen ni puto caso. La única que había metido pasta era telefónica para poder compensar las supuestas (o presuntas,muy de moda ahora) enfermedades provocadas por las antenas… ahora gracias a la cobertura se pueden salvar vidas y las antenas dejan de ser peligrosas. De esto sí que se debería hacer publicidad, debería recibir ayudas políticas y económicas y atención por parte de los medios de “comunicación”.
- Proxima systems, una empresa que integraba productos de comunicación para aplicación a domótica, video vigilancia y demás. Muy interesante lo que hacían, además tuve la suerte de que eran técnicos y pudimos hablar de algo más que de vender humo y de lo maravilloso que eran sus productos. Muy agradables.
Como curiosidad tuvimos todo el día un segway de esos, además casi en exclusiva, con el que casi nos matamos :). Fue la sensación de la feria.
En resumen, una jornada muy divertida, pudimos conocer a mucha gente y aprendimos bastantes cosas acerca de lo que hacer en una feria.
Decir que un 0 para lo políticos, los cuales llegaron mal y tarde. Como siempre, para hacerse la foto. De mal en peor.
Hacía tiempo que tenía ganas de probar a renderizar un fractal y leyendo ayer en la wikipedia acerca de Mandelbrot vi que el código era muy simple. Después de todo es calcular si una función diverge tras una serie de iteraciones por cada pixel.
He hecho un pequeño código en python para hacer pruebecillas, la verdad que con muy poco código se obtienen imágenes bastante bonitas, de hecho estoy pensando en imprimir alguna y ponerla de poster. Se generan imágenes de este pelo:
El código, necesita PIL y python 2.4 y he dejado algunas funciones para generar animaciones (con un par de hilos para -intentar- aprovechar mi dual core) y 3 ó 4 test de resultados chulos. El código generado HTML a partir del .py usando, como no, vim, la putada es que blogger te mete saltos de linea y hay que quitar los tags br, con un simple replace basta.
import Image;
from threading import Thread;
SIZEX = 1024;
SIZEY = int(SIZEX*2.0/3.0);
NFRAMES = 50;
ZOOMSTEP = 1.0;
def get_color(xx,yy):
x = x0 = xx;
y = y0 = yy;
colour = 0;
iteration = 0
maxiteration = 600
while ( x*x + y*y < 4 and iteration < maxiteration ):
tx = x*x - y*y + x0;
ty = 2*x*y + y0;
x = tx;
y = ty;
iteration = iteration + 1;
colour = float(iteration)/maxiteration;
return colour;
class Palete:
def __init__(self):
self._colors = []
pass;
def addColor(self,color, t):
self._colors.append((color,t));
def getColor(self,t):
#search for color
i = 0;
while(self._colors[i][1] < t):
i+=1;
if(i == 0):
return self._colors[0][0];
else:
t0 = self._colors[i-1][1];
t1 = self._colors[i][1]
dist = t1-t0;
d = (t-t0)/dist;
c0 = self._colors[i-1][0];
c1 = self._colors[i][0];
#print d
color = (c0[0] + d*(c1[0] - c0[0]),
c0[1] + d*(c1[1] - c0[1]),
c0[2] + d*(c1[2] - c0[2]));
return color;
def get_img_fractal(zoom, px,py, palete):
im = Image.new(“RGB”, (SIZEX,SIZEY))
for x in range(SIZEX):
for y in range(SIZEY):
t = get_color(px + zoom*(-2.0 + 3.0*(float(x)/SIZEX)) ,py + zoom*(-1.0 + 2.0*(float(y)/SIZEY)));
color = palete.getColor(t);
im.putpixel((x,y),(255*color[0],255*color[1],255*color[2]));
return im;
class Fractal(Thread):
def __init__ (self,fractals):
Thread.__init__(self)
self._fractals = fractals;
def run(self):
p = Palete();
p.addColor((1.0,1.0,1.0),0.0);
p.addColor((1.0,0.0,0.0),0.5);
p.addColor((1.0,1.0,1.0),1.0);
for x in self._fractals:
print ”generating %.3d.png” % x[3];
get_img_fractal(x[0],x[1],x[2],p).save(“%.3d.png” % x[3]);
def animation():
zoom = 1.0;
it = 0;
fractals = [];
for n in range(NFRAMES):
fractals.append((zoom,-0.77028065155993652446, -0.11144667326007166574,n));
zoom = zoom/2.0;
it+=1;
#launch two threadç
f1 = Fractal(fractals[:len(fractals)/2]);
f2 = Fractal(fractals[len(fractals)/2:-1]);
f1.start();
f2.start();
def testColoring():
p = Palete();
p.addColor((1.0,1.0,1.0),0.0);
p.addColor((1.0,0.0,0.0),0.5);
p.addColor((1.0,1.0,1.0),1.0);
get_img_fractal(0.4,-0.77028065155993652446, -0.11144667326007166574,p).save(“coloring.png”);
def testColoring2():
p = Palete();
p.addColor((0.0,0.0,0.0),0.0);
p.addColor((145.0/255.0,165.0/255.0,192.0/255.0),0.5);
p.addColor((1.0,1.0,1.0),1.0);
get_img_fractal(0.0001,-0.77028065155993652446, -0.11144667326007166574,p).save(“coloring2.png”);
def testColoring3():
p = Palete();
p.addColor((1.0,1.0,1.0),0.0);
p.addColor((145.0/255.0,165.0/255.0,192.0/255.0),0.5);
p.addColor((0.0,125.0/255.0,244.0/255.0),1.0);
get_img_fractal(0.0001,-0.77028065155993652446, -0.11144667326007166574,p).save(“coloring3.png”);
def testColoring4():
p = Palete();
p.addColor((0.0,0.0,0.0),0.0);
p.addColor((145.0/255.0,165.0/255.0,192.0/255.0),0.5);
p.addColor((1.0,1.0,1.0),1.0);
get_img_fractal(0.00001,-0.26605838294940658357,-0.65123057178473777796,p).save(“coloring4.png”);
#testColoring2();
#testColoring3();
testColoring4();
#animation();
El pasado sábado estuve en una de las reuniones que DOID organiza para presentarse. Fue en Madrid, en la sede del medialab, un sitio muy cool, con puertas grandes, todos con mac y gafas de pasta.
En el sitio de congregan para realizar una serie de talleres sobre temas de visualización, la verdad es que los temas que tratan parecen interesantes, precisamente el sábado estaba el creador de processing y unos meses atrás estuvo el proyecto levelhead, sí, el del cubo con webcam.
Al grano, Nae empezó comentando qué era DOID que se había hecho hasta ahora, que empresas lo formaban (tirón de orejas por no incluir unkasoft) y cual eran las directrices.
La exposición pasó a ser un debate en el que cada uno pedía lo que le salía de las narices poco más o menos, unos se quejaban de lo mal que se trata a los empleados, otros de la fama de frikis, las empresas se defendían incluso, ojo al dato, diciendo que se pagaba bien y que se pagaban las horas extras, sí, habeis leído bien. Fue de lo mejor que escuché en ese rato, una empresa que se dedica a temas relacionados con ingeniería (no me gusta la palabra informática) que paga horas extras, eso me impactó realmente. En ese poco tiempo se pidió un servicio de servidores de trac y svn, formación, difusión, apoyo a amateurs… de todo un poco.. ah! y se presentaron dos juegos casuales con muy buena pinta.
Hubo cosas curiosas, como por ejemplo el momento en el que entra juan tamargo, jefe de proyectos de pyro, entonces Nae paró la exposición y le preguntó acerca de un tema interesante, la falta de diseñadores y gestores de proyecto… el fulano le dijo que no venía representando a pyro, respondió brevemente y se piró. Qué momentazo.
En conclusión, hay pocos profesionales, no hay dinero en esta nuestra industria, la gente se va a otros sitios donde se trabaja menos, con menos presión, pensando menos y cobrando más… todas las nuevas empresas que empiezan lo hacen programando para móvil y mucha gente parece que se pasa a nintendo DS.
Una foto del evento tomada de la cuenta de flickr de medialab, donde se pueden encontrar más fotos del sábado.
Enhorabuena a Nae por saber tirar del carro.