Nota del autor

Si la entrada que estás leyendo carece de imágenes, no se ve el vídeo que teóricamente lleva incrustado o el código fuente mostrado aparece sin formato, podéis conocer los motivos aquí. Poco a poco iré restableciendo la normalidad en el blog.
Este blog es un archivo de los artículos situados previamente en Lobosoft.es y ha dejado de ser actualizado. Las nuevas entradas pueden encontrarse en www.lobosoft.es. Un saludo,
Lobosoft.

viernes, 29 de febrero de 2008

Atributos de NUnit 2.x

A la espera de las novedades que introducirá el lanzamiento de NUnit 3.0, vamos a presentar el uso de este unit-testing framework en la versión 2.4.x del mismo.


NUnit se presenta como una herramienta muy útil dentro del marco del desarrollo orientado a pruebas (TDD), permitiéndonos realizar las pruebas unitarias de forma automatizada y cubriendo todos los casos de uso que deban implementar las clases de nuestra aplicación. En el TDD, el flujo normal de desarrollo consiste en la escritura de las pruebas, escribir el código que debe pasarlas y hacer un refactoring para eliminar código duplicado. La escritura de las pruebas y la ejecución de los métodos que deben pasarlas correrá a cargo de NUnit.


El uso de NUnit se basa en el uso de atributos personalizados, que indicarán al framework de NUnit qué clases y qué métodos son los de pruebas, y qué pruebas deben realizarse sobre el código. Los atributos de NUnit en su versión 1.x eran nombrados según las convenciones del .Net Framework, pero esto cambió en la 2.x, usando ahora los atributos personalizados que pasamos a enumerar.


Atributos cuyo ámbito de uso es a nivel de clase:




  • TestFixture: Se usa para indicar que una determinada clase contiene métodos de prueba. Entre las restricciones para la clase están que deberá contar con un constructor por defecto (siendo válido el que proporciona automáticamente .Net) y que debe ser pública para que NUnit pueda acceder a ella para la ejecución de las pruebas.


Atributos cuyo ámbito de uso es a nivel de método:




  • Test: Su uso es indicar que un determinado método es un método de prueba. Entre las restricciones para el método de prueba estarán que no devuelva ningún valor (void) y no reciba parámetros, y que la clase a la que pertenezca esté marcada con el atributo TestFixture.



  • ExpectedException: Indica que el método va a producir una excepción del tipo indicado en el atributo (exactamente ese tipo, no otro distinto, aunque herede del mismo). La prueba se considera superada si al ejecutarlo lanza la excepción esperada.



  • TestFixtureSetUp: Inicializa el entorno de pruebas antes de ejecutarlas, es decir, establece las condiciones necesarias para que las pruebas se realicen en un ambiente idóneo. Se ejecutará antes que cualquier otro método. Sólo puede haber un método marcado con el atributo TestFixtureSetUp dentro de una clase TestFixture.



  • TestFixtureTearDown: Se encarga de restaurar el entorno creado para las pruebas por el método marcado con TestFixtureSetUp. Sólo puede haber un método marcado con este atributo dentro de la clase.



  • Setup: Inicializa y establece el entorno antes de la ejecución de cada prueba, es decir, justo antes de cada método de prueba que se ejecute. Generalmente se encarga de inicializar variables y dejar el entorno “limpio” para la ejecución de la prueba. Sólo puede haber un método marcado como Setup dentro de cada clase de pruebas.



  • TearDown: Su función es restaurar el entorno tras la ejecución de cada prueba unitaria. Sólo puede haber un método marcado como TearDown dentro de cada clase de pruebas.


El plan de ejecución de las pruebas será, por tanto, el siguiente:



Ejecución de las pruebas con NUnit


A nivel de método y clase tenemos los siguientes atributos:




  • Category: Otra opción que tenemos es agrupar las pruebas según categorías, de modo que podamos realizar la ejecución de un determinado bloque de pruebas simplemente indicando la categoría a la que pertenece la prueba. Para ello haremos uso del atributo Category, que puede usarse de forma conjunta a los atributos TestFixture o Test, es decir, a nivel de clase o de método.



  • Explicit: Obliga a indicar durante el proceso de pruebas que se incluya una determinada prueba en el mismo. Es decir, hay que indicar explícitamente que deseamos ejecutar una determinada prueba, siendo ignorada por NUnit en caso contrario.



  • Ignore: Es usado para ignorar una determinada prueba y no incluirla en el plan de pruebas. Al ejecutar NUnit, se marcará con amarillo, indicando que hay código sin probar. La ventaja de esto es que el código estará incluido en el ensamblado, ya que es compilado, pero lo excluimos de las pruebas igual que si todo el código del método o la clase hubiese sido comentado.


