Creando un control de usuario reutilizable : El mapa de México en XAML en acción – Parte I

Hace algunas semanas creé el primer mapa de México en XAML.  Esta iniciativa animó a unos buenos amigos a perfeccionar esta primer aproximación del mapa de México en XAML para poder utilizarlo en nuestras aplicaciones Silverlight / WPF.  En este artículo veremos cómo crear un control de usuario reutilizable a partir de este XAML para poder usarlo en la plataforma Silverlight.

Para iniciar, es buena idea mostrar el mapa de XAML que usaremos.  El mapa de México en XAML lo pueden descargar del sitio de contenido de La Liga Silverlight.  Para mostrar el mapa estoy usando KaXaml, una excelente herramienta para edición de XAML alternativa a las ya conocidas herramientas como Visual Studio .NET 2008 o Expression Blend.

Muy bien, para iniciar debemos hacer notar los siguiente:

  • Cada estado de la república es un Path, el cual está envuelto en un contenedor <Canvas> con el nombre de cada estado en la propiedad x:Name, esto para poder tener control sobre cada uno de los estados (al darle click sobre cada uno de ellos o al mover el mouse encima de él). 32 estados = 32 Path = 32 Canvas.
  • El <Canvas> raíz de todo el mapa se llama MapaMexico.  Este <Canvas> es el contenedor de los 32 estados del país

Comenzando

Crearemos una aplicación de tipo Silverlight por medio de Visual Studio .NET 2008 y usando las plantillas.  A esta aplicación le llamaremos PortalMexico como a continuación se muestra en la ilustración:

Posteriormente seleccionamos la opción de crear una aplicación Web y cerramos la ventana de diálogo.  Una vez descargado el mapa de México en XAML, agregamos los dos archivos Mexico.xaml y Mexico.xaml.cs al proyecto de Silverlight.  Estos archivos son el diseño en XAML y el code-behind relacionado a ese XAML respectivamente.

El mapa de México en XAML ya incluye código preconstruído el cual colorea el estado de la república Mexicana que esté seleccionado a través del cursor del mouse.  Este código es bastante sencillo y se logra de la siguiente manera:

Vale la pena notar que el código itera sobre todos los estados (Canvas) que están en el Canvas raíz (MapaMexico) y por cada uno ejecuta el método RegisterEvents() que a continuación se muestra:

Como podrás notar, para los eventos MouseEnter (al entrar el cursor del mouse sobre el Canvas), MouseLeave (al salir el cursor del mouse del Canvas) y MouseLeftButtonUp (al hacer clic completo con el mouse sobre un estado (Canvas)) se asignan los manejadores de evento:

estado_MouseEnter

estado_MouseLeave

estado_MouseLeftButtonUp

…respectivamente.  Esto quiere decir que, estos métodos (denominados manejadores de eventos por tratarse de métodos que se ejecutan cuando se dispara un evento) se comparten para los 32 estados!  librándonos de escribir más código del necesario, el cual también pudo haber sido resuelto de la siguiente manera pero menos eficiente:

O peor aún:

Asimismo, cuando haces clic sobre un estado del mapa de México, te muestra el navegador un mensaje de alerta con el nombre del estado que has seleccionado.  De hecho lo que te muestra no es más que el nombre del Canvas que envuelve el Path que representa el estado, tal y como lo podemos apreciar en el siguiente fragmento de código tomado del code-behind del mapa:

Es notable la presencia de la clase HtmlPage de Silverlight, la cual encapsula toda la funcionalidad necesaria del HTML Bridge de Silverlight.  Esta característica permite manipular el DOM del navegador con .NET dentro del plugin de Silverlight!!!  Esta es uno de los componentes que en lo personal considero bastante potente en esta plataforma y motivo suficiente para incluir Silverlight en todos nuestros proyectos Web ya que si abrimos un poco nuestra imaginación podremos darnos cuenta que tal vez, y digo, tal vez… no volvamos a necesitar crear scripts de Javascript para nuestras aplicaciones Web.  Este tema merece artículos en específico que próximamente estarán publicados en este blog y en La Liga Silverlight.

Vale la pena probar el mapa de México en XAML tal cual se puede descargar de La Liga Silverlight, sin modificaciones para poder entender lo que hemos explicado hasta el momento.  Para que la aplicación PortalMexico inicie con Mexico.xaml en vez de con Page.xaml, simplemente modifica la siguiente línea en el archivo App.xaml.cs, el cual es el archivo de código global para toda nuestra aplicación Silverlight, y posteriormente ejecuta la aplicación presionando la tecla F5 o eligiendo la opción Start Debugging del menú Debug en Visual Studio .NET 2008 (por favor toma en cuenta el nombre de espacio Mexico que contiene la clase Mexico)

Muy bien, ya que explicamos la manera de cómo se están adjuntando los manejadores de eventos a los diferentes eventos para cada estado y qué sucede cuando un usuario hace clic en algún estado es momento de implementar nuestro control de usuario en la aplicación Silverlight:  Es hora de reutilizar Mexico.xaml en Page.xaml :)

C# a la alza, Basic a la baja

Según el índice TIOBE, este año cierra con una interesante estadística acerca de los lenguajes de programación más populares, en donde podemos ver repuntar a un C# al lugar número 6 a comparación del lugar 8 que tenía el año pasado, mientras que los lenguajes basados en Basic (no específicamente VB.NET, hay que aclarar…) van a la baja perdiendo dos posiciones y terminando en número 5 en este año que apenas termina.

El índice TIOBE muestra las estadísticas de popularidad de los lenguajes de programación, no precisamente cuál es mejor o peor.

