SysInternals

Hace algunos años Mark Russinovich tenía un sitio llamado SysInternals donde no solo ofrecía rutinas para realizar operaciones de administración de Windows sino también el correspondiente código fuente y artículos con explicación detallada de la lógica de programación. Afortunadamente para él y desafortunadamente para los hackers curiosos Microsoft le compro el sitio y quito el acceso a los códigos fuentes y las explicaciones sobre el funcionamiento interno de Windows.

 
Ahora Microsoft incluye Windows SysInternals como parte de su sito de soporte con un enfoque de administración de sistemas en vez del de programación que originalmente tenia. No queda más que comprar Windows® Internals: Including Windows Server 2008 and Windows Vista, Fifth Edition (PRO-Developer) y compensar a Russinovich por compartir sus experiencias.

Nube de etiquetas en WordPress

La navegación en Internet ahora se basa más en etiquetas que en categorización de contenido. Es un esquema más flexible. Las etiquetas relacionadas se pueden presentar como una nube de etiquetas las cuales son visualmente atractivas y dan un indicación visual de la importancia relativa de cada etiqueta.

He estado tratando de probar algunos plugins para soportar esta funcionalidad en WordPress pero he tenido problemas con todos los que he probado.

Referencias:

Category tagging with WordPress

Ultimate Tag Warrior Jerome’s Keywords WordPress-Plugin: del.icio.us Tag Cloud II

del.icio.us tag cloud v1.0.1

 SimpleTags – A WordPress Plugin for generating Technorati Tags Add-Meta-Tags WordPress Plugin

WordPress: Lista de plugins no recomendados

Catcloud Wordress Plugin Updated for WordPress 2.1

A Tagging Bookmarklet for WordPress and WordPress.com Users WordPress, Tagging, and a Critique of Hierarchy …and thanks for all the fish

Zone Tag

Nube de etiquetas ( label cloud ) en beta.blogger Setup and configuration for New Blogger Tag Cloud / Label Cloud

La búsqueda de número primos

La búsqueda de número primos (GIMPS Home Page).

Inclusive hay recompensa económica para motivar el desarrollo de esta tecnología a través de EFF Cooperative Computing Awards para el que encuentre primero:

$50,000 por el primer número primo con más de 1,000,000 dígitos decimales ( Apr. 6, 2000)
$100,000 por el primer número primo con más de 10,000,000 dígitos decimales
$150,000 por el primer número primo con más de 100,000,000 dígitos decimales
$250,000 por el primer número primo con más de 1,000,000,000 dígitos decimales

Actualmente el primo más grande que se conoce es el primo Mersenne 44, 232,582,657-1, un número de 9,808,358 digitos así que el premio de los 100,000 dolares pudiera estar cerca.

¿Se podrá hacer algo mejor con tu PC que correr screen savers y tenerla esperando a que teclees la siguiente letra?


Levantamiento de requerimientos

El siguiente escenario es tí­pico: Un consultor trabaja con los usuarios para describir los procesos de negocio que serán soportados por el software. El equipo de desarrollo recibe la descripción del consultor pero no están familiarizados con los términos de negocio y consideran la descripción demasiado informal. Los desarrolladores escriben su propia descripción desde un punto de vista técnico. El usuario no entiende esta descripción pero la acepta para que el proyecto avance. El resultado puede ser un sistema que desde el punto de vista del usuario es difícil de usar y que no cumple con sus expectativas.

Parte de este problema es metodológico, y en parte es intrínseco a las caracterí­sticas de los usuarios. Algunas de las problemáticas que se presentan:

  • Los usuarios no saben que es lo que quieren
  • Los usuarios no aceptan como un compromiso los requerimientos escritos
  • Los usuarios insistirán en nuevos requerimientos después de fijar costos y agendas.
  • Los usuarios no están disponibles y la comunicación con ellos es lenta
  • Los usuarios no participan en revisiones de avance.
  • Los usuarios no entienden el proceso de desarrollo y no les interesa.

Existen herramientas y metodologías para el levantamiento de requerimientos. Casos de uso y UML son medios para formalizar este proceso. Que diagramas UML es apropiado usar dependerá del sistema a desarrollar.