En la próxima entrega veremos un ejemplo de clase de pruebas haciendo uso de estos atributos y de otra de las características de NUnit, las aserciones (Asserts), que nos permitirán validar si el resultado esperado en las pruebas coincide con el que nos devuelve nuestro método probado.


Actualización (8 de abril de 2008): 

El blog registra una nueva entrada el 3 de abril de 2008 sobre Cheat Sheets, en concreto recogiendo una "hoja de trucos" o guía de Test-Driven Development, disponible para su descarga en formato PDF.

 

jueves, 28 de febrero de 2008

NUnit 3.0

La Programación Extrema o Extreme Programming (XP), es una metodología ágil de desarrollo basada en una serie de aspectos que permitirían un desarrollo permisivo y adaptable a los cambios de requisitos que se producen habitualmente durante el desarrollo de un proyecto. Una de las características fundamentales de este enfoque es el desarrollo orientado a pruebas (Test-Driven Development, o TDD), en el que las pruebas se suelen escribir antes incluso que el propio código que ha de superarlas. En este aspecto profundizaremos en una próxima entrada del blog, al incluir las pruebas unitarias en el desarrollo de nuestra aplicación con la Web Client Software Factory que introdujimos hace unos días. Sin embargo, el propósito de hoy no es otro que presentar una de las herramientas más usadas a este efecto en los desarrollos con tecnologías Microsoft .Net. Me refiero a NUnit, un framework de pruebas unitarias perteneciente a la familia xUnit, que sigue vigente hoy día, aun a pesar de la inclusión por parte de Microsoft de los proyectos de prueba (Test Projects) en las ediciones Team System de los IDE de desarrollo Visual Studio 2005 y 2008. Entre los motivos en los que me baso para afirmarlo se encuentran el pecuniario (los costes de una licencia de VSTS son mucho más elevados que los de un Visual Studio Professional + NUnit -que es gratuito-, y ya no digamos que los de un SharpDevelop o Eclipse con NUnit, que son nulos) y el de la portabilidad, ya que NUnit está disponible, por ejemplo, para plataformas Linux en las que podríamos estar desarrollando con Mono .


NUnit, en el momento en que escribo estas líneas, está disponible en su versión 2.4.6, que será la que usemos en las próximas entradas relacionadas con el TDD, pero está previsto el lanzamiento de la versión 3.0, que incluirá importantes cambios con respecto a la versión actual. Para empezar, su arquitectura estará basada en plugins, por lo que será mucho más extensible que NUnit 2.4.x, que permite la ampliación de sus funcionalidades mediante la incorporación de addins, pero está muy limitado a este respecto. La ventaja de las aplicaciones que permiten la incorporación de plugins es que, partiendo de una configuración básica, pueden personalizarse para cada usuario en concreto, haciendo la herramienta más útil para el mismo, y más adaptable al cambio.


La segunda característica que incorporará NUnit 3.0 es su arquitectura basada en tres capas: interfaz de usuario, motor de pruebas y framework xUnit.



Capas de NUnit 3.0


Esta división en capas permite que NUnit pueda usarse de diversas formas: mediante su propio inferfaz gráfico o en consola, usando NAnt, por ejemplo, para automatizar pruebas. También que las pruebas sean extensibles a varias plataformas, ya que NUnit 3.0 permitirá la ejecución de pruebas como un proceso separado, dependiendo de la versión del CLR, así como la ejecución distribuida de las pruebas en distintos puntos de una red mediante agentes remotos (Test Agents) . Por último, la capa de framework permite que las pruebas puedan hacerse en diferentes versiones del .Net Framework, en el Mono CLR y con el Compact Framework, en plataformas Linux y Windows, así como entornos de 32 y 64 bits.


Aunque faltan unos meses para poder disfrutar de la nueva versión de NUnit, todo parece apuntar a que la espera merecerá la pena.


