El objetivo principal es compartir mis experiencias en la programación y gestión de proyectos de software, pero también un poco un sitio donde desahogarme y poder soltar tres o cuatro pensamientos que me llenan la cabeza a veces. Osea, lector, no esperes maravillas. Aquí hay solo un hombre que se escribe así mismo.
sábado, 31 de octubre de 2009
Una año más universitario.
martes, 27 de octubre de 2009
Aplicación Pomodoro en C# Mobile 6.5 – diferencias en el click de un DataGrid
¿Cómo capturar un click en un DataGrid para Smarthpone?
Ninguna de las siguientes funciona:
- private void dgToDoToday_KeyDown(object sender, KeyEventArgs e)
- private void dgToDoToday_MouseDown(object sender, KeyEventArgs e)
private void dgToDoToday_CurrentCellChanged(object sender, EventArgs e)
Y para saber cual es la fila que se ha invocado:
DataGrid.CurrentRowIndex.ToString();
lunes, 26 de octubre de 2009
Aplicación Pomodoro en C# Mobile 6.5 – diferencias entre un dropDownList y un comboList.
Pero aquí hay una pequeña diferencia que me ha llamado la atencióny que quiero compartir/almacenar en este blog.
En este hilo describo como cargar los campos de texto y valor de un dropDownList. Pero para mi WM utilizo otro control que es el de comboList y que, usando la misma sintaxis, cambia el nombre de los parámetros. Lo cual quedaría asi:
cbToDoToday.DataSource = datos.tablaToDo; //El campo tablaToDo de la clase datos devuelve un dataTable.
cbToDoToday.ValueMember = "id";
cbToDoToday.DisplayMember = "descripcion";
Fijaros que es lo mismo que en un dropDownList pero en vez de usar el DataValueField y el DataTextField, aquí utilizamos el ValueMember y el DisplayMember.
Actualización: aún hay más.
En el dropdownMenu utilizamos el SelectedValue o SelectedText para capturar o seleccionar un item del control. Pero en el combo la cosa es, otra vez, un tanto extraña ya que se hace con el SelectedItem.
Curiosas estas pequeñas diferencias.
Open Agile Spain 2009 - Madrid.
Gracias a la organización, patrocinadores y a todos los participantes.
jueves, 22 de octubre de 2009
Aplicación Pomodoro en C# Mobile 6.5 – adjuntando ficheros al Implementar la solución.
En este caso mi problema viene debido a que he creado un fichero xml en para utilizarlo como repositorio de los datos de las tareas a realizar y que serán utilizadas por el cronómetro.
Construyo la clase de datos que me cargue el contenido del xml en un dataSet y me devuelva el dataTable para alimentar a un DataGrid (pero eso es otra historia). Pero cuando lanzo el debuguer del VS me devuelve impepinablemente un error de fichero no encontrado.
Me reviso el directorio en donde me está Implementando la aplicación en el emulador y veo que me sube correctamente el fichero ejecutable pero no el fichero xml. Por lo cual y, con lógica vulcaniana, no lo encuentra.
Después de un montón de tiempo buscando en San Google, MSDN, Windows Mobile para programadores y hasta en HTCMania en sus foros de desarrollo WM, he encontrado la solución trasteando en el Visual Studio.
En el explorador de la solución del VS localizas el fichero .xml que quieres adjuntar a la aplicación y pulsas el botón derecho.
En el menú contextual, en la parte inferior seleccionas propiedades y en la pestaña que se abre verás dentro de la sección Avanzadas una entrada que dice "Copiar en el directorio de resultados".
Pones el valor de la entrada a "Copiar Siempre" o, mejor aún, a "Copiar si es posterior" y se han acabado los problemas.
Y mira que era sencillo.
lunes, 19 de octubre de 2009
Firefox, bloqueando Windows Presentation Foundation. (El mundo talibán está ganando).
En el trabajo tengo que usar Firefox para leer mi correo y mis rss ya que quiero dejar el rastro más pequeño posible de mis actividades “no laborales”.
Y hoy según lo enciendo me encuentro con el mensaje de que el plugin “Windos Presentation Foundation” ha sido bloqueado…¿?
Y esto qué es? Me pregunto. Navego a la página de descripción del error, que tiene un problema de seguridad en el certificado, y me encuentro con la siguiente conversación que es para poner los pelos de punta.
En resúmen:
1. En una revista del sector se habla sobre un fix en Windows Presentation Foundation que puede permitir la ejecución de código arbitrario. Pasando por varias revistas Y SIN PREGUNTARLE A MICROSOFT, van haciendo la bola cada vez más grande hasta que deciden que hay que bloquear el plugin, aunque ya sepan que no es un problema del mismo si no de NET. 3.5. Framework Assitn (¿Como bien dice uno, van a bloquear los SO no seguros –ósea todos-¿)
Es más, es tan alucinante como que como una revista dice que Microsoft dice que lo mejor es deshabilitarlo, hacen el salto directo y le atribuyen a Microsoft dicha declaración SIN HABERLA LEIDO en la página de Redmon. (fliplalo).
2. Inmediatamente los usuarios le avisan que esto solamente ocurre si se tiene una versión de la dll ANTIGUA del Framework Assitans, que está corregido y que no está dando fallos. Que no existe ninguna declaración de Microsoft de recomendación de deshabilitar el plugin, que todo es un FAKE. Y la respuesta es: Nada.
3. A estas alturas los mensajes de flame ya son duros. Le recuerdan que existen muchísimas páginas seguras en WPF y que qué le dicen a sus clientes cuando no puedan acceder a ellas.
4. Por último, y como resúmen. Mozilla ha deshabilitado un plugin por ser de Microsoft. Este plugin no tenia ningún problema, el problema existia en el .NET Framework Assistant (que es parte del SO) y no tiene nada que ver con Firefox y, además el problema fue solucionado DOS DIAS ANTES de que Mozilla tuviera su brillante idea.
A mí me toca la moral por tres razones:
1. ¿Quién demonios se cree Mozilla para decidir por mí que plugin puedo utilizar y cual no? Un aviso, vale. Un aviso más grande, vale. ¿Pero bloquearlo?¿Impedirme a mí, el usuario soberano, el acceder a la información en la Red?
2. ¿Cómo que no puedo desbloquearlo? ¿Cómo le puedo dar tanto poder a un simple navegador que me deja sin poder ver páginas realizadas en una tecnología? ¿Os imagináis la que se puede liar si Microsoft bloqueara los plugin que permiten ver Flash?
3. Su estupidez. No puedes bloquear la capacidad de tu navegador por un error FALSO y basado en dimes y diretes. Por dios que falta de profesionalidad.
Otra razón más para dejar de utilizar Mozilla.
domingo, 18 de octubre de 2009
GoogleWave. Una GRAN decepción.
No. Con más de una década de desarrollo web esto es inadmisible.
Una de las cosas que más se le crítico al IE6 era la barbaridad que hacían los malos desarrolladores de obligar a utilizar el navegador de Windows. Poco o a poco, se pasó de obligar a recomendar. Y por fin el desarrollo superó estas diferencias entre cómo representa la web los diferentes navegadores y no importaba el navegador.
Netxcape desapareció y surgió Firefox, opera siguió en la brecha, safari llegó a los PC, Internet Explorer creció a sus versiones 7 y 8 y con el último llegado llamado Chrome, todos muy ajustados a los estándar del W3C y a las CSS, estaba seguro que por fin solamente tendríamos que programar una vez las páginas Web y realizar pequeños ajustes. Y así olvidarnos de los Hack y demás chapuzas.
Porque dudo mucho, mucho, mucho que haya problemas con un IE. Si acaso con el IE6 y anteriores. Pero hay que recordar que hay DOS versiones y 9 años desde su nacimiento. Ósea, que si sigue siendo mayoritariamente usado será porque tan malo no es.
Por último, creo que Google debería aprender de Adobe y su flash. Que no se ha andado con esas tonterías y funciona en cualquier sistema operativo, en cualquier navegador (excepto en los Iphone). O de .NET o de Java o de tantos desarrollos que funcionan en cualquier navegador.
Pues eso, otro post más de queja y empiezo a mirar con recelo las actuaciones de Google.
P.D. Efectivamente no funciona en IE8, el más estandar de los navegadores actuales... bye, bye Wave.
P.D.D. Efectívamente funciona si le pones el Chrome Frame que es cambiar el motor del navegador... al de Google... mmmm maniobra monopolista como las más rancias de Microsoft... prefiero usar firefox para probarlo.
martes, 13 de octubre de 2009
Motivación. Se puede conseguir casi todo.
Estoy apuntado al “tostón” del twiter, que sigo sin verle mucha gracia, y su autor (de la técnica pomodoro) ha remitido por el canal #pomodorotechnique un excelente vídeo sobre la motivación.
http://www.youtube.com/watch?v=2lXh2n0aPyw
No os lo perdáis… es impresionante el resultado.
Actualización: La web thefuntheory.com y sus excelentes ideas de motivación -si haces las cosas divertidas...-
jueves, 8 de octubre de 2009
Aplicación Pomodoro en C# Mobile 6.5 – Creciendo y refactorizando.
/// <summary>
/// Efecto de alarma y pausa el cronómetro.
/// </summary>
private void alarma()
{
this.BackColor = Color.YellowGreen;
pausa();
}
Quitar un lapso de tiempo dado o iniciar una variable del este tipo utilizando el método FromSeconds(). También podría haber utilizado un TimeSpan.parse(<string tipo 00:00>); pero me gusta más la solución en donde declaro específicamente la unidad horario que estoy utilizando.
// Cómo quitar un segundo a una variable del tipo TimeSpan
horario = horario - TimeSpan.FromSeconds(1);
/// <summary>
/// Formatea el TimeSpan en minutos.
/// </summary>
/// <param name="horario">El TimeSpan a ser convertido a string</param>
/// <returns>Los minutos y segundos en formato "00:00"</returns>
private string timeSpan2minutos(TimeSpan horario)
{
return horario.Minutes.ToString("00") + ":" + horario.Seconds.ToString("00");
}
Inútiles, esta lleno de inútiles…
Estoy en un proyecto en un Ministerio, en donde me solicitan que haga un análisis funcional de un portal que es una auténtica locura para los usuarios.
Tan contento y recién acabado de un proyecto en CMMI me lanzo a hacer casos de uso, diagramas de flujo, diagramas de secuencia y muchos pantallazos, en un documento no muy técnico (pensaba yo). Nada de diseño técnico, de estructura de datos, de diagramas de clases ni cosas así complejas. Solamente qué hacia la aplicación y qué cosas por mejorar. Visio y Word a tope.
Pero, ay amigo, que como perro viejo ha sido fallo mío pensar que un funcionario pudiera tener el nivel técnico como para poder leer un diagrama de secuencia y enterarse de algo. Y, claro, me llegó la orden de rehacer el documento con “más pantallas” y “más detallado”.
Cayendo del burro me doy cuenta que tengo que bajar el nivel de explicación a nivel de cliente final y, ni corto ni perezoso, me hago un diagrama de navegación en PowerPoint. Es una presentación comercial que es como si alguien pulsara por ti el ratón. Pantallazao tras pantallazao y flechitas que indican el orden.Vamos algo que me daría vergüenza si alguien me lo enviara como análisis funcional porque me sentiría ofendido en mi corazoncito profesional.
Pues no. No solamente me dicen que está muy bien si no apostillan: "Ahora sí que el documento está reflejando la tramitación."
¡”•$!/(•”$)%%&(¡”&(“$•””(%/”•))!&!!!!!!
¿Y para hacer un PowerPoint la carrera, los casi 20 años de experiencia, los patrones, las buenas prácticas, el Agile y el tiempo delante de una pantalla?
Bueno, sigo con mi PowerPoint... :(
miércoles, 7 de octubre de 2009
100 posts!!
Y digo más de 100 veces porque se han quedado varios borradores en el tintero y dos o tres artículos que me he autocensurado por no ser constructivos.
Y ahora por el 102… :)
sábado, 3 de octubre de 2009
Aplicación Pomodoro en C# Mobile 6.5 – Hagamos sonar el tomate
Un pasito más. Vamos a hacer que cuando se pulse en el tomate, nos haga un ruidito. Para ello vamos a utilizar la clase SoundPlayer del namespace System.Media.
En la aplicación lo he echo un poquito más complejo para poder leer la configuración de sonidos también de el xml de configuracion, pero la forma rápida y sencilla es:
using System.Media;
SoundPlayer click = new SoundPlayer("\\Windows\\splat.wav");
click.Play();
Puesto en el evento de clik del tomate… ya suena!!
Aplicación Pomodoro en C# Mobile 6.5 – Construyendo el reloj
Bueno, como los requisitos son súper sencillos no voy a comerme mucho el tarro con esta pequeña práctica y voy a hacer una aplicación de una sola capa que tenga todo.
Por lo cual para el formulario voy a utilizar el logotipo de Pomodoro que es el siguiente:
Y a continuación los dos controles tipo label en donde voy a escribir la cuenta atrás y la fase en la que estoy. Por último, también tendré en cuenta los dos botones en la barra de menú inferior, quedando un formulario así:
La primera tarea que quiero hacer es todo el tema del cronometro, por lo cual me dejo la lectura de la configuración a un lado y directamente meto los parámetros en el constructor de la clase, eso sí lo dejo listo para más adelante hacer la clase de gestión de la configuración y que no tenga que modificar prácticamente nada.
Por ello también declaro una serie de constantes dentro de la propia clase. En vez de sacarlo a una estructura externa.
Para hacer el cronómetro me he apoyado en el control Timer de .NET, el cual indicándole un intervalo en milisegundos, me lanza un evento onTick en el cual le indico todo lo que tiene que ocurrir.
He creado un método pausa() que detiene y reinicia la cuenta atrás y visualiza los mensajes y los menús adecuados a cada fase.
Con cuidadin, ya que es una versión Beta inicial, aquí os dejo el código como está ahora mismo.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Media;
namespace Pomodoro
{
public partial class Pomodoro : Form
{
private int minutosDescansoLargo;
private int minutosDescansoCorto;
private int minutosTrabajo;
private int numIteracionesTrabajo;
public TimeSpan horario;
public int minutoActual;
public int minutoFin;
public int iteraciones;
/// <summary>
/// Nos indica si estamos en periodo de trabajo
/// </summary>
public bool trabajo;
/// <summary>
/// Nos indica si el reloj está iniciado
/// </summary>
public bool encendido;
/// <summary>
/// Repositorio temporal de mensajes
/// </summary>
public string mensajeTemporal;
/// <summary>
/// Objeto reproductor de sonidos
/// </summary>
sonido sonidos;
/// <summary>
/// Constantes de mensajes"
/// </summary>
public const string mensajeIniciar = "Iniciar";
public const string mensajePausa = "Pausa";
public const string mensajeContinuar = "Continuar";
public const string mensajeDescansoCorto = "Descanso breve";
public const string mensajeDescansoLargo = "Descanso largo";
public const string mensajeTrabaja = "Trabajando";
/// <summary>
/// Constructor del formulario
/// </summary>
public Pomodoro()
{
InitializeComponent();
sonidos = new sonido();
leeConfiguracion();
}
/// <summary>
/// Lee la configuración desde un fichero xml
/// </summary>
public void leeConfiguracion()
{
// Lee configuración del xml
// En desarrollo meto los valores a cañon.
minutosDescansoLargo = 15;
minutosDescansoCorto = 5;
minutosTrabajo = 25;
numIteracionesTrabajo = 4;
//Reinicio los valores
horario = TimeSpan.FromMinutes(minutosTrabajo);
iteraciones = numIteracionesTrabajo;
menuItem2.Text = mensajeIniciar;
lblMensaje.Text = string.Empty;
this.BackColor = Color.WhiteSmoke;
timer1.Interval = 1000; //Un segundo
encendido = false;
trabajo = true;
}
/// <summary>
/// Reloj. Gestiona los mensajes y los contadores de fases.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void timer1_Tick(object sender, EventArgs e)
{
lblReloj.Text = timeSpan2minutos(horario);
horario = horario - TimeSpan.FromSeconds(1);
// Si hemos llegado al final de la cuenta regresiva
if (horario.Minutes == 0 && horario.Seconds == 0)
{
// Si entramos en un periodo distinto del de trabajo
if (trabajo == true)
{
// Si entramos en un periodo de descansoCorto
if (iteraciones > 0)
{
iteraciones--;
horario = TimeSpan.FromMinutes(minutosDescansoCorto);
lblMensaje.Text = mensajeDescansoCorto;
}
else
{
iteraciones = numIteracionesTrabajo;
horario = TimeSpan.FromMinutes(minutosDescansoLargo);
lblMensaje.Text = mensajeDescansoLargo;
}
trabajo = false;
}
else
{
horario = TimeSpan.FromMinutes(minutosTrabajo);
trabajo = true;
lblMensaje.Text = mensajeTrabaja;
}
alarma();
}
}
/// <summary>
/// Pausa/continuar
/// </summary>
private void pausa()
{
lblReloj.Text = timeSpan2minutos(horario);
switch (menuItem2.Text)
{
// Ponemos el mensaje de trabaja
case mensajeIniciar:
lblMensaje.Text = mensajeTrabaja;
menuItem2.Text = mensajePausa;
break;
// Guardamos el mensaje de texto
// Y ponemos el mensaje de pausa
case mensajePausa:
mensajeTemporal = lblMensaje.Text;
lblMensaje.Text = mensajePausa;
menuItem2.Text = mensajeContinuar;
break;
// Recuperamos el mensaje de texto original
// Y lo visualizamos
case mensajeContinuar:
lblMensaje.Text = mensajeTemporal;
menuItem2.Text = mensajePausa;
break;
}
encendido = !encendido;
timer1.Enabled = encendido;
if (encendido == true)
{ this.BackColor = Color.WhiteSmoke; }
}
/// <summary>
/// Efecto de alarma y pausa el cronómetro.
/// </summary>
private void alarma()
{
this.BackColor = Color.YellowGreen;
pausa();
}
/// <summary>
/// Formatea el TimeSpan en minutos.
/// </summary>
/// <param name="horario">El TimeSpan a ser convertido a string</param>
/// <returns>Los minutos y segundos en formato "00:00"</returns>
private string timeSpan2minutos(TimeSpan horario)
{
return horario.Minutes.ToString("00") + ":" + horario.Seconds.ToString("00");
}
/// <summary>
/// Menú izquierdo
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void menuItem1_Click(object sender, EventArgs e)
{
leeConfiguracion();
lblReloj.Text = timeSpan2minutos(horario);
menuItem2.Text = mensajeIniciar;
lblMensaje.Text = mensajeIniciar;
timer1.Enabled = false;
}
/// <summary>
/// Menú derecho
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void menuItem2_Click(object sender, EventArgs e)
{
pausa();
}
/// <summary>
/// Imágen del tomate
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void pictureBox1_Click(object sender, EventArgs e)
{
//DrawString();
sonidos.click.Play();
pausa();
}
/// <summary>
/// Botón de salir
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void bSalir_Click(object sender, EventArgs e)
{
Application.Exit();
}
}
/// <summary>
/// Clase que inicializa los sonidos utilizados en la aplicación.
/// </summary>
public class sonido
{
public SoundPlayer click = new SoundPlayer("\\Windows\\splat.wav");
public sonido()
{
click.Play();
}
}
}
¿Lo siguiente?
viernes, 2 de octubre de 2009
Aplicación Pomodoro en C# Mobile 6.5 - Instalación del entorno de desarrollo.
Paso 1. Desinstalar el Mobile 6.0 Sdk si lo tuviéramos instalado, como me pasó a mí.
Paso 2. Descargarse e instalar:
- Windows Mobile 6 Professional and Standard Software Development Kits Refresh.
- Windows Mobile 6.5 Developer Tool Kit.
- XP: Active Sync 4.5
- Vista o Win7: Centro de dispositivos de Windows Mobile 6.1 para Windows Vista (32-bits)
*NOTA: Las descargas debieran ser todas en el mismo idioma. O en inglés o en español. Yo me he bajado las versiones en ambos idiomas. Hago referencias a las versiones de 32bits, pero existen para las versiones de 64bits.
Las demás descargas que se leen en el blog de Wade Wegner no son necesarias en este punto, pero yo me las he bajado e instalado igualmente.
Ahora si, podemos crear nuestro proyecto C# para Windows Mobile 6.0 en resolución VGA.
Agradecimientos:
Aplicación Pomodoro en C# Mobile 6.5
Pero, para empezar a hincar el diente he decidido hacer una pequeña aplicación que me haga un reloj Pomodoro. Vamos un cronometro de cocina con pequeñas variaciones para utilizarlo con la técnica antes descrita.
Requisitos iniciales:
- El reloj debe de contar por minutos de forma regresiva. Y se debe ver.
- En cualquier momento puedo detener la cuenta atrás.
- En cualquier momento puedo reiniciar el reloj.
- Los periodos a contar son:
o Periodo de pausa (5 minutos)
o Periodo de descanso (15 minutos)
o Iteraciones trabajo/pausa hasta el periodo de descanso (4)
- Efecto sonoro de cambio de periodo (3), pausa y reinicio.
- Efecto visual de cambio de periodo (3), pausa y reinicio.
- Las acciones de pausa y reinicio deben ser poder realizadas pulsando sobre el tomate y sobre el menú.
- Efectos visuales y sonoros de las acciones sobre el tomate.
- Gestor de configuración. Editar el xml de configuración.
- Integrar con la hoja de Inventario de actividades y el To Do Today.
- Utilizar remeber the milk o servicios similares en la nube.
- Integrarse con el Task de Outlook Mobile.
- Multi idioma
- Efectos visuales el tomate en DirectX (funcionamiento igual que uno de verdad)
Manos a la obra y empecemos…
jueves, 1 de octubre de 2009
Reunión Agile-Madrid 30/09/09
Estoy de Gallardón y sus obras hasta las narices..,
Pasando por encima de la acera, entre zanjas abiertas y vallas amarillas, llegué a la sede de 11870 a mi primera reunión del grupo Agile de Madrid. Con la ilusión de conocer a José María y a más gente “rarita” con esto del agilísimo.
Mi primera sorpresa es la oficina de 11870 que tienen un aire a buen rollito y a diseño gráfico que me recuerda viejos y buenos tiempos en Mc Erikson.
La gente fue llegando poco a poco, pero al final nos juntamos un grupo realmente grande y diverso. Gente maja y con ganas de escuchar, de aprender y de colaborar.
En cuanto llegó José Manuél Beas nos pusimos a cocinar una retrospectiva y Ángel Medinilla demostró el porqué es un gurú en el mundo Agile en España al hacer un coaching muy bueno a José Manuél que hacía las veces de facilitador.
El grupo fue bastante interactivo e, increíblemente, muy disciplinado con los timebox (caja de tiempo). Obteniéndose al final conclusiones claras y concisas que se podrán leer en el foro de Agile-Spain.
A partir de ese momento entramos en un coloquio con Ángel (lo que habla el Horda este… ;D) que empezó frio y acabo como tienen que acabar estas cosas… delante de unas cervecitas.
Flores (como nos enseñó Angel) para Agustín Yagüe, que ya hubiera querido de profesor cuando hice la carrera , por supuesto para José M. y para Angel
Resumen: me muero de ganas de ir a la siguiente reunión y al Open. GRACIAS!! – óiganse aplausos -