Mostrando entradas con la etiqueta programacion. Mostrar todas las entradas
Mostrando entradas con la etiqueta programacion. Mostrar todas las entradas

Que difíciles hacemos las cosas

Hay que ver que difíciles hacemos las cosas algunas veces.
Por ejemplo, me encuentro el siguiente código donde hay que buscar un fichero en distintos dispositivos:

if( existIn(A) )
{
...
}
else if( existIn(B) )
{
....
}

Tenía que hacer la comprobación en más dispositivos y me disponía a meter más else if. Menos mal que he pensado un poco antes de hacerlo
Al final me ha quedado:

const int devices[4] = { deviceA, deviceB, deviceC, deviceD };
for( int n = 0; n < 0; ++n )
{
if( existIn(device[n]) )
{
...
break;
}
}

Si hubiese hecho esto desde primera hora, hubiese sido mucho más fácil la modificación. Parece una tontería, pero ahora podemos cambiar el orden de búsqueda, añadir nuevos dispositivos,... con mayor facilidad.
Queda mucho más elegante.

Minimizar una aplicacion cuando otra es minimizada

Lo que necesito hacer es minimizar una aplicación escrita en C# cuando otra aplicación es minimizada.
Buscando información me topé con los HOOKS (ganchos). Con un hook se pueden procesar los mensajes que envían otras aplicaciones antes de que dichas aplicaciones respondan al mensaje. Es un rutina que se instala en el sistema y supervisa el tráfico de mensajes del sistema.
Hay 3 tipos de hook:
System hook: Intercepta mensajes del sistema.
Local system hook: Intercepta mensajes de un thread.
Global system hook: Intercepta mensajes de cualquier aplicación del sistema.

Con C# no es posible crear los gobal hooks. Se pueden crear, pero se necesita una dll en C++ que tendrá la función para procesar los mensajes.

Enlaces interesantes:
http://www.codeproject.com/csharp/globalsystemhook.asp
http://msdn.microsoft.com/msdnmag/issues/02/10/cuttingedge/
http://www.dotnetinterop.com/samples.aspx

Control de Versiones: Etiquedas y Ramas

Las ramas y las etiquetas pueden tener muchos usos y por eso se puede hacer complicado su uso.

Las etiquetas se usan para marcar el proyecto cuando está en un determinado estado.
Las ramas representan una bifurcación en la historia del proyecto.

Deberíamos usar una rama cuando lanzamos una versión del producto o por ejemplo cuando vamos a implementar funciones experimentales. Cada release brach puede tener varias releases o puntos donde la aplicación fue puesta a disposición del cliente. Estos puntos de marcan con las etiquetas.

Los bugs se fijan en la release branch correspondiente y el cambio se fusiona en las restantes ramas. Si el bug es complicado se puede crear una rama y luego fusionarla con las restantes ramas. Nota: El programa SourceOfSite no dispone de opciones para fusionar ramas.
Se usan etiquetas para marcar el comienzo y el final del bugfixing.

Para decidir si necesitamos una rama tenemos que pensar que esa rama deberá ser mantenida, es decir, que habrá que modificar algún fichero y fusionarla con las otras ramas en un futuro. Si no se va a mantener una rama es mejor usar una etiqueta. Tampoco es buena idea crear una rama para una modificación especifica de la aplicación para un determinado cliente. Esto habría que hacerlo la propia aplicación.

Control de Versiones

¿Qué es?
Es un software que facilita el trabajo de un programador.
  • Se podría considerar como el deshacer de un editor de textos pero para el código fuente.
  • Permite a múltiples programadores trabajar sobre el mismo código de manera controlada.
  • Mantiene un registro de los cambios realizados.
  • Permite llevar múltiples versiones del código mientras se continua trabajando sobre dicho código.

¿Qué se debería guardar?
Para saber que debemos guardar en el repositorio haz la siguiente pregunta: ¿Si no tengo una versión actualizada de x, ¿podría compilar, probar y distribuir la aplicación? Si la respuesta es no, entonces x debe guardarse en el repositorio.

Además de los ficheros anteriores, también se debe guardar cualquier cosa que ayude a entender la aplicación, ya sea documentación interna o externa, el texto de los correos electrónicos que hayan sido importantes en el desarrollo de la aplicación, información,....

No se deben guardar los ficheros que se pueden generar con ficheros ya existentes, por ejemplo: la documentación que generamos mediante la documentación incluida en el código fuente usando herramientas auxiliares.

Tags - Etiquetas
Es un nombre que se asigna a un conjunto de ficheros en un estado determinado del proyecto. De este modo podemos recuperar esos ficheros tal y como estaban en ese momento.

