viernes, 22 de octubre de 2010

Ver un PC virtual con VMWare Player desde la red

Hoy ha sido un día un interesante de trabajo para mi compañero Miguel Ángel y para mí. Estamos preparando un sistema de integración continua para nuestro proyecto y nos habíamos decidido por probar la solución de TeamCity, la cual ofrece una versión gratuita. La idea era montar este servicio sobre una unidad virtual en uno de los ordenadores de la red para que el resto del equipo tuviese acceso también.

Creamos la unidad virtual con VMWare Player v3.1.2 con Windows 7 Profesional e instalamos TeamCity sin complicaciones. La nueva unidad virtual puede ver sin problemas el resto de los ordenadores de la red así que configuramos TeamCity para que se conecte a los repositorios de código fuente. Todo perfecto… hasta aquí.

El problema

Si como he dicho antes la unidad virtual podía ver los ordenadores de la red, no era lo mismo al revés. Nadie, ni tan siquiera el host que albergaba a la unidad virtual era capaz de ver al equipo, y por tanto, acceder al servicio.

Buscamos por Internet suponiendo que este problema sería bastante común y que fácilmente encontraríamos la manera de configurar el sistema para solucionarlo. El caso es que no es así, y que además, la manera de solucionarlo es bastante… “truqui del almendruqui”.

Buscando la solución

Lo primero que debemos hacer es configurar la unidad virtual con configuración de red NAT como se muestra en la imagen:

clip_image002

Con esto hacemos que la unidad virtual comparta la misma IP que nuestro equipo host. Pero atención, debemos tener en cuenta que cuando instalamos VMware Player, automáticamente te instala un par de adaptadores de red: VMnet1 y VMnet2. Puedes verlo haciendo una llamada a ipconfig desde la consola:

clip_image003

Para hacer que la unidad virtual utilice de manera correcta el adaptador el adaptador, en nuestro caso VMnet8, necesitamos usar la herramienta de VMware: Virtual Network Editor.

Ya te puedes hinchar de buscar que no la vas a encontrar. Parece ser que no viene con la distribución gratuita de VMware Player. ¿O sí?

Conseguir Virtual Network Monitor

Por lo visto, a los chicos de VMware se les ha ocurrido una curiosa manera de “darte” esta aplicación, pero como si no existiera. En realidad la tienen oculta dentro del fichero de instalación. Para conseguirla tienes que seguir estos pasos:

1. Extrae todo el contenido del instalador mediante la llamada:
c:\> VMware-player-3.1.2.<versión>.exe /e vmware_temp

2. Dentro de la carpeta vmware_temp encontrarás un fichero network.cab. Descomprimelo con WinRAR o 7zip y dentro encontrarás el ejecutable que buscas: vmnetcfg.exe

3. Como este ejecutable tiene muchas dependencias con otras librerías, es aconsejable copiarlo a la carpeta donde esté instalado VMware Player.

4. Listo para configurar.

Configuración con Virtual Network Monitor

Una vez arranquemos la herramienta, realizará una búsqueda de todos los adaptadores de redes virtuales que se encuentren en el PC host. Entre ellos encontrará activados VMnet1 y VMnet8. Nosotros nos centramos en VMnet8. El cual configuramos de la siguiente manera:

clip_image005

Debemos asegurarnos que también esté configurado como NAT y que la IP y la máscara de subred corresponden con lo mostrado en la configuración que muestra el host con el ipconfig que le hicimos en VMnet8.

Con esto ya hemos conseguido configurar el adaptador de red que está asociado a nuestra unidad virtual.

Dado que desde fuera del host, no se tiene acceso a esa subred, y por tanto a la unidad virtual, debemos configurar el NAT para que el host haga de puente entre la red y la unidad virtual. Para ello, asociamos un puerto del host con un puerto de la unidad virtual.

Sabiendo que TeamCity lo que expone es un servicio web y por tanto se accede usando el navegador, configuramos el puerto 8080 del host para que se correspondiera con el puerto 80 de la unidad virtual:clip_image006