Para ver la estadística completa lo pueden hacer aquí.

Qué les dice a ustedes esta estadística?

Saludos!

Guitar Hero World Tour v.s. Rock Band

Nuevo año, Nuevo vicio

A casi ya un año de haber estrenado el Rock Band pasó lo que tenía que suceder:  el pad azul de la batería partido a la mitad debido a la serie de golpazos a la Neil Peart, Matt Cameron o Lars Ulrich.  Y pues también pasó lo que tenía que suceder: reemplazar dicho control de batería por otro nuevo.  Para esto tenía varias opciones:

1.- Reparar el pad de la batería actual

2.- Comprar otra batería de Rock Band 1

3.- Comprar una batería de Rock Band 2

4.- Adquirir el Guitar Hero World Tour

La primer opción fue la más viable económicamente hablando no obstante las secuelas de buen uso no solo se ven reflejadas en el pad del color mencionado sino también en el pedal y en el plástico del pad amarillo.

La siguiente opción era la siguiente más viable económicamente hablando ya que hoy en día es fácil conseguir un control de batería del Rock Band 1 a unos 50USD; pero con esto de la crisis ya no era una opción tan atractiva ya que la batería sufre de diversos defectos de construcción y no está pensado para jugadores traumados intensos.

Ahora en el PDC 2008 tuve la oportunidad de probar la batería del Rock Band 2 y mi sorpresa fue más de decepción que de agrado:  tiene el mismo diseño con tan solo dos “mejoras”: los pads son de hule y el pedal tiene una placa de metal pero no deja de ser plasticosa y endeble.  Por si fuera poco aún no venden la batería por separado para Xbox 360 :(

Por todo lo anterior la opción tomada fue la no. 4, y este es el motivo principal de este post el cual va dirigido principalmente a todas aquellas personas que están en la disyuntiva hoy en día de “compro el Rock Band 2 o el Guitar Hero World Tour?”, “cuál de los dos es mejor?”, “son mejores los instrumentos del Rock Band o del GHWT?”, y un sinfín de preguntas.  Aquí van mis comentarios:

La Batería

  • La batería del Guitar Hero World Tour realmente sobrepasó mis expectativas ya que a primera vista se denota una construcción mucho más fuerte y de más resistencia que su contraparte del Rock Band 1 o 2.  Las patas y armadura de la batería es de metal lo cuál la hace más pesada y con esto el control se mantiene más fijo resultando en una experiencia de juego superior, además las patas tienen gomas antiderrapantes para que no se resbale tu control en pisos lisos.
  • Los 3 pads + los 2 platillos y el pedal ofrecen en conjunto una experiencia muchísimo más realística al estar tocando la batería ya que cada uno de esos componentes tiene su propia funcionalidad y sonido: los toms son toms siempre, el platillo amarillo es hi-hat siempre, etc. Esto difiere bastante a la batería del Rock Band 1 o 2 en donde el pad azul a veces es tom, a veces es platillo,etc.; lo mismo sucede con el pad verde.  Sin duda alguna la batería del GHWT es lo que debió ser la del RB desde un inicio. Felicidades Red Octane por tan fabuloso acierto.  El único contratiempo que le he encontrado es que si eres un asiduo jugador de Rock Band como yo entonces encontrarás que la distribución es un poco confusa al principio debido al platillo amarillo un poco elevado y la presencia del platillo naranja.  Es solo cuestión de acostumbrarse y al poco rato ya estarás tocando a más de 95% todas las canciones ;)
  • Los pads y platillos están recubiertos de hule macizo y la batería es realmente silenciosa.  No más vecinos simpáticos quejándose a tu puerta de tus fills metaleros en medio de una canción… no más.
  • La batería es wireless.  Pro: ya no tienes que andar cuidando a los malacopa de tus amigos de que no se tropiecen con el cable.  Contra:  Usa dos baterías AA lo cual seguramente drenará su carga en pocos días.  Te recomiendo que adquieras baterías recargables para que no sufra tu bolsillo.
  • La batería tiene entrada MIDI, lo cual significa que puedes conectar una batería electrónica con salida MIDI a este puerto y jugar con ella como si fuera el control.  Creo que esto sería la máxima expresión de experiencia en juegos de batería y la mejor manera de aprender a tocar tus canciones favoritas.
  • La batería es 100% compatible con el Rock Band… así que matas dos pájaros de un tiro ;)
  • Contras:
    • El pedal, ya que aunque se ve con una mejor construcción que el del Rock Band, aún sigue siendo de plástico y muy probablemente será el primer componente que se rompa a corto plazo.
    • Los platillos naranja y amarillo están muy cerca de los pads y llega a ser un poco incómodo su uso.

La Guitarra

  • Aunque no soy mucho de jugar ni como guitarra ni bajo, el control que trae el GHWT está excelentemente bien construido y es un poco más grande que el del GH3 o del RB.
  • La guitarra tiene una entrada RJ11… no tengo idea por qué si alguien sabe por favor ponga un comment :)

El Juego

  • Red Octane se sacó un 10 con el GHWT por el catálogo de canciones.  Es realmente SUPERIOR al del Rock Band 2:
      • Parabola, Schism y Vicarious de Tool !!! Esto es simplemente la razón suficiente para comprar el juego :D
    • Beat it de Michael Jackson…. auuuu!  Hasta el vocalista de la banda hace el Moonwalk
    • Love me two times de The Doors
    • Band on the run de McCartney y sus Wings
    • Escuela de Calor de Radio Futura ! (arriba los 80’s :) )
    • Hotel California de The Eagles
    • Un largo etcétera…
  • Puedes hacer fills en muchas partes de las canciones
  • Apariciones de diversas personalidades rockeras entre ellas Mr. Billy Corgan, Ted Nugent, etc.
  • Puedes personalizar mucho más a tus personajes (rostro, edad, actitud al iniciar, actitud al ganar y perder, etc.etc.etc)

