October 2007 - Artículos

La empresa para la que trabajo (Informática El Corte Inglés) va a participar como patrocinador Oro en la III Conferencia de Usuarios de Sharepoint, que se celebrará el 30 de octubre en el Hotel Meliá Castilla, sito en la calle Capitán Haya, 43, en Madrid.

En esta conferencia se hará una presentación de un proyecto bastante interesante, con el que se ha alcanzado la certificación oficial "AA" de Accesibilidad.

Podéis consultar la agenda del evento aquí:

http://www.microsoft.com/spain/office/ceus/agenda/default.mspx

Y podéis inscribiros aquí:

http://www.microsoft.com/spain/office/ceus/default.mspx

Saludos!

Hola a todos!

Como ya he comentado en otra ocasión, estoy usando el Visual C++ 2005 Express para desarrollar un jueguecillo con OpenGL y SDL. Cuando empecé, lo estaba desarrollando con el Visual C++ 2003, pero me comentaron que la STL había mejorado en la versión 2005, y como había una versión gratuita, decidí actualizarme.

El caso es que el otro día decidí liberar una alpha para los betatesters. Y de repente algunos (no todos) me comentaron que no funcionaba. Que les daba el siguiente error:

No se pudo iniciar la aplicacion porque su configuracion es incorrecta. Reinstalar la aplicacion puede solucionar el problema.

Hmmm... Al principio pensé que debía haber algún problema con mi código. Así que empece a meter trazas y pedir logs. Tras comentarme los betatesters que no había ningún log, me di cuenta de que la aplicación, como dice el error claramente, no llegaba a iniciarse. ^_^U

Entonces me di cuenta de un pequeño detalle. El runtime de C de esta versión de C++ probablemente no lo tenían todos los usuarios. Googleando un poco, ví que los betatesters se podían instalar el paquete de distribución del runtime de C++... Pero me pareció que iba a ser un rollo para ellos tener que andar instalando nada para probar una alpha.

¿Qué hago? Si no quiero que se instalen el paquete de distribución, tampoco me voy a poner a generar un msi con la alpha del juego. Habría sido la mejor solución, pero generalmente la gente prefiere descomprimir el archivo, y ejecutar directamente, sobre todo cuando algo es no definitivo...

Finalmente, encontré la solución en los foros de microsoft. La traduzco a continuación:

1) En la máquina en la que tienes instalado Visual C++ Express, crea la siguiente carpeta y subcarpetas colgando de %PROGRAMFILES%\Microsoft Visual Studio 8\VC

redist\x86\Microsoft.VC80.CRT

2) Copia msvcr80.dll, msvcp80.dll, msvcm80.dll de:

%WINDIR%\winsxs\x86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_8.0.50727.42_x-ww_0de06acd

a:

%PROGRAMFILES%\Microsoft Visual Studio 8\VC\redist\x86\Microsoft.VC80.CRT

3) En la carpeta Microsoft.VC80.CRT, crea un nuevo fichero llamado:

Microsoft.VC80.CRT.manifest

4) Dicho fichero deberá tener el siguiente contenido:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- Copyright © 1981-2001 Microsoft Corporation -->
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <noInheritable/>
  <assemblyIdentity
      type="win32"
      name="Microsoft.VC80.CRT"
      version="8.0.50608.0"
      processorArchitecture="x86"
      publicKeyToken="1fc8b3b9a1e18e3b"
    />
  <file name="msvcr80.dll"/>
  <file name="msvcp80.dll"/>
  <file name="msvcm80.dll"/>
</assembly>

Con esto hemos creado un nuevo directorio en tu instalación de Visual C++ Express que puede ser reutilizado siempre que lo necesites.

Para distribuir estos ficheros, simplemente copia la carpeta Microsoft.VC80.CRT en la carpeta de tu programa. Y eso es todo. Así que, por ejemplo, si el ejecutable de tu aplicación está en la ruta:

%PROGRAMFILES%\MiAplicación

tendrás una carpeta llamada:

%PROGRAMFILES%\MiAplicación\Microsoft.VC80.CRT

que contendrá los cuatro ficheros mencionados anteriormente (3 DLLs, y el manifiesto que has creado a mano).

No hace falta instalar nada más. Simplemente arranca tu aplicación, y se ejecutará sin problemas. No hace falta ninguna instalación específica. Simplemente basta con que tu programa de instalación cree esa subcarpeta junto con el resto de archivos que tenga tu aplicación.

NOTA:

%WINDIR% es el directorio en el que está instalado Windows. Es una variable que se puede utilizar en el cmd.exe. Normalmente es C:\WINDOWS

%PROGRAMFILES% es similar, salvo que apunta a la carpeta Archivos de Programa. Lo bueno es que es independiente de idioma.

Saludos!

No os llevéis a confusión con el título... Este artículo no es más que un mini-tutorial sobre la clase System.IO.Compression.GZipStream, que nos proporciona la funcionalidad necesaria para comprimir datos utilizando el estándar "de facto" gzip.

La verdad es que el uso de esta clase no debería ser complicado, ya que básicamente lo que hacemos es leer y escribir datos de un stream, como si fuese un fichero o un trozo de memoria más. Pero tiene una pequeña particularidad: Para que funcione correctamente nuestro código tenemos que tener cuidado de indicar en el constructor que queremos que el stream subyacente a nuestro GZipStream se quede abierto cuando terminemos de utilizarlo. Sobre todo cuando lo que queremos es comprimir en memoria, para posteriormente, sin crear ficheros temporales en el disco duro, enviarlo por red.

Veamos el ejemplo, sencillo, sencillo:

Para comprimir:

   Dim memStream As New System.IO.MemoryStream
   ' Aquí está el quid de la cuestión: Indicarle en el tercer parámetro
   ' que cuando cierre el stream de compresión, no elimine el stream
   ' subyacente.
   Dim gzip As New System.IO.Compression.GZipStream(memStream, _
                   IO.Compression.CompressionMode.Compress, True)
   Dim fileBytes() As Byte
   Dim compressedFileBytes() As Byte = {}
 
   ' Leemos el contenido del fichero a comprimir
   fileBytes = System.IO.File.ReadAllBytes(filePath)
   ' Escribimos en el stream compresor
   gzip.Write(fileBytes, 0, fileBytes.Length)
   ' Si no cerramos el stream, no podremos leer correctamente el 
   ' resultado de la compresión.
   gzip.Close()
 
   ' Vamos a leer los datos comprimidos
   Array.Resize(compressedFileBytes, memStream.Position)
   ' Colocamos el stream de memoria al inicio, para leer todo.
   memStream.Position = 0
   ' Ya tenemos todos los datos en el array compressedFileBytes.
   memStream.Read(compressedFileBytes, 0, compressedFileBytes.Length)
 
   ' Hacer lo que queramos con los bytes comprimidos...
 
   ' Y finalmente, limpiar un poquito.
   memStream.Close()
   gzip.Dispose()

Para descomprimir:

  ' fileBytes es un array de bytes que contiene el fichero comprimido
  Dim memStream As New System.IO.MemoryStream(fileBytes)
  ' Creamos el GZipStream basándonos en el stream de memoria.
  Dim gzip As New System.IO.Compression.GZipStream(memStream, _
                   IO.Compression.CompressionMode.Decompress)
  ' Si sabemos a priori el tamaño del fichero sin comprimir, 
  ' inicializamos el array de bytes que contendrá el fichero
  ' descomprimido.
  Dim realFileBytes(fileSize - 1) As Byte
 
  memStream.Position = 0
  
  ' Leemos el fichero.
  gzip.Read(realFileBytes, 0, fileSize)
  ' Cerramos...
  gzip.Close()
  gzip.Dispose()
 
  ' Usamos el fichero para lo que queramos, está en el memoryStream...
 
  ' Cerramos el MemoryStream.
  memStream.Close()

Saludos!

Publicado 15/10/2007 14:00 por Augusto Ruiz | 1 comment(s)
Archivado en:

Iba a poner "para redimensionar imágenes", pero realmente no es eso lo que hace. Lo interesante de esta técnica es que cuando reduces la imagen, lo que hace es eliminar la parte de la imagen que no nos proporciona información interesante. Y funciona bastante bien.

A esta técnica la llaman "Seam Carving".

Un vídeo de demostración de esta técnica que podéis ver en YouTube:

Uno de los impulsos más difíciles de reprimir para un programador es el de ver un código antiguo, de esos que los años han ido degradando, y no caer en la tentación de rehacer esa funcionalidad que se nota que tiene ñapa sobre ñapa, que se hace de manera ineficiente, que tiene cincuenta mil ifs anidados...

Por otra parte, cada cierto tiempo, las empresas se plantean realizar migraciones de aplicaciones antiguas a una tecnología más nueva. Los motivos esgrimidos suelen ser aprovechar una infraestructura que ha ido mejorando con el paso del tiempo, que puede soportar un mayor número de usuarios, o mayor carga de trabajo.

Sin embargo, el software de dichas empresas puede no haber crecido a la par, por ejemplo porque cuando se desarrolló la aplicación no había esas necesidades, y no se incluyeron como requisitos no funcionales.

Ese es el momento en el que, armados con todas las herramientas estupendas que tenemos a día de hoy, te encuentras con la "fácil" tarea de realizar la migración. Y ya que estamos, como hacer esa migración es "tan sencillo", pues ya aprovechamos y tenemos que incluir cierta funcionalidad que no tenía la aplicación original. Como todos sabemos, una migración es algo que "no produce valor añadido" - dicen - y claro, puede tener un cierto coste que, elevado o no, hay que justificar. Y de ahí el hecho de meterle "algo nuevo".

¿Quién no se ha encontrado con una situación así?

Tras realizar la migración, el resultado habitual, y que sorprende a muchos clientes, es el siguiente:

  • La aplicación migrada suele tener más bugs que la original. Normalmente suele ser porque ese código tan feo suele cubrir los cincuenta millones de casos especiales que se presentan durante el proceso que cubre, y al que nadie hace caso en el momento de plantear la nueva solución. Generalmente, no es posible bajar al nivel del código para todo el sistema antiguo cuando se diseña el nuevo.
  • El rendimiento de la nueva aplicación suele ser menor. Esto pasa más a menudo de lo que pudiera parecer, por ejemplo cuando se migra una aplicación en entorno host (cobol) a tecnologías actuales (Java - .NET). Cierto, la tecnología moderna te proporciona mucha más funcionalidad de base, pero a un cierto precio. Acelera el desarrollo, pero no necesariamente el rendimiento.

De ahí que surja la pregunta: ¿realmente es rentable hacer una migración de una aplicación desde cero?

Mi opinión es que depende. Hay situaciones en las que puede interesar migrar. Pero en la mayoría de los casos, puede ser interesante pensar en la reutilización de ese sistema, por ejemplo aplicando una arquitectura orientada a servicios. La nueva funcionalidad se puede desarrollar con otra tecnología más actual, y ciertas partes del sistema antiguo se pueden ir migrando paulatinamente.

Y vosotros, ¿qué opináis?

P.D.: Al hilo, un artículo muy interesante.