Actualización (8 de abril de 2008): 

El blog registra una nueva entrada el 3 de abril de 2008 sobre Cheat Sheets, en concreto recogiendo una "hoja de trucos" o guía de Test-Driven Development, disponible para su descarga en formato PDF.

 

martes, 26 de febrero de 2008

La pérdida de conocimiento en la empresa actual

Hace unos meses, mientras buscaba información técnica sobre algún aspecto del desarrollo de software, encontré un artículo que me llamó enormemente la atención. Tras leerlo, lo compartí con algunos amigos, compañeros de profesión, y coincidieron conmigo en lo acertado del análisis que realiza sobre la pérdida de conocimiento que sufren, por decisión propia, tantas empresas del sector de la consultoría informática.


Aunque hay que admitir que en el mundo globalizado que nos ha tocado vivir merecen igualdad de condiciones un indio, que un latinoamericano o un europeo, y que la competitividad ha crecido -y seguirá haciéndolo- hasta límites inesperados, lo que no deja de sorprenderme es la facilidad con que las empresas “reponen” a los trabajadores que, tras meses o años de aprendizaje, deciden abandonar el barco antes de que, por el propio burn out producido por la insatisfacción profesional a que lleva el sentirse infravalorado, ardan las naves con el pasaje dentro. Y su puesto, como si nada hubiese ocurrido, llegará otra persona que partirá desde cero para intentar hacer crecer el árbol que plantó su predecesor, quien ya conocía cada hoja y cada brote del mismo.


Citando el artículo “Insourcing”, mejor que “outsourcing”:




Otro factor por el que el outsourcing no es interesante desde mi punto de vista, es que los que aprenden son otros. Cada vez que trabajas en la implementación de un sistema, por trivial que sea, aprendes algo, y ese conocimiento adquirido es algo que te va a ayudar en proyectos futuros. A las empresas siempre se nos llena la boca cuando hablamos de know how, pero se nos olvida que el know how, sólo nace de la experiencia, de la formación y de la capacidad para retener a nuestro personal. Llevar a cabo proyectos de software no es sólo una manera de ganarse la vida, sino también una excelente manera de aprender para poder abarcar proyectos futuros y poder seguir en el juego de ganarnos la vida. Sin ese proceso de aprendizaje de las empresas, es también muy difícil que se den las condiciones necesarias para que se produzca la innovación. Y todos los proyectos de desarrollo de software que triunfan son innovadores, en uno u otro sentido.



Se puede decir más alto, pero no más claro. O tal vez sí, de una forma ciertamente más lírica. Hace unos días, mientras leía la revisión que de la Ilíada hace Baricco, me encontraba con un texto que salvando distancias, puede asemejarse en buena medida al sentimiento de burn out que mencionaba anteriormente.



Habló Aquiles, diciendo:

Hijo de Laertes, divino de mente astuta, es mejor que hable claro y diga lo que pienso, y lo que sucederá: así nos evitaremos seguir charlando inútilmente. No hay en la tierra ni un solo aqueo que pueda convencerme de que abandone mi ira. No podrá hacerlo Agamenón, ni podréis hacerlo vosotros. ¿Qué provecho obtiene quien combate, siempre, sin tregua, ante cualquier enemigo? El destino es igual tanto para el animoso como para el bellaco, igual es el honor para el valiente que para el cobarde, y mueren igual el holgazán y el esforzado. Nada me queda después de haber sufrido tanto, después de haber arriesgado mi vida en todo momento en el corazón de la batalla. Como un pájaro que lleva a sus polluelos la comida que con tanto esfuerzo ha conseguido, del mismo modo pasé yo muchas noches insomnes, y muchos días dediqué a luchar contra el enemigo en el campo ensangrentado.

[…]

Ve a donde esté Agamenón y refiérele lo que te he dicho, y hazlo en voz alta, delante de todos, de manera que los demás aqueos sepan qué clase de hombre es, para que tengan cuidado, no vayan a ser engañados ellos también. Yo os digo que, por muy desvergonzado que sea, no volverá a tener el valor de mirarme a los ojos. Y yo no iré en su ayuda, ni combatiendo, ni dándole consejo; ya he tenido bastante, que se vaya al diablo, nada puedo hacer si se ha vuelto loco. Él ya nada me importa, y odio sus presentes: aunque me diera diez, veinte veces cuanto posee, aunque me ofreciera tantos bienes como granos tiene la arena, ni siquiera así lograría doblegar mi corazón. Antes tendrá que pagar, hasta el fondo, la horrible ofensa con que me ha herido.