Resumen

Si es tu primer juego musical no lo dudes y adquiere mejor GHWT y compra el DVD del Rock Band 2 por separado ya que el catálogo de canciones de Rock Band es mucho más amplio y cada semana se actualiza con nuevas adiciones:  GHWT no le llega a los talones a Rock Band en ese sentido, pero los instrumentos del GHWT son superiores a los de Rock Band.

Finalmente, toma en cuenta que muchas baterías de GHWT para Xbox 360 están descalibradas de fábrica, esto es, que su sensibilidad está muy baja y tienes que literalmente azotar los platillos (principalmente el naranja) para que registre el golpe.  Exige en la tienda donde lo compres o en la carta a Santaclós que te la calibren (se hace por medio de un cable MIDI-USB y un software que Activision liberó hace poco).  Ojo: es solo para Windows y el cable lo da Activision de manera gratuita pero desgraciadamente aún no hay soporte para México y/o Latinoamérica :@

Keep on rockin’ in the free world.

Salu2!

Transacciones en Workflow Foundation

Transacciones en Workflow Foundation

Muy frecuentemente en nuestras aplicaciones necesitamos incorporar algún tipo de mecanismo que nos asegure que los datos que estemos usando hayan sido grabados de manera correcta y consistente. Bienvenidos a las Transacciones, las cuáles -en el contexto de WF- las podemos utilizar como medio para asegurarnos que efectivamente la información haya sido actualizada tal y como lo esperamos y en todo caso de alguna falla la información no quede incompleta o inconsistente.

Pero ¿qué es una Transacción?

Una transacción la podemos definir como una unidad de trabajo en donde se ejecutan exitosamente todas las tareas que se incluyen en la transacción, o no se ejecuta ninguna.

En WF podemos incorporar en nuestros flujos de trabajo dos tipos de transacciones: Transacciones de tipo 2PC (Two Phase Commit) y Transacciones Compensables. En este capítulo explicaremos y mostraremos el uso de cada una de ellas para nuestras aplicaciones.

Transacciones Two Pase Commit

Este tipo de transacción es aquella que está coordinada a través de un administrador el cual su objetivo es determinar si las acciones y datos relacionados con la transacción se deben aplicar en un momento específico. Ese momento lo determina el administrador tomando en cuenta si todos los recursos relacionados en la transacción “votan” para que la transacción continúe o se deshaga en su totalidad.

Las transacciones de esta categoría deben tener las propiedades ACID, las cuales son por sus siglas en inglés: Atomicity, Consistency, Isolation y Durability.

La prueba del “Ácido” para las transacciones

Como describimos en el párrafo anterior, las transacciones de tipo Two Phase Commit deben tener ciertas propiedades para que su comportamiento sea el esperado y funcionen correctamente. Estas propiedades las explicaremos a continuación:

Atomicidad (Atomicity). Esta propiedad indica que todas las operaciones relacionadas con la transacción se han ejecutado en su totalidad o no se han ejecutado, es decir, esta es la propiedad que nos asegura que un proceso de actualización de datos no puede quedar a medias provocando que nuestros datos queden en un estado incorrecto. Un ejemplo en donde podemos apreciar esta propiedad es cuando realizamos un retiro de dinero en un cajero automático: solicitamos cierta cantidad y esa cantidad nos es dada en efectivo. Ahora bien, imaginemos el caso en el que la transacción no fuera atómica y que ocurriese alguna falla en la transacción, digamos que el cajero automático no tenga dinero suficiente para nuestro retiro. Terminaríamos con un saldo menor e incorrecto en nuestra cuenta de ahorros pero con nada de dinero en efectivo en las manos. O tal vez el pago de un servicio en línea por medio de una tarjeta de crédito. En fin, ejemplos podríamos decir muchos. Gracias a la propiedad de atomicidad en las transacciones nos aseguramos que en algún caso de error en los ejemplos anteriores los datos relacionados no se vean afectados.

La Atomicidad nos asegura que todas las operaciones en una transacción se realizan todas o no se realiza ninguna.

Consistencia (Consistency). Esta propiedad indica que los datos envueltos en la transacción se deben mantener consistentes. Si tomamos como ejemplo una base de datos relacional esto indica que la transacción no debe romper ninguna restricción que haya sido declarada. Tal es el caso de una transacción que requiere insertar un registro en dos tablas con una relación padre-hijo por ejemplo las tablas Cliente y Factura. Si la transacción inserta exitosamente un registro en la tabla Factura pero falla al insertar el registro correspondiente en la tabla Cliente, la integridad de la base de datos se vería afectada y la transacción –gracias a la propiedad de Consistencia- es echada para atrás.

La Consistencia nos asegura que la integridad de los datos se mantendrá una vez realizada la transacción y que no se romperá ninguna restricción.

Aislamiento (Isolation). Esta propiedad nos permite que las operaciones en una transacción no afecten a otras. Existen diferentes tipos de nivel de aislamiento para las transacciones que podemos utilizar según el contexto y las necesidades propias de la aplicación y/o flujo de trabajo que estemos desarrollando.

La propiedad de Aislamiento nos asegura que las operaciones de una transacción no pueden afectar a otras.

Durabilidad (Durability). Esta propiedad nos asegura que una vez realizada la transacción los datos modificados o agregados quedarán guardados de una manera no-volátil y estarán disponibles aún si ocurriese una falla en el sistema. Esto es cierto aún si la falla ocurriera 1 milisegundo después de haber sido realizada la transacción.

