Libro “Programming the Microsoft Bot Framework”

Por fin he logrado arañar el tiempo necesario para leer con detalle el libro “Programming the Microsoft Bot Framework. A Multiplatform Approach to Building Chatbots” (Microsoft Press/Pearson Education, 2018), escrito por mi buen amigo Joe Mayo, a quien sigo desde el ya lejano 2009, cuando publicó su excelente “LINQ Programming“. Recomiendo de corazón el nuevo libro a todo aquel que quiera adentrarse en esta novedosa tecnología de Microsoft, empezando desde los fundamentos básicos y llegando hasta temas avanzados como la creación de canales de control personalizados o la integración con servicios de voz, correo, SMS y web, así como con los Servicios Cognitivos de Microsoft (Microsoft Cognitive Services), que potencian las modernas aplicaciones basadas en Inteligencia Artificial. Puede encontrar la Tabla de Contenidos del libro y algunas páginas de ejemplo en la página del libro en Amazon.com.

Debo mencionar que el autor se puso de muy mala suerte y dos de las API en las que se apoyó para el desarrollo de los ejemplos incluidos en el libro, Wine.com y Groove, fueron abandonadas por sus respectivos creadores después del envío del libro a imprenta. Pero esto es algo que sucede con cierta frecuencia cuando se experimenta con tecnologías novedosas, y para mí ni siquiera es un problema – hacer un poco de abstracción nunca viene mal. No obstante, el autor ha reescrito todo ese código de ejemplo basándose en datos de prueba y la API de Spotify (que al fin y al cabo es el sustituto de Groove), respectivamente. El código fuente actualizado puede descargarse desde el blog de Joe Mayo.

Patrones en C# 7.0

“Early morning, April four
Shot rings out in the Memphis sky.
Free at last, they took your life
They could not take your pride.”
U2, “Pride (In the Name of Love)” (1984)

Otra de las novedades relevantes que introdujo C# 7.0 son los llamados patrones (patterns). Los patrones permiten, con una sintaxis concisa, comprobar que el valor de una expresión tiene una cierta “forma” y, en caso afirmativo, extraer información de esa expresión. El término “patrón” hace referencia al concepto de casamientoemparejamiento de patrones (pattern matching) tan popular en los lenguajes de programación lógica y funcional; aunque, como intentamos mostrar en un artículo anterior dedicado a la deconstrucción, por el momento las posibilidades que ofrece C# en esta área palidecen con respecto a las de tales lenguajes1.

En C# 7.0, los patrones pueden utilizarse para realzar la expresividad de dos construcciones del lenguaje:

  • El operador is de comprobación de tipos acepta ahora también en su parte derecha un patrón, además de un tipo.
  • Las cláusulas case de la sentencia switch ahora pueden especificar un patrón de emparejamiento en lugar de una constante.

Para los ejemplos de esta entrada nos centraremos en los nuevos usos del operador is; dejaremos los ejemplos de patrones en cláusulas case para nuestras próximas entregas, que estarán dedicadas íntegramente a las nuevas posibilidades que desde C# 7.0 ofrece la sentencia switch.

C# 7.0 incorpora tres tipos de patrones:

a) Los patrones constantes tienen la forma c, donde c es una constante, y comprueban que el valor de la expresión es igual a c. Por ejemplo:

    public static void Patterns1(object oint n)
    {
        if (o is null)
            Console.WriteLine("o is null");
        if (n is 27)
            Console.WriteLine("n is 27");
    }

El argumento de que is es más legible que == no es razón suficiente para convencerme a utilizar este tipo de patrón con el operador is. Tenga en cuenta el lector que la generación de código actual se apoya ciegamente en object.Equals() para la comparación, lo que puede dar lugar a pérdidas de rendimiento (por ejemplo, esto provoca dos operaciones de boxing al ejecutar la segunda sentencia if).

b) Los patrones de tipo tienen la forma T x, donde T es un tipo y x un identificador de variable; mediante ellos se comprueba si el valor de la expresión es de tipo T, y en caso afirmativo, se asigna dicho valor a la variable x de tipo T.

    public static void Patterns2(object o)
    {
        if (o is int n || (o is string s && int.TryParse(sout n)))
            Console.WriteLine(n);
        if (o is Person p)
            Console.WriteLine(p.FullName);
    }

Aquí si hay una economía de expresión importante sin comprometer la legibilidad, en mi humilde opinión. La primera parte del método del ejemplo imprime un valor en la consola si el parámetro suministrado es un entero (en cuyo caso, como “efecto colateral”, el valor entero es asignado a la variable n), o si el parámetro es una cadena que puede interpretarse como un entero (en cuyo caso, la cadena es asignada a la variable s, que es pasada a continuación a TryParse)2.

c) Finalmente, los patrones var tienen la forma var x, donde x es un identificador de variable; estos patrones casan incondicionalmente, y simplemente asignan el valor de la expresión a la variable x, que será del mismo tipo de la expresión.

    public static void Patterns3(object o)
    {
        if (o is var x)
            Console.WriteLine(x.GetType());
    }

Un caso particular a tener muy en cuenta al utilizar esta construcción es que en ella el patrón siempre casa, incluso si la expresión es null. Si el parámetro de entrada es null, el método del ejemplo lanzará NullReferenceException al intentar llamar a GetType(). No se me ocurre ninguna situación práctica en la que sea evidente la conveniencia de utilizar este tipo de patrón con el operador is; sin embargo, en una próxima entrega veremos un posible caso de uso, en combinación con la nueva cláusula when en la sentencia switch.

En las próximas entregas, que estarán dedicadas a la sentencia switch, arrojaremos más luz sobre el uso de estos tres tipos de patrones en las cláusulas case de la misma.

1 Los creadores de C# han prometido en varios foros que en el futuro se añadirán más tipos de patrones al lenguaje.

Nótese que la variable n se considera declarada tras su primera aparición, por lo que puede utilizarse como parámetro de salida de TryParse.


Referencia musical: Como esta entrada se escribe durante un día festivo dedicado a la figura de Martin Luther King, aprovecho para rememorar este tema dedicado a él de una banda imprescindible de las últimas cuatro décadas, U2,  que periódicamente nos demuestra que en el rock no todo son excesos e individualismo, sino que en ocasiones también puede encontrarse progresismo y compromiso social.