viernes, 8 de agosto de 2014

Automatizar TortoiseSVN con fichero por lotes

Si necesitamos automatizar ciertas tareas en cada commit/update de nuestro proyecto gestionado con TortoiseSVN en windows podemos realizar estos sencillos ficheros por lotes .bat para simplificar la tarea.
Dejo aquí dos ejemplos básicos que he visto en este blog en inglés.

Ejemplo para Commit:
@echo off
echo.
echo. [ SVN Committer ]
:: The two lines below should be changed to suit your system.
set SOURCE=C:\Users\Administrador\Desktop\repoCodesk
set SVN=C:\Program Files\TortoiseSVN\bin
echo.
echo. Committing %SOURCE% to SVN...
"%SVN%\TortoiseProc.exe" /command:commit /path:"%SOURCE%" /closeonend:0
echo. done.
echo.
echo. Operation complete.
Ejemplo para Update:
@echo off
echo.
echo. [ SVN Updater ]
set SOURCE=C:\Users\Administrador\Desktop\repoCodesk
set SVN=C:\Program Files\TortoiseSVN\bin
:: The SOURCEj below should be already set to fit your system.
echo. Updating %SOURCE%\ from SVN...
"%SVN%\TortoiseProc.exe" /command:update /path:"%SOURCE%\" /closeonend:2
echo.        done.

Nota:  Utilizamos el parámetro closeonend según nuestras necesidad. En el caso del Commit mostramos el diálogo de selección de ficheros, para el update en este caso lo omitimos.

viernes, 22 de noviembre de 2013

Diez cosas que todo programador debería saber

Muchos pensamos que es importante adoptar buenas prácticas de programación, quien no opina así estará condenado a cometer los mismos errores que ya se han cometido una y otra vez.  
Hoy he encontrado una buena ración de sentido común y experiencia en esta página: 97 cosas que todo programador debería saber, a parte de recomendar su lectura voy a hacer un ejercicio de reflexión y voy a recopilar aquí las 10 que más me hayan llamado la atención:

  1. Aprende a hacer estimaciones.
    El eterno handycap del programador.
  2. Averigua qué haría el usuario (tú no eres un usuario).Hay que hacer un gran esfuerzo en este sentido.
  3. La belleza está en la simplicidad.
    Esta máxima siempre presente.
  4. Comenta sólo lo que el código no dice.
    Hay quien no comenta y hay quien comenta más de la cuenta (confieso que soy de los segundos). Comentar es importante, pero lo justo y necesario.
  5. El diseño del código sí importa.
    Es vital para su mantenimiento, calidad y trabajo en grupo.
  6. Dos cabezas son a menudo mejor que una. No seas un lobo solitario.
  7. Escribe código como si tuvieras que mantenerlo el resto de tu vida. Sencillamente me ha gustado esta frase, tenerla en cuenta más a menudo nos ahorraría muchas chapuzas rápidas.
  8. Mejora código quitándolo.
    Como dice la frase "Algo es perfecto cuando ya no se le puede quitar nada".
  9. Haz pruebas mientras duermes, incluso los fines de semana. Pruebas, pruebas y más pruebas... y si no sabes qué hacer, haz más pruebas.
  10. Suelta el ratón y aléjate del teclado. Excelente consejo, si estás bloqueado coge bolígrafo y papel, ponte música, piensa de otra manera, busca otro enfoque, no todo se hace con teclado.

Por supuesto hay otras muy interesantes, algunas más obvias y otras no tanto.  Lo más importante, siempre, la actitud de constante aprendizaje.

lunes, 25 de marzo de 2013

A la caza de leaks en Embarcadero C++