La Durabilidad nos asegura que una vez realizada la transacción los datos quedarán guardados aunque falle el sistema.

Ejemplo

Veamos ahora cómo implementar transacciones de tipo Two Phase Commit en nuestros flujos de trabajo utilizando Workflow Foundation. Cabe mencionar que el siguiente ejemplo supone la existencia de la base de datos Northwind implementada en SQL Server Express de manera local y supone también que se ha configurado el servicio SqlWorkflowPersistenceService usando una base de datos también local llamada WorkflowStore usando los scripts que se incluyen con el .NET Framework 3.0 presentes en [Carpeta de Windows]\Microsoft.NET\Framework\v3.0\Windows Workflow Foundation\SQL\EN. Para mayor información acerca de SqlWorkflowPersistenceService consulta el capítulo “Persistencia” en esta obra.

Con Visual Studio .NET abierto, hagamos un nuevo proyecto de tipo Sequential Workflow Console Application. Con el diseñador de WF en la pantalla arrastremos y coloquemos una actividad de tipo TransactionScope tal y como lo muestra la siguiente figura:

La actividad TransactionScope es una actividad compuesta, es decir, que puede contener una o más actividades dentro de ella. Todas las actividades que definamos dentro de la actividad TransactionScope participarán en la misma transacción. Una de las propiedades más importantes de esta actividad es TransactionOptions.IsolationLevel la cual indica el nivel de aislamiento que esta transacción tendrá al ejecutar todas sus operaciones siendo su valor predeterminado Serializable (el nivel de aislamiento más restrictivo). A continuación en la tabla 1 se enlistan los diferentes niveles de aislamiento disponibles:

Nombre

Descripción

Serializable

Los datos no aplicados pueden ser leídos pero no modificados, y no se pueden insertar datos durante la transacción

RepeatableRead

Los datos no aplicados pueden ser leídos pero no modificados. Se pueden insertar datos durante la transacción

ReadCommitted

Los datos no aplicados no pueden ser leídos durante la transacción pero sí pueden ser modificados

ReadUncommitted

Los datos no aplicados pueden ser leídos y modificados

Snapshot

Los datos no aplicados pueden ser leídos. Antes de modificar los datos verifica si otra transacción ha modificado los datos después de que se leyeron los datos, si es así arroja una excepción

Chaos

Los cambios pendientes de transacciones que tengan un nivel de aislamiento superior no pueden ser reemplazados

Unspecified

Otro. Sin embargo este nivel no puede ser asignado de manera manual

Tabla 1. Niveles de aislamiento para las transacciones

No podemos colocar una actividad TransactionScope dentro de otra

Para continuar con el ejemplo usaremos una actividad de tipo Code y la colocaremos dentro de la actividad transactionScopeActivity1. Es en esta actividad en donde declararemos el código que deseamos que participe en la transacción así que asignemos un método llamado “Transaccion” en la propiedad ExecuteCode de la actividad codeActivity1. En este método definamos el siguiente código:

Asimismo, en nuestra clase del flujo de trabajo definamos una propiedad pública de tipo int llamada RegionID. Esta propiedad nos servirá como mecanismo para enviar parámetros a nuestro flujo de trabajo específicamente al comando de SQL que vamos a ejecutar.

Ya que vamos a demostrar el poder y comportamiento de las transacciones es buena idea agregar un Fault Handler a nuestro flujo de trabajo para que capture cualquier tipo de excepción, es por eso que vamos a usar la clase System.Exception. En el fault handler agregaremos una actividad de tipo Code la cual ejecutará el método ErrorHandler para mostrar un mensaje amigable al usuario. La siguiente figura muestra el diseñador de Workflow Foundation en la vista de Fault Handlers.

El código del método ErrorHandler será el siguiente:

Una vez hecho lo anterior, asignemos un método manejador para el evento Completed de nuestro flujo de trabajo. Esto lo podemos lograr haciendo clic en el botón de eventos en la ventana de propiedades del flujo de trabajo tal y como lo muestra la siguiente figura:

El nombre del método será WorkflowCompleto y tendrá el siguiente código:

Por último debemos modificar el código que inicia la instancia del flujo de trabajo en la aplicación de consola. Para esto modifiquemos el código incluido en Program.cs para que tenga el siguiente código antes de invocar instance.Start().

Muy bien! Hemos preparado nuestro flujo de trabajo para que agregue una nueva región a la table Region de la base de datos Northwind dentro de una transacción. Probemos nuestro proyecto ejecutándolo con Ctrl + F5 y pasemos la región número 5 como parámetro. En este caso la operación de inserción es exitosa y nuestro flujo de trabajo nos despliega el siguiente mensaje en la consola:

Finalmente debemos comentar que en caso de alguna falla la actividad TransactionScope se encargará de echar para atrás todos los cambios dejando los datos en un estado consistente.

Transacciones Compensables

Este tipo de transacciones nos permiten definir una serie de operaciones a ejecutar cuando la ejecución de la transacción falla, es decir, la compensan. A diferencia de las transacciones de tipo Two Phase Commit en donde las operaciones se ejecutan o no se ejecutan, en una transacción compensable las operaciones sí son ejecutadas y en todo caso de una falla esas operaciones no son echadas para atrás sino que se ejecutan algunas otras acciones que complementan o “compensan” esa falla. Para dar un ejemplo de esto podemos mencionar el caso cuando pagamos un excedente de algún servicio, en donde la operación compensatoria es emitir una nota de crédito o cupón para hacer uso de ese beneficio posteriormente. Cabe mencionar que este tipo de transacciones son útiles cuando ya no podemos echar para atrás los cambios producidos por la misma transacción o por otra.