Una guía simple en términos de la complejidad del sistema:

  • Aplicación mono usuario
    • Diagrama de casos de uso.
    • Diagrama de clases.
    • Diagrama de interacción.
  • Aplicación mono usuario, con manejo de eventos:
    • Añadir: Diagrama de estados.
  • Aplicación cliente servidor:
    • Añadir: Diagrama de despliegue y diagrama de componentes, dependiendo de la complejidad.
  • Aplicación compleja distribuida:
    • Todos.

Para una aplicación sencilla debemos realizar entre tres y seis tipos de diagramas, y para una aplicación compleja unos nueve tipos. El diagrama de casos de uso puede modelar el contexto de un sistema o los requisitos del mismo. Se puede extender la colección de elementos base de UML utilizando estereotipos.

Referencias:

El número 7

7

El número 7 es un numero relacionado con el ciclo primario universal.

El ciclo lunar es de 28 días. Los factores primos de 28 son 7 y 2 y por lo tanto la mitad de la mitad del mes (semana) tiene 7 días.

Los planetas, las estrellas errantes en un universo estático y perfecto son 7: El Sol, la Luna, Marte, Mercurio, Venus, Júpiter y Saturno.

Al jugar con dos dados de seis caras, 7 es la suma más probable.

Referencias

La historia de π (pi)

Una de las experiencias más satisfactorias para mi ha sido leer A history of PI de Petr Beckmann.

Aunque los logros específicos del saber humano se dan a través de individuos al ver la historia el contexto social parece ser determinante para el desarrollo tecnológico y el entendimiento científico. Como dijo alguien con respecto a la bomba atómica:

 El secreto es saber que se puede hacer.

Por otro lado, los genios son cosa rara. Consideramos el siglo veinte y lo que va del veintiuno como superiores al resto de la historia humana en términos de entendimiento científico y avance tecnológico pero tal vez todavía no terminamos de aprehender lo que Newton percibió y plasmo en su obra hace 300 años.

Pi es interesante porque el circulo es interesante. El circulo es una forma ideal abstracta que no existe en la realidad pero también es la forma de muchos objetos de la vida diaria.

Algunas personas pueden entender que un objeto redondo es aproximadamente circular pero que si medimos con suficiente precisión no hay círculos perfectos en el mundo. Para algunos lograr este salto de abstracción no es una posibilidad y logran demostrar que pi es igual 20612/6561, que en términos prácticos, en términos de medir una mesa, o rebanar un pastel esta más que bien, pero en términos de capacidad de desarrollar tecnología, por ponerlo de alguna manera, es un callejón sin salida. La practicidad es un duende travieso que nos permite salir adelante ante los retos de la vida pero que si nos descuidamos nos lleva por los senderos del estancamiento y de la corrupción. Empecemos por valorar a los que pueden, tratemos de entender. El primer paso, según alcohólicos anónimos es aceptar el problema. La educación es el camino, trabajemos para que nuestros niños sepan observar, pensar, discutir, y hacer, no para que sean científicos, sino para que todos vivamos mejor.

Un lector del libro de Beckmann comparte su frustración en Internet:

I think my main problem with the book is that I was looking for an interesting narrative that explores the impact of pi from a cultural and personal point of view. What I got was a mathematical primer on pi, heavy on formulas, charts and graphs, peppered with bland historical facts easily obtained from general knowledge history books and encyclopedias.

Es curioso el comentario porque el libro es ameno, atestiguado por sus ventas, y las matemáticas son un lenguaje para hablar de cosas como pi, es decir son parte de la narrativa. Parece que la comunicación entre el hemisferio izquierdo y el derecho del cerebro no es tan fácil. Para algunos, como Pitágoras, los números son mágicos y su manipulación un camino para controlar el destino.

Volviendo a pi, veamos como expresarlo como una fracción.

Empecemos con una aproximación
pi=3.141592653589793+.
=
3 + 0.14159…

Tomado el reciproco de la parte fraccionaria
1
3 + ————
7.06251…

Iterando el procedimiento
1
3 + —————-
7 + 0.06251…

1
3 + ——————-
1
7 + ————-
15.99658…

Si la parte decimal es mayor a .5 podemos acercarnos por arriba
1
3 + —————————
1
7 + ———————
1
16 – ————–
292.98696…

Simplificando