Los desarrolladores que utilizamos Codegear RAD Studio no disponemos de tantas herramientas como nos gustaría, la mayor parte de éstas están orientadas a VisualStudio.
Recientemente he necesitado realizar tareas de debug intensivo en una aplicación servidor debido a la existencia de varios leaks de memoria difíciles de encontrar.  Hasta la fecha me había bastado con el socorrido CodeGuard que viene de serie con el IDE, pero al parecer esta herramienta tan sólo puede encontrar ciertos tipos concretos de fugas, inicializaciones erróneas o acceso a objetos de memoria inválidos.

En mi búsqueda de herramientas alternativas he topado con un código que puede ser de utilidad, lo he probado y funcionar funciona (aunque todavía no he hecho pruebas intensivas). Es una adaptación de la herramienta IMallocSpy escrita originalmente para MSVC, que encontré en este blog adaptada a BCB. He tenido que arreglar alguna función para que compilara. Aquí os la dejo, esperando que sea de utilidad y os ahorre algún  quebradero de cabeza. Estos son los pasos:

1) Necesitamos descargar los archivos stdafx.cpp y leaker.cpp de esta dirección: http://comcorba.tripod.com/comleaks.htm

2) Crea la unidad IMallocSpyUnit.h con el siguiente contenido:

#ifndef IMallocSpyUnit
#ifndef IMallocSpyUnit
#define IMallocSpyUnit

// IMallocSpyUnit.h
class CMallocSpy : public IMallocSpy
{
 public:
 CMallocSpy(void);
 ~CMallocSpy(void);
 virtual HRESULT STDMETHODCALLTYPE QueryInterface();
 virtual ULONG STDMETHODCALLTYPE AddRef( void);
 virtual ULONG STDMETHODCALLTYPE Release( void);

 // IMallocSpy methods
 virtual SIZE_T STDMETHODCALLTYPE PreAlloc(
 /* [in] */ SIZE_T cbRequest);
 virtual void *STDMETHODCALLTYPE PostAlloc(
 /* [in] */ void *pActual);
 virtual void *STDMETHODCALLTYPE PreFree(
 /* [in] */ void *pRequest,
 /* [in] */ BOOL fSpyed);
 virtual void STDMETHODCALLTYPE PostFree(
 /* [in] */ BOOL fSpyed);
 virtual SIZE_T STDMETHODCALLTYPE PreRealloc(
 /* [in] */ void *pRequest,
 /* [in] */ SIZE_T cbRequest,
 /* [out] */ void **ppNewRequest,
 /* [in] */ BOOL fSpyed);
 virtual void *STDMETHODCALLTYPE PostRealloc(
 /* [in] */ void *pActual,
 /* [in] */ BOOL fSpyed);
 virtual void *STDMETHODCALLTYPE PreGetSize(
 /* [in] */ void *pRequest,
 /* [in] */ BOOL fSpyed);
 virtual SIZE_T STDMETHODCALLTYPE PostGetSize(
 /* [in] */ SIZE_T cbActual,
 /* [in] */ BOOL fSpyed);
 virtual void *STDMETHODCALLTYPE PreDidAlloc(
 /* [in] */ void *pRequest,
 /* [in] */ BOOL fSpyed);
 virtual int STDMETHODCALLTYPE PostDidAlloc(
 /* [in] */ void *pRequest,
 /* [in] */ BOOL fSpyed,
 /* [in] */ int fActual)
 virtual void STDMETHODCALLTYPE PreHeapMinimize( void);
 virtual void STDMETHODCALLTYPE PostHeapMinimize( void);

 void Clear();
 void Dump();
 void SetBreakAlloc(int allocNum);

 protected:
 enum
 {
   HEADERSIZE = 4,
   MAX_ALLOCATIONS = 100000 // cannot handle more than max
 };

 ULONG m_cRef;
 ULONG m_cbRequest;
 int m_counter;
 int m_breakAlloc;
 char *m_map;
 size_t m_mapSize;
};

#endif
  