Ejemplo

Para demostrar este tipo de transacciones retomemos el proyecto de ejemplo anterior, sin embargo en vez de usar una actividad de tipo TransactionScope utilizaremos la actividad CompensatableTransactionScope la cual nos permite definir una serie de actividades a ejecutar como parte de esa transacción tal y como ocurre con su contraparte explicada en la sección anterior.

Asimismo, para esta demostración provocaremos un error a propósito después de ejecutar la transacción que da de alta regiones en la base de datos Northwind. La actividad que arrojaremos será de tipo System.Exception. La siguiente figura muestra el diseñador de Workflow Foundation con los cambios necesarios:

Debemos notar que el tipo de transacción que ejecuta la actividad codeActivity1 ahora es de tipo CompensateTransactionScope y que agregamos una actividad de tipo Throw después de la transacción para provocar el error mencionado.

Para indicar la serie de actividades compensatorias a ejecutar debemos definirlas en la vista de la actividad compensationHandlerActivity1. Esto lo podemos lograr haciendo clic la opción apropiada del menú desplegable de la transacción compensatableTransactionScopeActivity1 tal y como lo muestra la siguiente figura:

En la actividad compensationHandlerActivity1 añadiremos una actividad de tipo Code. Esta actividad nos servirá para ejemplificar la compensación de una transacción cuando esta falla. A esta actividad le relacionaremos el método Compensa y en este método solamente agregaremos el siguiente sencillo código:

Finalmente, en la vista de Fault Handlers agregaremos una actividad de tipo Compensate, la cual indica por medio de su propiedad TargetActivityName la actividad que se quiere compensar, en nuestro caso será la actividad compensatableTransactionScopeActivity1. Esta actividad nos servirá para indicar de manera manual que queremos realizar la compensación correspondiente. La figura 7 muestra el diseñador de Workflow Foundation con la vista de Fault Handlers:

Resumen

En este capítulo vimos los dos tipos de transacciones que podemos incorporar en nuestros flujos de trabajo. Asimismo dimos ejemplos y escenarios en donde pueden ser implementados y la manera sencilla y amigable que disponemos en Workflow Foundation para hacer uso de ellos.

Este artículo fue creado para el curso Desarrollador .NET de la revista Users.  http://desarrollador.redusers.com/

FIL.2008 = new FIL.2008();

Los ojos de toda América Latina están puestos en la emblemática ciudad de Guadalajara, Jalisco, México debido a la más reciente edición de la Feria Internacional del Libro que en esta ciudad se lleva a cabo desde hace más de un par de décadas.  En especial esta edición me parece de lo más interesante -y obligada para todas aquellas personas que gustamos de la letra-, ya que el país invitado en esta ocasión es Italia; país de grandes iconos de literatura moderna y clásica, país del buen comer y por qué no, del buen beber.

Sin embargo, no solamente se engalana por la presencia del mediterráneo país sino también por una serie de eventos y presentaciones efectuadas por grandes luminarias nacionales y extranjeras en el plano literario.  Por ejemplo, tendremos el estreno mundial de la últimamente multi-mencionada obra operística “Santa Anna” de Carlos Fuentes, gran escritor mexicano nacido -por accidente- en Panamá, acerca de los últimos años de vida de este personaje ligado íntimamente a la historia de nuestra nación.  También tendremos diversos estrenos en papel y tinta como por ejemplo la más reciente obra del maestro Monsiváis, el nuevo libro de Martha Chapa -ipso facto antojable al simple oído- acerca de los Tacos de México (de dónde más caray…), diferentes lecturas públicas de poesía llevadas a cabo por personas como José Emilio Pacheco, entre otros momentos invaluables.

Un plato fuerte de esta edición será el encuentro de magníficos moneros como Sergio Aragonés, Rius y Trino (no me lo puedo perder :) ), y claro está, la estupenda oportunidad de adquirir algunos buenos ejemplares para las bibliotecas personales a excelentes precios (espero).  Toda la semana que sigue, a partir del día de mañana podremos disfrutar de este espléndido evento.  Si estás en la ciudad, o vienes durante la siguiente semana por negocios / placer: aprovecha.

Más que nunca me da mucha alegría vivir en esta ciudad, que, como en pocas, se pueden disfrutar eventos de este calibre cultural de gran importancia internacional.

Quien tenga oídos para oír, que oiga.

Saludos!

Reunión de la Comunidad Guadalajara .NET en el ITESO y premier de La Liga Silverlight

 

El próximo día 4 de diciembre, de 3:00pm a 6:00pm tendremos una reunión en el ITESO por parte de la Comunidad Guadalajara .NET, en donde –como siempre- platicaremos diversos temas de suma importancia del mundo de la plataforma Microsoft.

Por mi parte estaré platicando acerca de Silverlight!… Así que para todos aquellos que estén interesados en asistir revisen la página de la comunidad en donde publicaremos más información al respecto y la agenda final en los próximos días.

Asimismo, dentro de la misma reunión tendremos la premier de La Liga Silverlight:  La primer comunidad MSDN de habla hispana acerca de Silverlight.  Si quieres conocer de qué se trata y/o cuál es el objetivo de este gremio !no faltes!, habrá una sesión de preguntas y respuestas y algunos regalillos sorpresas.  Ojo: no es una reunión de La Liga Silverlight, esa la tendremos próximamente! ;)

Así que no hay pretextos!  Nos vemos en el ITESO !!!

De traumas, estrés y otras incomodidades