Es interesante destacar que hay que hacerlo tanto para el protocolo TCP y UDP, sino, no funciona.

Y listo. Cualquier ordenador de la red que acceda desde el navegador a la dirección 192.168.14.248:8080, realmente está accediendo a la subred privada 172.16.37.128:80

A continuación la configuración de red de la unidad virtual:

clip_image008

domingo, 3 de octubre de 2010

El patrón Modelo-Vista-Presentador (MVP) a examen

Desde hace tiempo llevo enfrentándome con diversos patrones de diseño cuyo objetivo principal es el de separar la interfaz de usuario de la lógica de las aplicaciones. Desde mis años de estudiante universitario con Smalltalk y el patrón Modelo-Vista-Controlador (MVC), hasta MVVM con WPF, pasando por MVP, MP y sus variaciones.

Cada vez que he tenido que me embarcaba a usar uno de estos patrones de diseño me encontraba con la misma curva de aprendizaje. Un concepto bastante sencillo pero que ante ciertos escenarios que encontraba en proyectos reales uno no sabe exactamente qué solución tomar.

En esta entrada quiero centrarme en el patrón de diseño Modelo-Vista-Presentador (MVP), pero yendo más allá de la descripción académica de este patrón y enfocándome en cómo puede ser aplicado en aplicaciones reales.

Como he comentado antes, MVP es otro patrón de diseño que tiene como objetivo separar la interfaz de usuario de la lógica de las aplicaciones.

Básicamente este patrón consiste en 3 componentes:

  • La vista. Compuesta de las ventanas y controles que forman la interfaz de usuario de la aplicación.
  • El modelo. Que es donde se lleva a cabo toda la lógica de negocio.
  • El presentador. Escucha los eventos que se producen en la vista y ejecuta las acciones necesarias a través del modelo. Además puede tener acceso a las vistas a través de las interfaces que la vista debe implementar.

image

El concepto de este patrón es bastante sencillo. Por un lado tengo la vista, que se encarga de mostrar la información al usuario y de interactuar con él para hacer ciertas operaciones. Por otro lado, tenemos el modelo que, ignorante de cómo la información es mostrada al usuario, realiza toda la lógica de las aplicaciones usando las entidades del dominio. Y por último tenemos al presentador que es el que “presenta” a ambos actores sin que haya ningún tipo de dependencia entre ellos.

El propósito del presentador tal y como se ha definido en este patrón no establece de manera clara el grado de control que este puede hacer de la vista.

Dependiendo de este grado de control podemos encontrarnos variaciones en la manera de ver MVP. De hecho, algunas de ellas, dejan de ser MVP para convertirse en MVC, por lo cual debemos tener cuidado.

MVP como Controlador Supervisado

Por un lado, podemos tener un presentador que no gestione la forma en que la información es mostrada en la vista. Es la vista quien define la lógica de cómo la información es formateada y mostrada en la pantalla a partir de los controles que contiene. En este caso, el presentador únicamente los casos más complejos para facilitar el trabajo de la vista. Martin Fowler llama a esta variación Controlador Supervisado.

image

Cuando la vista recibe algún evento de ratón o teclado por parte del usuario, delega el control del evento en el presentador. Este puede realizar ciertas operaciones relacionadas con la vista como el control del estado de los controles y después realizar la llamada a algún comando en el modelo que realice la operación requerida por el usuario. El modelo realiza las operaciones pudiendo realizar cambios en su estado generando el evento correspondiente, el cual es manejado por la vista para actualizar los controles de la pantalla.

Hay que tener en cuenta de que el hecho de que la vista pueda hacer referencia al modelo nos da como resultado un diagrama muy parecido al de MVC. Aunque este enfoque nos permita el uso de técnicas de Data Binding. Con lo cual la cantidad de código que la vista y presentador necesitan, se disminuye.