3) Añade este código donde quieras debuguear en busca de leaks:
 typedef void WINAPI (*SETOANOCACHE)();
 HINSTANCE hDLL = LoadLibrary(L"oleaut32.dll");
 if(!hDLL) throw Exception("Unable to load oleaut32.dll");
 SETOANOCACHE SetOaNoCachePtr = (SETOANOCACHE) GetProcAddress(hDLL,"SetOaNoCache");
 if (!SetOaNoCachePtr) throw Exception("Unable to get SetOaNoCache");
 SetOaNoCachePtr();
 // Initialize COM.
 ::CoInitialize(NULL);
 // Initialize the COM memory checker …
 CMallocSpy* pMallocSpy = new CMallocSpy;
 pMallocSpy->AddRef();
 ::CoRegisterMallocSpy(pMallocSpy);
 pMallocSpy->Clear();
 test_com_allocs(); // CAMBIA ESTO POR LA FUNCIÓN A TESTEAR
 pMallocSpy->Dump();
 ::CoRevokeMallocSpy();
 pMallocSpy->Release();
 ::CoUninitialize();
Si se da algún leak en el código contenido por la función de ejemplo "test_com_allocs()" nos aparecerá el aviso en el output del IDE.

viernes, 16 de noviembre de 2012

Migrar de Indy9 a Indy10 en Codegear C++

Hace algunos años que utilizo este componentse desde que empecé a trabajar con el viejo Borland C++ Builder ( Indy8 ). El problema es que, cuando quieres actualizarte a Indy10, te encuentras con que en esa versión han reorganizado la mayoría de las clases y han reescrito parte de los interfaces… además la documentación clara escasea y más aún los ejemplos en C++.

En mis periplos para traducir clientes y servidores escritos en Indy9 tuve que consultar gran variedad de foros y recursos on-line, pero hubo uno que me resultó especialmente útil ya que enumeraba los principales cambios de una versión a otra.

Por si resulta de utilidad a alguien, dejo aquí el  resumen de diferencias principales:

  • POP3->MaxLineLength  ahora es Pop->IOHandler->MaxLineLength 
  • wsOK movido, ahora se usa IdIMap4  
  • Pop3.Connect(Timeout) se divide en dos nuevos comandos ( ya no permite indicar timeout en el constructor ), ahora se usa Pop3->ConnectTimeout = TimeOut; y Pop3->Connect() 
  • StoredPathName desaparece, camgiado TIdAttachment to TIdAttachmentFile
  • POP->Capture(Dest) ahora es POP->IOHandler->Capture(Dest) 
  • Parámetros de OnWork y OnProcessWork cambiados, cambiado el parámetro const int a int64 ( no const)
  • EIDSocketError desaparece , usar IdStack 
  • CommaSepaeratedToStringList desaparece, ahora se usa IdGlobalProtocols
  • TIdText desaparece, añadido IdText
  •  Dentro de TIdTCPServer los eventos OnConnect y OnExecute cambian sus parámetros TIdPeerThread a TIdContext ( un concepto distinto )

Quien quiera puede leer el artículo original aquí ( he añadido algúa nota que no aparecía en él ): Artículo original ( en inglés )


viernes, 14 de septiembre de 2012

Supresión de errores en PHP empeora el rendimiento

Cualquier desarrollador PHP sabe que el rendimiento no es el punto fuerte e este lenguaje, no obstante la comunidad ha ido aportando grandes mejoras versión tras versión ( precompilado, optimización, etc ).

No es cuestión de derrochar recursos porque sí... es bueno estar abiertos a esos pequeños tips que nos enseñan con poco esfuerzo a ahorrar preciosos ciclos de reloj que en un proyecto grande pueden significar la diferencia entre algo razonable y algo insoportable.

Y he aquí la curiosidad: el magnífico sistema de supresión de errores en PHP ( incluir una arroba "@" antes de la instrucción que se desea silenciar )  es un auténtico caníbal silencioso de CPUs.  En algunos artículos acusan a esta directiva de provocar hasta un 40% de retardo adicional.