1
3 + ———-
1
7 + —-
16

1
3 + ——-
113
—–
16

16
3 + —–
113

335
—–
113

Las primeas cuatro aproximaciones a pi corresponden con valores históricos;

3/1 3.000000000000000
22/7 3.142857142857143
355/113 3.141592920353983
104348/33215 3.141592653921421

Referencias:

La librería Gnu Multiple Precision (GMP)

La librería Gnu Multiple Precision (GMP) permite hacer cálculos de precisión arbitraria.

En el sitio de GMP viene un código de referencia que permite calcular pi hasta donde le alcance la memoria a la maquina.

Para construir la librería bajo mingw y Windows XP solo hay que seguir las instrucciones. Único detalle a tomar en cuenta es que /usr en mingw esta mapeado al directorio raíz de msys.

Posicionarse en el directorio raíz de la librería y seguir al secuencia del make

./configure
make
make check
make install

Ver el make trabajar es espeluznante, más de 10 minutos de pantallas can parámetros. Sin embargo hay puertos disponibles para .Net, aunque de la versión 4.1.

Para usar la librería podemos tomar como ejemplo el programa para calcular pi.

gcc -c gmp-chudnovsky.c -I/local/include
gcc -o gmp-chudnovsky.exe gmp-chudnovsky.o -L/local/lib -lgmp
gmp-chudnovsky.exe 50 1

Existe un puerto actualizado para Visual Studio 2005 disponible en la pagina Building GMP and MPFR with Microsoft Visual Studio 2005 and YASM. Hay que seguir las instrucciones del ReadMe con cuidado y al final aunque se generan warnings se construyen bien las librerías. Un paso que no esta claro del readme es que hacer con el archivo mparam_h.in. Yo simplemente lo renombre mparam.h.

El archivo gmp-chudnovsky.c del sitio de gmp necesita modificarse para usarlo en Visual Studio. Es necesario agregar las lineas de código:

#ifdef _MSC_VER
#define inline __inline
#endif

En la configuración del proyecto hay que agregar el directorio donde esta gmp.h y donde esta la librería que se quiera usar ademas de agregar la referencia a gmp.lib

Referencias

“Many Digits” Friendly Competition , Programas usados por el equipo de MPFR.

The MPFR Library

GMPY Project goals and strategies

Advanced Computation Group

Multiprecision floating-point arithmetic on Apple systems

Guile Extensions and Examples – Summary

AlgLibNet

Genius Math Tool and the GEL Language

Giac/Xcas

Computer algebra system

iRRAM – Exact Arithmetic in C++

MAGMA Computational Algebra System

SAGE is Open Source Mathematics Software

Wcalc

Numbers, constants, and computation

Minimalist GNU for Windows

MinGW o MinGW32 (Minimalist GNU for Windows) es una implementación de los compiladores GCC para la plataforma Win32, que permite migrar aplicaciones GNU a entornos Windows. Es un derivado de Cygwin en su versión 1.3.3.

MinGW incluye un conjunto de la api de Win32, permitiendo un desarrollo de aplicaciones nativas para esa plataforma, pudiendo generar ejecutables y librerí­as usando la API de Windows.

MinGW fue creado por Colin Peters, el 1 de julio de 1998, compilándolo con Gygwin. La primera versión nativa de MinGW fue realizada por Jan-Jaap van der Heijden, quien también tuvo participación en el proyecto GCC. Mumit Khan estuvo a cargo del mantenimiento del proyecto e incluyo al compilador algunas características propias de Windows. Los archivos de cabecera del API de Windows fueron provistos por Anders Norlander.