Este enfoque nos va a permitir el uso de técnicas de Data Binding sobre el modelo. Por tanto, la cantidad de líneas de código fuente en la vista y el presentador disminuyen. Si nos fijamos en el diagrama, este es similar al de MVC por lo que hay que tener mucho cuidado en no caer en un cambio de patrón.

MVP como Vista Pasiva

Por otro lado, podemos hacer que el presentador gestione totalmente cómo la información se muestra en la vista. Es decir, tenemos una vista "tonta", sin ningún tipo de lógica, cuya única función es la de mostrar la información que se le pasa a través de la interfaz de la vista. Martin Fowler llama a esta variación Vista Pasiva.

image

En este caso, cuando un usuario realiza alguna operación sobre la interfaz de usuario, la vista delega los eventos sobre el presentador. Este realizará algún cambio sobre la vista para indicar el cambio de estado y hará las llamadas a los comandos sobre el modelo para llevar a cabo la operación requerida por el usuario. Cuando el modelo provoque cambios en su estado, estos serán recogidos por el presentador (al contrario que en el controlador supervisado, que era la vista quien atendía a estos cambios de estado en el modelo), el cual pedirá al modelo los cambios realizados para luego actualizar la vista acorde a los cambios recibidos.

Ejemplo

Supongamos el siguiente ejemplo: Un programa que para una fecha que le introduzcamos, te diga si es pasado, futuro o la fecha del día actual.

image

Cuando el usuario introduce la fecha y pulsa el botón OK, la vista delega el evento de pulsación de botón sobre el presentador. El presentador toma la fecha introducida del cuadro de texto y valida que el contenido tiene el formato de fecha correcto.

Nota: He obviado la posibilidad de usar un control específico para introducir fechas y así ver en qué lugar se pude hacer la validación de datos.

Si la fecha introducida no fuera correcta, el presentador comunicaría al usuario este hecho a través de la vista.

En caso de que la fecha fuese correcta, el presentador realizaría la operación de comprobar la fecha usando el modelo. Al recibir el resultado de la operación, el presentador mostraría el resultado a través de la vista. Por ejemplo, modificando el texto de la etiqueta con el resultado.

En el siguiente diagrama vemos la secuencia de llamadas realizada para el caso de Vista Pasiva:

image

En caso de usar la variación de Controlador Supervisado, supondría que la vista toma el resultado directamente del modelo y que además, la vista define la lógica de cómo el resultado se muestra en la pantalla. En el caso de que la validación de la fecha fallara, el presentador podría, por ejemplo, enviar una excepción hacia la vista que al capturarla decidiría como se mostraría al usuario.

Actualización: 
He creado en Codeplex un proyecto que hace uso de este patrón. Se trata de un sencillo ejemplo de máquina tragaperras sobre Windows Forms. El enlace al proyecto es este.

viernes, 27 de agosto de 2010

He leído “Dont Make Me Think” de Steve Krug

Curioseando en Amazon me encontré con este curioso libro. Por el título me parecía más bien un libro de esos de autoayuda, pero el caso es que estaba dentro de una colección de libros sobre usabilidad de las interfaces de usuario de las páginas web. Lo que realmente hizo que hiciera clic sobre él fue el número de comentarios, más de 500 y con casi 5 estrellas!! Cuando el resto apenas llegaba a los 100 comentarios.

El libro me lo he leído en un solo día. Son unas 200 páginas y es que el escritor se ha esforzado en que sea ligero y ameno en su lectura: “Si es breve, es más probable que se use”

El libro trata de los errores más comunes que cometen los desarrolladores y diseñadores cuando abordan (u omiten) el tema de la usabilidad de una página web. Y que al final hacen que un usuario pierda la paciencia o se frustre navegando por sus páginas y termine yéndose a la página de la competencia.

Contiene numerosos ejemplos de buenos diseños y malos diseños y de como solucionar los problemas más comunes respecto a su usabilidad. Interesante también el capitulo dedicado a las pruebas de usabilidad. Sin duda para tener en cuenta por cualquier diseñador de interfaces de usuario.