(Alessandro Baricco, Homero, Ilíada)

Para profundizar en el tema:

Expresiones lambda vs Delegados y métodos anónimos

En la entrada anterior vimos cómo usar las expresiones lambda para formular con una sintaxis compacta y clara una serie de ecuaciones matemáticas en el .Net Framework 3.0 (y 3.5). Avanzamos también la relación existente entre esta notación y la declaración de un delegado y un método anónimo para implementar la misma funcionalidad, y cómo, hasta cierto punto, si las expresiones lambda hubiesen aparecido en la versión anterior del framework, podrían haber suplido la función de los métodos anónimos, brindando además una mayor funcionalidad, como el uso de bloques de código como datos y el uso de árboles de expresión, aspectos en los que profundizaremos más adelante, pues dotan a C# de características propias de la metaprogramación.


El propósito de hoy, sin embargo, es complementar al artículo de ayer, en el que afirmaba la íntima relación existente entre las expresiones lambda y los métodos anónimos y delegados, como avanzaba hace un momento. Para demostrarlo, haremos uso de la excelente herramienta Reflector, de Lutz Roeder, que permite desensamblar código objeto generado para el .Net Framework y mostrarlo en varios de los lenguajes que soporta (C#, VB.Net y el propio IL, entre otros).


Si abrimos, usando Reflector, la DLL correspondiente al ejemplo de ayer, en el que implementábamos una clase que nos ofrecía la funcionalidad de cálculo del interés simple en matemáticas financieras, nos encontraremos con una serie de peculiaridades.



Estructura de la clase Financiera


Como podemos apreciar, en el ensamblado se encuentran, además de los métodos que definimos en la clase, otra serie de métodos y delegados con nombres generados automáticamente. Si comprobamos el contenido de los mismos, pulsando sobre su nombre en el árbol de exploración de Reflector, nos encontraremos con un delegado “vacío”, correspondiente a la expresión lambda que definimos con nuestra ecuación para el interés.


Delegado “Interes”


El analizador de Reflector (botón derecho, y opción analizar) nos indica las dependencias del método y por cuáles otros es usado. En la secuencia de figuras que se muestran a continuación se puede comprobar que nuestra expresión lambda ha sido convertida internamente en un método anónimo y un delegado, ambos privados.




Método que implementa nuestra funcionalidad para el interés simple
La implementación de nuestra funcionalidad inicial



El método abstracto y delegado con sus dependencias
El delegado con sus usos y dependencias

La clase ofrecerá la funcionalidad a través de un delegado público que implementa el tipo genérico System.Func. Finalmente, el código de la clase quedará:



Código de la clase, según el desensamblador


Con ésto hemos demostrado la relación existente entre las expresiones lambda y los delegados y métodos anónimos que indicábamos ayer.

Expresiones Lambda en C#

Ya he hablado en otras ocasiones sobre la incorporación de las expresiones lambda al .Net Framework a partir de su versión 3.0. Este tipo de expresiones, en las que profundizaremos hoy, proporcionan al framework el soporte necesario para el uso de LINQ como lenguaje de consulta casi, diríamos, universal. Lo primero que llama la atención al ver la implementación de las expresiones lambda en .Net es que, de haber aparecido antes, no habrían sido necesarios los métodos anónimos que se incorporaron en la anterior versión del framework (.Net 2.0). Es más, en cierto modo constituyen -entre otras mejoras- un embellecimiento del código y un (permítasenos la licencia de llamarlo así) encapsulamiento del método anónimo y del delegado que lo incluye. Esta relación, y cómo se definen las expresiones lambda, será el tema principal de la entrada de hoy.


En el cálculo del interés simple, dentro del campo de las matemáticas financieras, entran en juego una serie de ecuaciones que deseamos implementar en nuestro código.


Interés = Capital * Tiempo * Tasa de interés
Valor Futuro = Capital * (1 + Tasa * Tiempo)
Capital = Valor Futuro * (1+ Tasa * Tiempo) -1

Si deseáramos implementar estas funciones mediante el uso de métodos anónimos, deberíamos hacerlo a través de un delegado. Por ejemplo, la función que define el Interés podría implementarse como sigue:


[csharp]
private static double MiInteres(double C, int t, float i)
{
return ((C * t) * i);
}
[/csharp]

Para poder asignarla a un delegado, deberíamos tener definido un delegado con su misma firma:


[csharp]public delegate double Func(double C, int t, Single i);[/csharp]

La asignación, entonces, sería automática:


[csharp]Func miInteres1 = MiInteres;[/csharp]

Sin embargo, los métodos anónimos nos brindan un método más compacto y elegante para obtener el mismo resultado:


[csharp]Func miInteres2 = delegate(double C, int t, Single i) { return C * t * i; };[/csharp]

La definición de Func, incluido en el espacio de nombres System.Linq como tipo genérico de delegado, es la que sigue (para un ejemplo con 0, 1 y 2 argumentos):


[csharp]
public delegate TResult Func();
public delegate TResult Func(T1 arg1);
public delegate TResult Func(T1 arg1, T2 arg2);
[/csharp]

Visto esto, ¿cómo podríamos realizar la implementación de nuestras funciones financieras usando expresiones lambda? Vuelvo a incidir en la cercanía de dichas expresiones con los lenguajes funcionales y en que, debido a esta característica, su declaración será compacta y precisa. Comencemos con la misma función que nos ha ocupado hasta este momento, la del cálculo del interés simple. Recordemos que esta función estaba definida como

Interés = Capital * Tiempo * Tasa de interés

La expresión lambda equivalente será
[csharp]
public static Func Interes = (C, t, i) => (C * t * i);
[/csharp]

Como vemos, el C# de los .Net Frameworks 3.0 y 3.5 incluye mediante las expresiones lambda una sintaxis mucho más clara y concisa que el que se conseguía mediante el uso de los métodos anónimos. Una posible implementación de las ecuaciones implicadas en el cálculo del interés podría ser la siguiente:


[csharp]
public static class InteresSimple
{
public static Func Interes =
(C, t, i) => (C * t * i);

public static Func ValorFuturo =
(C, t, i) => (C * (1 + i * t));

public static Func Capital =
(VF, t, i) => (VF * Math.Pow((1 + i * t), -1));
}
[/csharp]

Entre las ventajas que nos aportará el uso de las expresiones lambda frente al de métodos anónimos y delegados se encuentra no sólo la simplicidad y limpieza sintáctica de la expresión, sino también la posiblidad de usar bloques de código como datos (algo inherente a estas expresiones e imposible de conseguir mediante los métodos anónimos), una característica en la que profundizaremos en otra ocasión.

lunes, 25 de febrero de 2008

Mi ordenador es un zombi


Ghost’n Goblins - Ordenadores Zombi


Desafortunadamente el título de la entrada de hoy no parafrasea el de la conocida canción de Alaska y Dinarama, sino que hace referencia a la expansión que se viene produciendo desde hace un par de años de malware específicamente diseñado para facilitar la delincuencia en el ciberespacio. Por un lado, proliferan ataques de phishing que, haciendo uso de lo que en su día se dio en llamar “ingeniería social”, vulneran la privacidad de los usuarios robando sus contraseñas gracias a la inconsciencia de aquellos que, tras recibir un correo electrónico o una petición por cualquier método, incluido el telefónico, de su autenticación en el sistema informático de su banco, se prestan, sin mayor dilación, a hacerlo. La captura de las contraseñas se produce desde un sitio web muy similar al verdadero, que simplemente recoge la clave introducida por el usuario y, con probabilidad, informa al mismo de que la introdujo mal redirigiéndole después al sitio web verdadero, con lo que en el segundo intento puede acceder al sistema y piensa, ingenuo, que se equivocó la primera vez al teclear la contraseña.


Hay otros métodos más sofisticados, como el uso de troyanos u otro malware que, convenientemente instalado en el ordenador del usuario, usa keyloggers para recuperar todo lo escrito desde el mismo. Sin embargo, y ante la inclusión de los bancos de teclados virtuales en sus páginas, mediante los que solicitan al usuario la introducción de la contraseña en lugar de hacerlo a través del verdadero teclado, han aparecido troyanos que incluso realizan una grabación en video del momento clave (nunca mejor dicho) en el que el usuario introduce su contraseña haciendo uso del mencionado teclado virtual. A todos estos ataques de phishing habría que sumar los de pharming para comprobar que no estamos tan seguros como creemos en nuestra casa y frente a nuestros ordenadores personales.


¿Qué diríamos ahora si nos acusaran de formar parte de un equipo de ciberdelincuentes, de difundir SPAM (correo basura) entre miles de usuarios, de realizar ataques DoS a sitios web o distribuir pornografía infantil desde nuestro ordenador? Es decir, formar parte de los criminales, y no de las víctimas. Lo negaríamos, ¿verdad? Pero, ¿estamos seguros de no estar incurriendo en el delito que pretenden inculparnos? La respuesta debería ser un rotundo no. Evidentemente, desde Lobosoft deseamos creer en su inocencia, y que está siendo víctima de otro tipo de ataque que prolifera actualmente: convertir su ordenador en un zombi mediante la instalación de un software malicioso que permita al atacante controlarlo y usarlo para perpetrar todo tipo de delitos; desde enviar correo publicitario no deseado a realizar ataques de denegación de servicio, pasando por su uso como pasarela a otros sistemas informáticos consiguiendo, mediante una serie de “saltos”, ocultar su rastro ante posibles rastreos de la policía científica.


La proliferación de equipos zombis en los últimos años ha sufrido un crecimiento exponencial en todos los países desarrollados. El nuestro, con un afán loable de superación, España es el segundo país dentro del ranking Europeo de ordenadores infectados por este tipo de malware, según un informe de la Europol fechado en agosto del pasado año, por lo que existe una alta probabilidad de que ahora, desde su equipo, se esté compartiendo pornografía o esté enviando correos con publicidad sobre alargamiento del miembro viril masculino a cientos de usuarios, hastiados ya de recibir este tipo de información.


Ante todo esto, ¿cómo actuar? Sin duda, instalando en su equipo y manteniendo actualizado un antivirus, software de protección anti-spyware y algún firewall. Y, ante todo, actuando siempre con la máxima prudencia.


Para saber más:



viernes, 22 de febrero de 2008

Olvido de contraseñas en Windows

Ophcrak logo 


¿Cuántas veces habrá acudido a nosotros un usuario desesperado porque no recuerda la contraseña de Windows? En entornos en los que existe un repositorio centralizado de contraseñas (léase LDAP y similares), el administrador de sistemas dará fin a la inquietud del usuario en un santiamén. Sin embargo, en equipos domésticos o pequeñas empresas eso es, cuando menos, ciencia ficción. Ante situaciones como la planteada es cuando demuestran su utilidad herramientas como las que presentaba hace unos días en la entrada sobre distribuciones Linux que incluyen herramientas de seguridad. Esta tarde he aprovechado para probar una de las más sencillas que pueda encontrarse: Ophcrack. Se trata de un LiveCD que incluye un SLAX Linux (una distribución bastante ligera) con la herramienta Ophcrack instalada. El uso de la misma es tremendamente complejo, por lo que conviene enumerar los pasos a seguir:




  1. Introducir el LiveCD en la unidad lectora del equipo.

  2. Reiniciar el ordenador.

  3. Esperar a que aparezca el menú de arranque y pulsar Enter.

  4. Se iniciará el sistema Linux. Montará automáticamente la partición Windows donde se encuentre el archivo SAM de contraseñas. Iniciará automáticamente OphCrack.

  5. Esperar.

  6. Esperar más.

  7. La lista de usuarios con sus contraseñas respectivas estará ante nosotros.


El ataque de Ophcrack está basado en tablas Rainbow, por lo que la fortaleza de las contraseñas será inversamente proporcional a la similitud de las mismas con palabras reales. En cualquier caso, existen tablas con caracteres especiales, y si ninguna de ellas consigue romper las claves, finalmente se produce un ataque por fuerza bruta. Por tanto, la duración del proceso irá en relación directa con la complejidad de las contraseñas de los usuarios.




Ophcrack LiveCD




Ophcrack es una herramienta recomendable que conviene tener siempre a mano, sobre todo si corremos el peligro de enfrentarnos a situaciones como la que planteaba en el inicio del post de hoy.