Una de las desventajas de MinGW es que los ejecutables que genera son de tamaño más grande que los generados por otros compiladores. Esto ocurre cuando se incluyen los archivos de cabecera estándares de C++ (por ejemplo, #include ), y se debe a que el compilador vincula todas las librerí­as dentro del archivo ejecutable de manera estática.

MinGW incluye MSYS (Minimal SYStem) un shell POSIX/Bourne para ejecutar scripts de configuración usados por make y ./configure

Después de descargar MinGW y MSYS, incluyendo mingw-runtime, w32api, binutils y gcc, gdb y mingw32-make se pueden expandir los archivos de dos formas. Poner el directorio de MinGW dentro de MSYS o instalarlos en directorios distintos y modificar el archivo MSYS /etc/fstab para agregar un apuntador al directorio donde mingw esta instalado.

Para probar la instalación se puede correr el shell de msys y probar el comando de línea

gcc –v

Para habilitar el soporte de IDEs agregar lib a la variable de entorno LIBRARY_PATH y los subdirectorios bin de y a la variable de entorno PATH
Aplicación de consola:

En un archivo con el nombre hello.c poner el siguiente código:

#include

int main(int argc, char **argv)
{
printf (“Hellon”);
return (0);
}

y compilar con

gcc -c hello.c

y después

gcc -o hello hello.o

Alternativamente

gcc -o hello hello.c

En un archivo con el nombre hello.cpp poner el siguiente código:

#include
int main(int argc, char **argv)
{
std::cout return (0);
}

y compilar con

g++ -c hello.cpp
g++ -o hello hello.o
Aplicación Windows

En un archivo con el nombre hello.c poner el siguiente código:

#include

int WINAPI WinMain (HINSTANCE hInstance,
HINSTANCE hPrevInstance,
PSTR szCmdLine,
int iCmdShow)
{
MessageBox (NULL, “Hello”, “Hello Demo”, MB_OK);
return (0);
}

para crear el ejecutable usar los comandos de linea

gcc -c hello.c

y

gcc -o hello hello.o -mwindows

el parametro -mwindows es necesario para que se incluyan las librerias necesarias para un programa Windows.
dll

En un archivo con el nombre dllfct.h poner el siguiente código:

#ifdef BUILD_DLL
// the dll exports
#define EXPORT __declspec(dllexport)
#else
// the exe imports
#define EXPORT __declspec(dllimport)
#endif

// function to be imported/exported
EXPORT void tstfunc (void);

En un archivo con el nombre dllfct.c poner el siguiente código:

#include
#include “dllfct.h”

EXPORT void tstfunc (void)
{
printf (“Hellon”);
}

En un archivo con el nombre Hello.c poner el siguiente código:

#include “dllfct.h”

int main ()
{
tstfunc ();
return (0);
}

Para crear una dll y un ejecutable que lo use:

gcc -c hello.c
gcc -c -DBUILD_DLL dllfct.c
gcc -shared -o tst.dll -Wl,–out-implib,libtstdll.a dllfct.o
gcc -o hello.exe hello.o -L./ -ltstdll

Se puede especificar el directorio a usar para los includes durante la compilación con

-I/path/to/headers

y las librerias para link:

-L/usr/lib/library

Usualmente no hay necesidad de andar moviendo las librerias.
Archivo .def para un dll

Si tiene un dll llamado file.dll y quiere crear un archivo .def con el nombre file.def,

echo EXPORTS > file.def
nm file.dll | grep ‘ T _’ | sed ‘s/.* T _//’ >> file.def

Para crear una biblioteca con el nombre file.a :

dlltool –def file.def –dllname file.dll –output-lib file.a

Generación de código

sisyphus

Así­ como los objetos fí­sicos se mueven a través del tiempo y el espacio, las aplicaciones de software se mueven por diferentes ejes en su ciclo de vida. Concretamente, el mantenimiento de una aplicación requerirá de una serie de adecuaciones y cambios por distintos motivos: cambio de plataforma, cambios en el proceso de negocio, nuevos requerimientos, nueva base de datos. Etcétera. Además, desde el punto de vista del desarrollador, lo ideal es poder reutilizar lo más posible de esfuerzos anteriores. En el ciclo de vida de un sistema, más del 60% del costo es el mantenimiento

La tendencia a requerimientos cada vez más complejos con tiempos de desarrollo cada vez más cortos vuelve el re-uso de código un imperativo.

Teóricamente, la programación orientada a objetos facilita el re uso de código. Los atributos de los lenguajes orientados a objetos que promueven el re-uso de código son:

Abstracción de datos que promueve sistemas modulares.

Herencia que permite que las subclases re-usen código de las superclases.

Poliformismo facilita el re-uso de comportamiento bajo diferentes contextos.

Marcos (frameworks) que son conjuntos de clases abstractas que solucionan familias de problemas relacionados.

Pero, para que se cumpla esta promesa divina de re-uso, el código, o más bien dicho, el diseño, debe ser bueno, muy bueno. ¿Qué es, entonces, un buen diseño? Cada cuál tendrá su idea. A manera de contrapunto empecemos por lo negativo, ¿Qué características tiene un mal diseño? Concediendo que la aplicación cumple con los requerimientos para los que fue diseñada, un diseño puede adolecer de lo siguiente:

Rigidez. La aplicación es difí­cil de cambiar porque cualquier cambio afecta demasiadas cosas.

Fragilidad. Cuando se hace un cambio, la aplicación deja de funcionar en lugares inesperados.

Inmovilidad. Es difí­cil utilizar la aplicación como parte de otra aplicación porque las dependencias con el contexto están enmadejadas en el código.

¿Qué es lo que hace un diseño rí­gido, frágil, e inmóvil? Las interdependencias de sus módulos. Entonces, para que el proceso de mantenimiento no sea la imagen de un perro persiguiendo su cola, se debe tener cuidado de minimizar interdependencias.

Desde el punto de vista de la programación estructurada, un diseño se puede ir construyendo bottom-up o top-down. Es decir, a partir de los componentes o módulos que tengo disponibles voy construyendo módulos más complejos, hasta cubrir los requerimientos, o conversamente, voy dividiendo mis requerimientos entre sub-módulos, hasta que llego a un punto suficientemente concreto para resolverlo de manera independiente. Al final, de manera iterativa, se llega a un diseño de capas jerárquico, donde en un sentido estricto, los únicos componentes que pueden ser completamente independientes del resto son los módulos de más bajo nivel en la jerárquia, es decir los más concretos y especí­ficos, los más ligados al problema particular que se esta resolviendo.

La mecánica establecida para re-usar rutinas de bajo nivel es el uso de librerí­as. En la practica la productividad de un lenguaje o ambiente de desarrollo esta ligada con la calidad y disponibilidad de librerías. Esto esta bien, pero desde el punto de vista de re-uso de código las dependencias están al revés. Los módulos de alto nivel, que resuelven un proceso complejo de interacción entre la aplicación, sus módulos internos, y el contexto exterior son los que queremos re-usar. De acuerdo a este precepto, un buen diseño debe cumplir con el principio de inversión de dependencias.

El principio de inversión de dependencias

Módulos de alto nivel no deben depender en módulos de bajo nivel. Ambos deben depender de abstracciones.

Abstracciones no deben depender de los detalles. Los detalles deben depender de las abstracciones.

Al concepto de inversión de control se le refiere como el principio de Hollywood:

Do not call us, we call you

Inversión de control es un aspecto clave que diferencia un marco orientado a objetos de una librería. Una librerí­a es un conjunto de funciones, tal vez organizadas dentro de clases, que una aplicación (cliente) llama dentro del código, la función hace lo que tiene que hacer, y regresa el control al cliente. En un marco orientado a objetos, es el marco el que llama al código del cliente. En .Net, por ejemplo, una manera de hacer esto es que el marco defina eventos a los cuales se subscribe el cliente y mediante el uso de delegados, el cliente asigna el compartimiento especifico que requiere.

En términos más generales, Interfaces es la manera de abstraer la interacción entre el cliente y el marco (framework). Una técnica de inversión de control es dependency injection.

La inversión de control es parte de lo que hace la programación de marcos orientados a objetos perturbadora para algunos. Al programar un procedimiento, la atención del programador esta en el flujo de control. Es difícil imaginar como se pudiera entender un programa sin saber la lógica de ejecución. Pero un buen marco abstrae el detalle del control de flujo. El foco de atención esta en los objetos, lo que puede ser al mismo tiempo más y menos tangible que el flujo de control.

En el marco, lo importante son las responsabilidades de cada objeto y la interacción (colaboración) entre ellos. Es una visión más abstracta, más declarativa del mundo, potencialmente más flexible y amplia que el enfoque en procedimientos.

Resumiendo, un buen diseño es aquel que nos permite hace cambios de manera no intrusiva, es decir, añadiendo código en vez de cambiando código. Un buen diseño se puede modificar sin tocar el código existente. O sea, en un desarrollo orientado a objetos el esfuerzo debe estar en el diseño. La programación orientada a objetos debe ser fácil, a costa de un proceso exhaustivo de diseño. He ahí la promesa y el reto fundamental de la orientación a objetos.

Los buenos patrones de diseño no se inventan, se descubren. Desde una perspectiva macro de diseño el principio de inversión de control es fundamental. Desde la perspectiva de las clases en si, ¿Qué principios se deben seguir para facilitar un buen diseño?, o más importante, ¿Qué debemos evitar para no inhibir el potencial del diseño? ¿Cómo garantizar que no haremos daño?

Algunos tips:

Es más fácil reusar un comportamiento agregando un componente que a través de herencia.

Eliminar análisis de casos. En el caso de .Net se pueden usar genéricos.

Reducir el número de argumentos. Sin embargo, al crear un objeto, es preferible exponer todas las dependencias para facilitar pruebas de clases individuales.

Reducir el tamaño de los métodos. El propósito del método debe ser obvio e idealmente el código debe ser auto documentado.

Las jerarquías de clases deben ser profundas y espigadas. Una clase todopoderosa, rodeada de ratoncitos indica un área de oportunidad en el diseño. Cada clase debe tener una responsabilidad principal, de preferencia única, claramente definida.

Minimizar acceso a variables. Una clase debe exponer solo aquello que sea estrictamente necesario para cumplir con su responsabilidad. En .Net se promueve el uso de propiedades en vez de variables públicas, para que la clase tenga mayor control en el uso de sus valores a través de métodos get y set.

La raíz de la jerarquía de clases debe ser abstracta. Es decir, no debe tener ningún (minimizar) detalle de implementación y solo exponer la interfaz de la clase.

Subclases deben ser especializaciones. Usualmente una subclase no debe redefinir métodos de la superclase, solo añadir nuevos.

Dividir clases grandes. Factorizar diferencias de implementación en sub-componentes. Separar métodos que no se comunican entre si.

Evitar el uso implícito de parámetros.

La guí­a del buen objeto,

  • Mantengo un estado consistente todo el tiempo.
  • No tengo métodos o variables estáticos.
  • Nunca espero o regreso null.
  • Fallo pronto.
  • Soy fácil de probar, todos los objetos de los que dependo los recibo como parámetros, normalmente durante construcción.
  • Los objetos de los que dependo pueden ser substituidos por Mock Objects (no uso dependencias a clases concretas).
  • Encadeno constructores multiples a un lugar comun, usando this
  • Siempre defino hashCode() junto a equals().
  • Prefiero valores inmutables que puede tirar fácilmente.
  • Tengo un valor especial para nada, por ejemplo EMPTY_SET para colecciones.
  • Disparo una excepción cuando el cliente pide algo que no es razonable, por ejemplo, abrir un archivo que no existe.
  • Disparo una excepción cuando no puedo hacer algo que deberí­a poder hacer, por ejemplo error de disco al leer un archivo abierto.
  • Solo atrapo excepciones que puedo manejar completamente.
  • Solo registró en bitácora información que alguien necesita ver.

Referencias

Johnson and Foote’s paper Designing Reusable Classes, Journal of Object-Oriented Programming , 1988.

El libro del Gang of Four

Richard Sweet ,1983.

John Vlissides column for C++ report

http://www.betaversion.org/%7Estefano/

http://www.laputan.org/drc/drc.html

http://www.laputan.org/dfc/discussion.html#Rock

http://www.digibarn.com/friends/curbow/star/XDEPaper.pdf

http://researchweb.watson.ibm.com/designpatterns/

http://www.flexwiki.com/default.aspx

http://www.artima.com/lejava/articles/patterns_practice.html

http://www.artima.com/index.jsp

http://today.java.net/pub/a/today/2004/02/10/ioc.html

http://www.objectmentor.com/resources/articles/dip.pdf

http://www.objectmentor.com/

One important characteristic of a framework is that the methods defined by the user to tailor the framework will often be called from within the framework itself, rather than from the user’s application code. The framework often plays the role of the main program in coordinating and sequencing application activity. This inversion of control gives frameworks the power to serve as extensible skeletons. The methods supplied by the user tailor the generic algorithms defined in the framework for a particular application.

Ralph Johnson y Brian Foote