Algunas de las claves que da el libro pueden resumirse en:

  • Los usuarios no quieren pensar mientras navegan por una pagina porque:
    1. No las leen, las escanean buscando palabras clave.
    2. No hacen búsquedas optimas, se quedan en el primer enlace que parece que les pueda dirigir a lo que buscan.
    3. No averiguan el funcionamiento de las cosas. Se las arreglan con lo que le dice su instinto.
  • No les importa el número de veces que hay que hacer clic en algo si la opción es mecánica e inequívoca.
  • Elimine la mitad de las palabras en todas las páginas y luego deshágase de la mitad de lo que quede.

Libro muy recomendable para todos aquellos diseñadores de paginas web o que tengan algo que ver con el diseño de Interfaces de Usuario en aplicaciones.

domingo, 11 de julio de 2010

Open eBook Reader

Me acabo de estrenar en CodePlex subiendo un proyecto de mi propia cosecha. Se trata de un lector de libros electrónicos para PC. Lo he llamado Open eBook Reader y lo podéis encontrar en este enlace.
Open eBook Reader
La verdad es que lo hubiera llamado eBook Reader a secas, pero ya estaba pillado. En fin, que le he acoplado lo del Open delante porque lo he puesto con licencia de Open Source y porque pretendo que únicamente lea formatos de libros que también sean Open Source.
Por ahora sólo lee formato Fiction Book v2.0. Ya iremos ampliando el repertorio de formatos.

martes, 8 de junio de 2010

S.O.L.I.D. – El Principio Abierto-Cerrado (OCP) (parte 3)

En muchas ocasiones hemos visto en nuestro trabajo como nos cambiaban los requerimientos de alguno de los módulos cuando ya estaban prácticamente terminados. Lo que suponía cambiar el módulo, y comprobar que no hubiera efectos colaterales en otros módulos relacionados. Tener en cuenta este principio va a hacer que evitemos muchos de los problemas relacionados con los cambios en un módulo a causa de cambios en las especificaciones de las clases o componentes.

image

Por ejemplo, supongamos una clase conductor (Driver) que es capaz de conducir Vehículos (Vehicle). Si los requerimientos del sistema cambiaran y ahora el conductor tuviese que conducir sólo vehículos a motor, está claro que la clase Vehicle cambiaría en su comportamiento y posiblemente en su interfaz, por lo que la clase Driver tendría que adaptarse a los nuevos cambios del la clase Vehicle.

El Principio de Abierto-Cerrado, del inglés “The Open-Close Principle (OCP)”, nos viene a decir que cualquier entidad software (clases, módulos, funciones, etc.) debe de estar abierta para ser extendida en funcionalidad pero cerrada para ser modificada. Es decir, una clase que cumpla con OCP tiene estas dos características:

  1. La funcionalidad del módulo puede cambiarse o extenderse en base a los cambios que requiera el sistema.
  2. Extender la funcionalidad de un módulo no implica cambios en el código fuente de ese módulo en si mismo.

¿Cómo se puede entender esto? ¿Cómo cambiar el comportamiento de una clase sin cambiar su código fuente? ¿Cómo hacer que la clase Driver no se tenga que cambiar y sin embargo sea capaz de tratar con el nuevo tipo de vehículo. La respuesta está en la abstracción. La abstracción se puede conseguir de muchas maneras en programación orientada a objetos. A través de interfaces, clases abstractas, delegados, etc.

image En este case, la interfaz IDriver es la abstracción que define la clase Driver para conducir un Vehicle. Fíjese en que no he llamado a la interfaz IVehicle como podría haber sido lo lógico. Esto es así porque el que define la funcionalidad es el Driver mientras que Vehicle es únicamente una implementación de esa interfaz. Para implementar el cambio que decía que un Driver sólo puede conducir vehículos a motor bastaría con cambiar únicamente la implementación de Vehicle para ajustarse a las nuevas necesidades.