Branches - Ramas.
Se llama Trunk a la rama principal del código donde se trabaja normalmente. Es decir, los ficheros del repositorio donde hacemos los cambios diariamente.
Pero, si estamos próximos al lanzamiento de la aplicación, no podemos añadir más funcionalidad pues esa funcionalidad será para una futura versión, y seguramente no estará termianda para el lanzamiento de la aplicación. Entonces, lo que podemos hacer es crear una rama que contendrá el código fuente para una determinada versión de la aplicación. Es lo que se conoce como release branch.

Cuando creamos una rama tenemos 2 proyectos con un futuro distinto para cada uno de ellos. De esta manera tenemos el código de la aplicación que vamos a lanzar y el de la futura versión perfectamente diferenciados.
Si después del lanzamiento de la aplicación se encuentran fallos se corregirán en la rama correspondiente, así podemos generar la misma versión con los fallos corregidos, y esos cambios para reparar el bugs en la release branch se fusionan con la rama principal o trunk branch.

En general, un proyecto tendrá una rama principal (trunk), y por cada lanzamiento podemos añadir otra rama (release branch). Una release branch no cambia mucho durante su vida, sólo para corregir los fallos que se puedan encontrar.

Los cambios significativos en la vida de un proyecto se marcan amenudo con etiquetas. Una etiqueta podría contener el código usado para lanzar una determinada versión de la aplicación.

Merging - Fusionando.
Esos cambios se deben añadir también a la rama principal para que estén corregidos en la próxima versión.
Se pueden fusionar los cambios hechos para fijar el error en la rama correspondiente con la rama de la siguiente versión sin usar el copiar y pegar.
Mantener el código entre las distintas ramas puede ser complicado, por eso es recomendable no tener muchas ramas.

Logs
Cuando un fichero es modificado y puesto en el repositorio se puede añadir una nota. En esa nota no se explica el cambio realizado, ya que este se puede obtener al ver las diferencias entre los ficheros. Lo que debemos poner en el log es el por que se ha realizado el cambio. Si el cambio es para fijar un bug se debe poner la identidad del bug en la aplicación que usemos para llevar el control de errores.

InvokeRequired

Ya se que cuando queremos actualizar un formulario o control desde un thread distinto al que creo el control hay que usar el método Invoke o BeginInvoke pasandole un delegado a ejecutar.

Para no tener que definir el delegado podemos usar los metodos anónimos.


if( this.InvokeRequired )
{
this.Invoke( (System.Threading.ParameterizedThreadStart)delegate( object o )
{ UpdateProgressBar( current ); } , current );
}


o este si no necesitamos pasar parámetros


if( InvokeRequired )
{
this.Invoke( (MethodInvoker)delegate() { StopTest(); } );
}

Comparar doubles

Para comparar dos float o doubles deberíamos hacer:


float myNumber;
float yourNumber;

if( fabs (myNumber - yourNumber) < 0.00001 )
printf("They are close enough") ;

C++ Contar los dígitos de un número

Código para contar los dígitos de un número entero: Fuente

#include <cmath>
#include <limits>

// log10(x) == (n - 1) digits
// (1 + n + fff) == number of digits
// fff == floating-point fudge factor
int digits(int number)
{
// Avoid doing work if number is 0
if (number != 0)
{
double lg = std::log10(static_cast<double>(std::abs(number)));
double eps = std::numeric_limits<double>::epsilon();
return static_cast<int>(1 + lg + eps);
}
else
return 1;
}

// Count until 0 and chop of every tenth
int digits2(int num)
{
// Avoid doing work if number is 0
if (num != 0)
{
int n = 0;

while (num > 0)
{
++n;
num /= 10;
}

return n;
}
else
return 1;
}

C++ Autoincremento de nombre

Función para incrementar un nombre de algo añadiendole números. Útil cuando es necesario un nombre único.

void IncName( StringC& strName, int nCount, int nMaxChars )
{
int nCountDigit = 1;
while( (nCount / pow(10.0,nCountDigit)) >= 1.0 )
{
nCountDigit++;
}

StringC strFormat;
strFormat.Format( L"%%s_%d", nCount );

strName.Format( strFormat, (const wchar_t*)strName.Mid( 0, nMaxChars-nCountDigit-1 ) );
}
¡Se puede mejorar haciendo uso de las funciones de la siguiente entrada!

Esta función fue usada en SOA_SetOfAngles para ponerle nombre a la lista de puntos.
Una versión fue usada en DXF2LandXml para ponerle nombre a los puntos repetidos.

C# Generics y Find

Para buscar en una lista genérica en C# un elemento que cumpla una determinada condición existe la función:
public T Find Predicate match

Para realizar una búsqueda usando Find en una sola línea de código podemos usar los Métodos Anónimos incluidos en .NET 2.0. Los métodos anónimos permiten asociar código a los objetos delegados directamente.

Así, para buscar un valor dentro de una lista con Find podremos hacer por ejemplo:

int result = CgPointCollection.Find(
delegate( XmlCgPoint point ) { return point.Name == nameToFind; } );