No hay nada que me estrese más que mudarme, sin embargo, lo he hecho muchas veces.  No sé si sea el duendecillo de la costumbre a algún lugar, o el tener que bucear entre escombros de bobadas y recuerdos inútiles lo que me pone los nervios de punta.

No obstante, es y será siempre un buen momento para inventariar y re-considerar nuestros tesoros personales.  Yo por mi parte me considero un melómano-bibliófilo-cinéfilo, y por lo tanto –analizando bien este asunto- lo que más me incomoda y preocupa por encima de muchas otras cosas es que mis discos, libros y películas no les afecte el cambio de domicilio.  Creo que simplemente por estar guardando los cd’s en una caja atascada ya rompí como 5 cajas :(

También una de las cosas que es digna de mis más terribles fiacas es el re-acomodo de tooooodo y peor si no tendrás el lugar adecuado o de buen tamaño como lo tenías antes.

Y qué me dicen de los nuevos vecinos?  Si de por sí es complicada la convivencia con personas cercanas y queridas, aún más lo es el tratar con criaturas totalmente extrañas y ajenas.  Claro está, siempre existirá desde la típica señora con perfil de detective hasta las familias que viven en comuna dentro de la misma casa.

En fin, siempre son buenos los cambios.  Siempre es bueno sacudirse la mala energía que nos ahoga y detiene, ya que esto siempre nos llevará a nuevos buenos caminos.

Sino, a ver.. Cómo termina The Godfather Parte 1??? Claro! Con una mudanza.  La mudanza representa en la película el fin de una etapa en la vida de la familia Corleone para comenzar otra con nuevos bríos y oportunidades, sino, no hubiera hecho toda la fortuna e imperio Michael Corleone… o sí???  Por qué estoy escribiendo esto?

No lo sé.  Pero lo que sí sé es que todo cambio es bueno,… aunque el cambio de domicilio sea a solo 10 minutos :P ….  La mala vibra se queda y nosotros nos vamos.  Ah! y también se mudan conmigo “Family Guy meets the masked Chamulas”.

Salu2!

Nuevo dashboard de Xbox 360

Si tienes Xbox 360 y Xbox Live seguramente ya descargaste el nuevo dashboard de la consola, o como Microsoft lo promociona: “La experiencia Xbox 360”.

En lo personal me gustó muchísimo más que el dashboard tan horrendo poco amigable que teníamos antes, ah! y qué tal el cinemático de inicio??? WOW… un aplauso Microsoft!

<Pero>Ok, los Avatars a simple vista son una copia flagrante de los Mii’s de la consola Wii de Nintendo.  <Ok>Sin embargo hay diversas personalizaciones que puedes hacer como cambiarles sus ropitas y otras monadas</Ok></Pero>

En fin, en general una gran mejora al querido Xbox que sin lugar a dudas les quedó espectacular.

Por cierto, alguien ya jugó Rock Band 2 con la batería del Guitar Hero World Tour???  Alguien tiene algo bueno o malo qué decir al respecto?

Salu2!

Generación Grunge en su máxima expresión…

Solo si han vivido debajo de una piedra no sabrán que el Grunge fue un movimiento que transformó la música a como la conocemos actualmente.  Si fuiste adolecente en la década de los noventas (especialmente a principio de), sabrás perfectamente de lo que estoy hablando.  No niños/as no todo en la vida es U2, Rasmus o Amandititititita: NO.

Y bueno, como buen exponente de esa época y de la Generación X me gustaría mostrarles un pequeño tesoro para que se deleiten sus pupilas.  Considerados como Patrimonio Rockero de la Humanidad por la UNESCO, este par de drumsticks engalanarán una de las paredes de mi nuevo hogar:

Así es, un par de drumsticks autografiados por el mismísimo, incomparable, grandioso, poderoso y legendario Matt Cameron; especialmente para mí =D.  Que cóooomo los conseguí??? Eso es secreto de Estado.  Es como decirles cómo ganar la lotería, o decirles exactamente cuántos vuelos de Aeroméxico llegarán retardados hoy (sí, son más de 20 :) ),…. no no no.

Salu2! :)

Políticas en Workflow Foundation

Políticas en Workflow Foundation

Como ya hemos visto en capítulos anteriores, una regla es un conjunto de expresiones condicionales que nos permiten evaluar ciertos valores para determinar un resultado verdadero o falso. En este capítulo profundizaremos un poco más acerca de las reglas y su relación que guardan con los Conjuntos de Reglas o RuleSet, usado por la actividad Policy.

La actividad Policy y los Conjuntos de Reglas

La actividad llamada Policy nos permite en un flujo de trabajo evaluar un RuleSet, el cuál es una colección de reglas relacionadas o no entre sí.

El Conjunto de Reglas o RuleSet es una colección de reglas relacionadas o no entre sí. Nos referimos a que dos o más reglas están relacionadas entre sí cuando ellas leen o actualizan el mismo campo o propiedad de alguna clase.

Veamos ahora en la práctica cómo podemos utilizar esta actividad dentro de nuestros flujos de trabajo en Workflow Foundation.

Para comenzar, abramos Visual Studio .NET si es que no está actualmente abierto. Posteriormente crearemos un nuevo proyecto llamado PolicyWF de tipo Sequential Workflow Console Application tal y como lo muestra la siguiente figura:

Ya que deseamos mostrar la funcionalidad de la actividad Policy, junto con la evaluación de su RuleSet relacionado, necesitamos escribir un poco de funcionalidad para nuestro flujo de trabajo. Sin embargo, esta es una tarea muy sencilla: vamos a crear cuatro variables públicas de tipo int llamadas a, b, c y d. Estas variables (comúnmente denominados “campos”) le permitirán al RuleSet evaluar sus reglas y su posible re-evaluación. Muy bien, manos a la obra. Hagamos clic en el botón “View Code” de la ventana Solution Explorer de Visual Studio.NET para desplegar la vista de código de nuestro flujo de trabajo. Posteriormente escribamos el código para crear esas variables a nivel de clase:

Ahora, necesitamos asignarle un valor a cada variable para que las reglas en el RuleSet que vamos a crear lean esos valores. Esto lo podemos hacer inmediatamente después de la invocación al método InitializeComponent() en el constructor de la clase:

El siguiente paso es seleccionar la actividad Policy del Toolbox y arrastrarla al diseñador de Workflow Foundation. Cuando la actividad es colocada en el diseñador, automáticamente Visual Studio .NET le asigna un nombre el cual en nuestro caso eso policyActivity1. Asimismo esta actividad muestra un símbolo de admiración en color rojo, esto significa que la actividad aun no ha sido configurada (tal y como sucede al configurar una actividad de tipo IfElseActivity como vimos en los capítulos anteriores).

Como podemos apreciar en la ventana de propiedades, la actividad policyActivity1 tiene una propiedad llamada RuleSetReference, la cual indica el nombre del RuleSet que deseamos asociar a esa actividad. Ya que en este caso acabamos de crear un proyecto nuevo no tenemos un RuleSet definido. Esto lo podemos hacer en la caja de diálogo llamada “Select Rule Set”, la misma que es desplegada al hacer clic en el botón con tres puntos “…” en la propiedad RuleSetReference de policyActivity1 tal y como lo muestra la siguiente figura:

Esta caja de diálogo nos permite crear, modificar o eliminar los Conjuntos de Reglas que hayamos definido dentro de nuestro proyecto. Ya que no tenemos nada definido aún, es buena idea hacer clic en el botón “New…” para poder crear un nuevo RuleSet. Al hacer clic en este botón Visual Studio .NET despliega la caja de diálogo llamada “Rule Set Editor” la cual nos permite establecer las reglas que componen ese RuleSet, su configuración de encadenamiento o Chaining (el mismo que explicaremos más adelante), su prioridad, su comportamiento de re-evaluación, la expresión condicional, las acciones a ejecutar si esa expresión es verdadera (THEN) y las acciones a ejecutar si esa expresión resulta ser falsa (ELSE). Podemos apreciar esta caja de diálogo en la siguiente figura:

Es tiempo de crear la primera regla de nuestro RuleSet. Hagamos clic en el botón “Add Rule”. Al hacer clic en este botón, es creada una nueva regla con nombre predeterminado “Rule1”. A esta regla le asignaremos una prioridad con valor 100, dejaremos el resto de sus propiedades con el valor por defecto y la condición la expresaremos como “Si a es igual a 20…”, es decir:

Ahora bien, escribamos la expresión para cuando esa condición sea verdadera. Queremos que en el caso que a sea 20, entonces d sea 50: esto lo haremos en la caja de texto para THEN:

Hemos completado la primera regla de nuestro RuleSet. La regla completa la podemos ver en la siguiente figura:

La prioridad de las reglas permite al motor de reglas de Workflow Foundation determinar qué reglas se evalúan primero y cuáles después. En un RuleSet, las reglas serán ejecutadas en el orden del valor de prioridad que tengan asignadas, siendo la regla que tenga el valor más alto la que se evaluará primero y así consecutivamente.

Continuemos ahora agregando una segunda regla a nuestro RuleSet, haciendo clic en el botón “Add Rule” de la barra de botones para crear una regla llamada Rule2. La expresión condicional para esta regla será “Si b es igual a 1, a será 20 de lo contrario d será 90”, de ahí que la condición será:

El bloque THEN:

Y la expresión ELSE:

A esta regla le asignaremos la prioridad con un valor de 99. Agreguemos otra regla llamada Rule3 a nuestro RuleSet con prioridad 98 y con la expresión condicional: “Si d es 50 entonces c es 100 de lo contrario c es 60”. La siguiente figura muestra las reglas Rule2 y Rule3 terminadas:

Muy bien, es hora de poner en marcha nuestro RuleSet y comprobar su funcionamiento, para esto agregaremos una actividad de tipo Code después de la actividad policyActivity1 en nuestro diseñador. Le asignaremos como valor “DisplayResults” en la propiedad ExecuteCode en la ventana de propiedades de esta nueva actividad (codeActivity1). La siguiente figura muestra el diseñador de Workflow Foundation incluyendo esta nueva actividad:

Después de teclear <Enter> Visual Studio .NET nos mostrará el código fuente de nuestro flujo de trabajo y el cuerpo del método DisplayResults(). Completemos el código:

Este código mostrará en la consola el valor de cada una de los campos que creamos.

Ejecutemos el código y veamos el resultado:

¿Por qué los resultados son así? Es muy importante hacer un alto y hacer notar la Dependencia que tienen las reglas Rule1 y Rule2 y Rule 3 entre sí.

Podemos decir que, existe Dependencia entre reglas cuando una regla modifica un campo o propiedad que otra regla está leyendo como parte de su expresión condicional, tal y como sucede en Rule1 y Rule2 en donde Rule1 está evaluando el valor de a y asimismo Rule2 está modificando el valor de a.

Asimismo, Rule3 tiene dependencia tanto con Rule1 y Rule2:

Con Rule1 porque modifica el valor de d cuando su expresión condicional es verdadera (THEN) .

Con Rule2 porque esta modifica el valor de d cuando su expresión es falsa (ELSE).