Con este diseño, la clase Driver cumpliría con OCP, pues está abierto a cambios (respecto a conducir vehículos) y cerrado a los cambios (para cambiar el comportamiento de los vehículos, no se necesita cambiar). Otro tema sería que los cambios que se pidieran no fuesen soportados por la interfaz disponible. Por ejemplo, tener en cuenta vehículos voladores. En este caso los cambios serían a nivel de requerimientos de más alto nivel, por lo que se entiende que no quede más remedio que cambiar la clase Driver, la interfaz IDriver, y evidentemente todas las implementaciones de esta interfaz.

Anticipación al uso de OCP

No debemos caer en la tentación tampoco de crear abstracciones e interfaces en todas las clases. Esto haría que el diseño creara interfaces por casi cualquier referencia a otra clase que se tuviera. Y haría el código menos legible. Además, esto tampoco nos evitaría tener una clase completamente cerrada. siempre nos pueden pedir un cambio que no esté soportado por las abstracciones que tengamos. Entonces, ¿cuando debemos forzar una clase a que cumpla con este principio? Cuando nos lo diga el sentido común. Yo por ejemplo en mi caso, lo aplico siempre que vea muy claro una dependencia a una clase cuya funcionalidad veo que tenga ciertas posibilidades de que cambie de comportamiento. Otro caso donde es conveniente el uso de OCP es cuando te piden un cambio en una clase, y ese cambio afecta a las clases llamantes de la clase modificada (se arrastran los cambios). En este caso, me creo la interfaz para esas clases y hago que la clase que cambia la implemente. De esta manera, aunque la primera vez tenga que hacer la refactorización de varias clases, me aseguro de que si me piden nuevos cambios, estos sólo afecten a la clase que implemente la interfaz.

domingo, 6 de junio de 2010

Nuevo eBook Reader Papyre 6.S Alex

Hoy me he llevado una sorpresa. Navegando en busca de tiendas de ebooks me he encontrado que la empresa suministradora en España del lector de ebooks Papyre ha sacado un nuevo modelo al mercado. El Papyre 6.S Alex.

Papyre 6.S alex

El punto distintivo de este modelo con el resto de la familia de lectores Papyre es la doble pantalla de al que dispone. La típica de 6” para la lectura, y otra más pequeña de 3.5” en color y táctil para los controles. También me ha llamado la atención el que haya cambiado el sistema operativo de Linux por un Android. Y es que parece que este sistema se está colando en todos los dispositivos pequeños.

Desde el punto de vista de la conectividad ha dado un paso de gigante con respecto al de sus hermanos pequeños puesto que dispone de conexión WIFI. Así que se podrá navegar por internet, leer el correo, etc.

También es capaz de reproducir ficheros MP3 y videos MPEG2/4 por lo que se puede comportar como un dispositivo multimedia. Aunque evidentemente, usándolo así, la batería nos durará mucho menos.

También se pueden sincronizar las pantallas. Así que si estamos viendo una página de un periódico o un blog en la mini pantalla, podemos ponerla en la pantalla grande. Eso si, en las 16 escalas de grises que soporta.

Y para aquellos que le echen en falta poder navegar usando 3G decir que he leído en algún sitio que tienen preparado una versión de firmware con soporte para esto. Que si todavía no lo han puesto es porque están en negociación con las operadoras de telefonía móvil.

Para los valientes, decir que el cacharrito sale por unos 450€ en la página de Grammata. Más información en http://grammata.es/papyre/papyre-6-s-alex

viernes, 4 de junio de 2010

S.O.L.I.D. – El principio de la Responsabilidad Única (SRP) (parte 2)

El Principio de Responsabilidad Única (o en inglés Single Responsibility Principle (SRP)) fue descrito por Tom DeMarco y Meilir Page-Jones en un trabajo que llamado “Cohesión” en el que se definen las relaciones de los elementos de un módulo. Este principio nos viene a decir que una clase sólo debería tener una única razón para cambiar.

“Una clase debe tener una única razón para cambiar.”