En este otro enlace muestran una sencilla prueba de 10.000 iteraciones con y sin prefijo "@", el resultado parece muy claro, hasta 10 veces más lento:


0.010571002960205 microsegundos con supresión de errores ( @instrucción )
0.002446174621582 microsegundos en ejecución normal

Desde que conozco esta información, como es de esperar, he eliminado la supresión de errores de mis algoritmos, no he percibido la diferencia de forma subjetiva, pero no pongo en duda lo que parece claro.

Y ahora queda una duda ¿qué hacemos con los posibles errores que pueden surgir si no hacemos uso de la supresión de errores?. Creo que sólo hay una respuesta... aplicar un control de errores más estricto prestando especial atención a las excepciones inesperadas en instrucciones básicas. Las buenas prácticas lo requieren.

martes, 26 de junio de 2012

Cuidado con las contraseñas


El otro día un compañero me pasó este enlace a una aplicación que busca hashes MD5 en varias bases de datos. Ya había visto sistemas de este tipo, pero la verdad es que esta vez me impresionó por la cantidad de cadenas que indexa (me desveló combinaciones como m00nwalker ,marta16 ó enunlugardelamancha ).

Si alguien consiguiera extraer miles de passwords de algún portal o red social (como ocurrió hace poco en linkedin) y los procesara con una herramienta de este calibre ( o más potentes, algo probable en el futuro) seguro que podría desenmascarar entre el 10% y el 20% de las claves, y eso son muchos fraudes en potencia.

¿Qué podemos hacer para que nuestros datos estén a salvo? Yo recomendaría al menos seguir estas sencillas buenas costumbres:

  • Usar claves distintas para cada web (o al menos distinguir entre dos o tres distintas), así si nos roban una clave no podrán acceder a todas nuestras cuentas.
  • Combinar mayúsculas, minúsculas y números intentando usar algún truco mnemotécnico para no olvidarla, pero no ser muy evidentes ( por ejemplo pEPit000, 30m30NA, etc... )
  • Si el sistema lo permite, añadir símbolos ( "_" "-" "@" )
  • Cambiar las claves cada cierto tiempo es una excelente costumbre.
  • Destruir cookies al cerrar una sesión, sobre todo usando un ordenador público o una conexión WIFI poco segura.
Muchas de estas medidas pueden parecer incómodas, pero es muy sencillo de cumplir y nos puede evitar más de un dolor de cabeza.  La verdad es que como desarrollador he comprobado por mí mismo la cantidad de usuarios que utilizan claves del tipo "micasa" ó "123456" quedando totalmente expuestos al primer hackercillo de fin de semana. Estas claves son el equivalente a guardar la llave del coche en el parabrisas o la de casa debajo del felpudo.


Url del buscador MD5:
http://www.tmto.org/pages/passwordtools/hashcracker

miércoles, 9 de mayo de 2012

Usar servidor proxy para cambiar ip externa


Si desarrollas aplicaciones cliente-servidor necesitarás realizar pruebas emulando un entorno real... En la realidad el cliente debería estar en una parte del mundo lejana al servidor.
Cuando hacemos pruebas con el servidor y el cliente en la misma red local, incluso aunque usemos la Ip externa, el router nos redireccionará por red interna de forma transparente, y eso tirará por tierra nuestro intento de emular ese entorno real.

Para solucionarlo podemos usar Proxifier, una excelente aplicación que permite conectar con cualquier servidor proxy y así salir con otra IP ( excelente también para quien quiera, por ejemplo, navegar de forma anónima ).


- Descarga e instala la aplicación (click aquí ).

- Busca una lista de servidores proxy gratuítos

- Ejecuta el programa y ve a Profile > Proxy Servers

- Añade ahí el servidor que prefieras.


Así de fácil estaremos conectados mediante el proxy remoto y tendremos una IP pública distinta, pudiendo probar nuestras aplicaciones en un entorno parecido al real.