En este caso específico, el motor de reglas de Workflow Foundation usa el concepto de encadenamiento de reglas o Chaining, para determinar si una regla se re-evalúa como resultado de la modificación de un campo o propiedad que otra regla haya modificado.

Chaining es el proceso en donde el motor de reglas de Workflow Foundation re-evalúa las reglas dependientes entre sí, encadenando efectivamente una con otra hasta que todas las reglas de un RuleSet son evaluadas. Hay tres tipos de Chaining: Implícito, Basado en Atributos y Explícito.

Tipos de Control de Chaining

A continuación se explican cada uno de los tipos de Chaining que el motor de reglas de Workflow Foundation implementa:

Implícito (default)

En este tipo de Chaining el motor de reglas de Workflow Foundation es el responsable de asegurarse que las reglas se evalúen y re-evalúen según sus dependencias entre sí. Este es el mecanismo de Chaining por defecto ya que es el más sencillo de usar para nosotros los desarrolladores ya que el motor de reglas se encarga de todo el proceso de encadenamiento.

Basado en Atributos

Este tipo de Chaining utiliza atributos especiales con los que podemos decorar nuestros métodos para determinar si un campo o propiedad será modificado después de ejecutar dicho método. Este mecanismo es usado para escenarios de Chaining más sofisticados y complejos. Los atributos usados en este tipo de Chaining son los siguientes:

  • RuleRead. Le indica al motor de reglas que un campo o propiedad está siendo leído.
  • RuleWrite. Le indica al motor de reglas que un campo o propiedad está siendo modificado.
  • RuleInvoke. Le indica al motor de reglas que el método especificado será invocado, el cuál muy probablemente esté a su vez decorado con ReadWrite. Este atributo es usado cuando un método ejecuta otro.

Explícito

Este tipo de Chaining hace uso de la cláusula Update, la cual le indica de inmediato al motor de reglas que un campo o propiedad ha sido modificado. Prácticamente este mismo comportamiento lo obtenemos con el Chaining implícito o por medio del atributo ReadWrite, sin embargo este mecanismo es necesario cuando estamos invocando un método o función que no hayamos escrito nosotros en nuestras reglas. Por ejemplo:

Ejemplo

Modifiquemos nuestro proyecto agregando un método llamado Modifica_A() que reciba como parámetro un entero. A este método lo decoraremos con el atributo RuleWrite(“a”) para indicar al motor de reglas que este método está actualizando el valor del campo a. El código es el siguiente:

Asimismo, modifiquemos la acción THEN de Rule2 para invocar el método Modifica_A() enviando como parámetro el valor 20 en vez de hacer la modificación directamente en el código de la acción:

El resultado será el mismo. Ahora quitemos el atributo [RuleWrite(“a”)] del método Modifica_A(). Ejecuta de nuevo el proyecto. ¿Qué sucede?

Tipos de Comportamiento de Chaining

Tenemos la posibilidad de modificar el comportamiento de Chaining para nuestro RuleSet, ya que existen tres tipos de comportamientos los cuales están listados en la siguiente tabla:

Tipo de Comportamiento

Descripción

Encadenamiento Completo (Full Chaining)

Este es el comportamiento por defecto

Solo Actualización Explícita (Explicit Update Only)

Como su nombre lo indica este comportamiento desactiva todos los atributos y el Chaining implícito y únicamente usará las cláusulas Update para llevar a cabo el proceso de Chaining.

Secuencial (Sequential)

Con este comportamiento, el motor de reglas evalúa las reglas una sola vez en el orden indicado por su prioridad.

Debemos tener especial cuidado al seleccionar tanto el tipo de control como el tipo de comportamiento de Chaining, ya que podríamos llegar a una situación de un bucle infinito en donde una Regla A modifique un valor que cause que otra Regla B se evalúe, y esta a su vez modifique un campo que Regla A utiliza.

Ejemplo de Comportamiento Secuencial

Modifiquemos el comportamiento del Chaining en nuestro RuleSet a Sequential. Esto lo podemos lograr en la caja de diálogo “Rule Set Editor” y seleccionando apropiadamente el valor de la lista desplegable. Hagamos clic en el botón OK y otra vez OK. Ejecutemos otra vez nuestro proyecto. El resultado ahora será:

Comportamiento de Re-evaluación

Existen dos tipos de comportamientos de re-evaluación para las reglas dentro de un RuleSet: Siempre (Always) o Never (Nunca).

Always es el comportamiento por defecto en donde la regla se re-evaluará tantas veces como sea necesario según la dependencia y el mecanismo de Chaining. Por el otro lado, Never como su nombre lo indica evaluará solo la primera vez la regla pero nunca se re-evaluará. Podemos hacer uso de este mecanismo para evitar bucles infinitos entre las reglas.

La cláusula Halt

Esta cláusula sirve para terminar la ejecución del RuleSet. La podemos equiparar a la función break dentro de un bucle for de Visual C# ya que nos sirve para regresar el control al código origen cuando cierto objetivo ha sido logrado dentro de nuestro RuleSet y ya no sea necesario ejecutar las demás reglas.

Resumen

En este capítulo profundizamos acerca de las reglas y vimos el uso de la actividad Policy. También se explicó el término RuleSet y vimos en la práctica cómo crean. Posteriormente hablamos del mecanismo de Chaining y sus diversos comportamientos y opciones incluídos en el motor de reglas de Workflow Foundation para resolver escenarios sencillos o más sofisticados en nuestras aplicaciones que necesiten usar este motor.

Este artículo fue creado para el curso Desarrollador .NET de la revista Users.  http://desarrollador.redusers.com/