Lo que trata de decirnos este principio es que debemos huir de aquellas clases monolíticas que aglutinen varias responsabilidades. Pero, ¿qué es una responsabilidad? Desde el punto de vista de SRP se podría decir que una responsabilidad en una clase es una razón para cambiar esa clase. Es decir, si encontramos que hay más de una razón por la que una clase pueda cambiar entonces es que esa clase tiene más de una responsabilidad.

¿Y no sería más sencillo decir que una clase debería tener una sola razón para existir en lugar de para cambiar? Cuidado, porque esto nos podría llevar a hacer muy malos diseños de sistemas. Llevado al pie de la letra podría encontrarme con cientos de clases en mi sistema, cada una con una única función. Lo que haría al sistema nada mantenible.

El punto clave que nos dice las razones por la que una clase puede cambiar va a depender del contexto en el que se va a dar uso a esa clase. Pongamos por ejemplo una clase que represente al motor de un coche. ¿Necesitamos conocer el régimen de revoluciones del motor?, ¿el peso?, ¿número de cilindros?, ¿presión del inyector de gasolina?, ¿o lo que nos interesa es simplemente poder arrancarlo y esperar que haga andar a un coche para llevaros de un sitio a otro? La respuesta a estas preguntas va a depender del contexto en el cual usemos la clase motor. No va a tener las mismas necesidades sobre esta clase un fabricante de coches que un usuario que usa el coche para ir de un sitio a otro. El fabricante de coches va a notar un número mayor de responsabilidades en el motor que el usuario del coche. Por tanto, para el fabricante, este principio recomendaría dividir la clase motor en otras más pequeñas que cumplan con las especificaciones de manera individual.

Veamos otro ejemplo típico de violación del SRP: Supongamos que tenemos la clase Employee (Empleado) en un sistema de gestión de una empresa cualquiera. Esta clase nos permite realizar las tareas esperadas sobre un empleado: Cargor y almacenarlo en una base de datos, generar la nómina, información básica del empleado, etc.

image

Ahora supongamos dos aplicaciones que hacen uso de la clase Employee. Una para ser usada por el departamento de recursos humanos para la gestión de las nominas del personal y otra para la gestión de los proyectos que lleva la empresa.

¿Podemos pensar que no se está siguiendo el SRP? Lo que sería lo mismo, ¿creemos que la clase Employee tiene más de una razón por la que pueda cambiar? A mi se me ocurren unas cuantas: Cambiar el formato de almacenamiento de base de datos, modificar los campos que definen a un empleado, cambiar la lógica de generación de nóminas, etc. Es decir, esta clase tiene varias responsabilidades: Es responsable de la persistencia de los clientes, responsable de caracterizar a un empleado, responsable de generar las nóminas, etc.

Las consecuencias de violar el SRP en este caso son dos:

  • La clase Employee tiene una dependencia con la clase AccountService para poder realizar el cálculo de las nóminas. Por tanto la aplicación de gestión de proyectos, a la hora de hacer el despliegue de esa aplicación, tambien debe incluir la librería que contiene esa clase aunque no la necesite.
  • Si alguna de las aplicaciones necesita implementar nueva funcionalidad y requiere cambiar la definición de la clase Employee, este cambio arrastraría cambios en el resto de aplicaciones que requerirían adaptarse a los nuevos cambios de la clase. En caso de olvidarnos, las consecuencias serían impredecibles.

Una mejora en el diseño sería separar las responsabilidades en clases distintas

image

Hemos creado dos nuevas clases: una para la gestión de nóminas y otra para el almacenamiento en la base de datos. Hay que fijarse en el detalle de que la clase Employee no depende de las nuevas clases EmployeeAccount y de EmployeeStorage, sino que la dependencia la tienen las aplicaciones.

En definitiva. Este principio es uno de los más simples de SOLID, y sin embargo de los más difíciles de implementar correctamente. Aplicando SRP,podemos alcanzar niveles más bajos de acoplamiento y una cohesión más alta del sistema.