Weblogs Código

Blog Bitix

El editor, explorador e IDE GraphiQL para una API con GraphQL

agosto 19, 2018 09:00

GraphQL

Hace ya un tiempo escribí una serie de artículos sobre GraphQL para desarrollar una API en una aplicación como alternativa a desarrollarla basada en REST. En esa serie de artículos explicaba varios conceptos básicos e introductorios pero suficientes para desarrollar una API completamente funcional con GraphQL usando el lenguaje de programación Java. Sin embargo, sobre algunos otros conceptos y posibilidades de GraphQL no había escrito.

Uno de esas posibilidades de GraphQL es la herramienta GraphiQL que es un editor interactivo para construir consultas y explorar la API. Una de sus mayores ventajas es que ofrece asistencia contextual y proporciona mensajes de error en caso de que la sintaxis de la consulta sea errónea. En los artículos que escribí con anterioridad los ejemplos los hice usando el comando curl. Ahora que he visto y aprendido algunas pocas cosas más de GraphQL en este artículo explico como usar la herramienta GraphiQL como alternativa a curl.

GraphiQL en casi un IDE para crear consultas de GraphQL, está basado en JavaScript, se ejecutan en el navegador y para su funcionamiento solo hay que proporcionarle el endpoint de la API a probar.

En la página de este tutorial se explica cual es el código HTML necesario para el editor GraphiQL. Básicamente es un HTML que hay colocar en el caso de una aplicación Java en el directorio web de la aplicación, utilizando la página por defecto index.html se carga al acceder a la dirección http://localhost:8080/.

En el código del archivo index.html del ejemplo he tenido que cambiar estas dos cosas, una de ellas es utilizar un CDN para los recursos de GraphiQL y la otra en la función graphQLFetcher es que en este ejemplo el endpoint es /library en vez de /graphql.

Varias de las mismas consultas que hacía con curl en otros artículos es posible lanzarlas con GraphiQL. Es posible formatear correctamente una consulta con el botón prettify. Con en el enlace de documentación se puede explorar los tipos definidos en la API. Con funciones similares a un IDE ofrece errores de sintaxis, asistencia contextual e historial de consultas, en definitiva es una gran mejora sobre curl y su incorporación a la aplicación es muy sencilla.

El editor GraphiQL para una API con GraphQL

El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub y probarlo en tu equipo ejecutando el comando ./gradlew run.

» Leer más, comentarios, etc...

Blog Bitix

Sobre las competiciones deportivas de videojuegos o eSports

agosto 15, 2018 08:30

El sector de los videojuegos es una industria que mueve miles de millones de euros en todo el mundo mayor que sectores con más historia como la industria del cine, los juegos triple AAA poseen inversiones y desarrollos cinematográficos. Los computadores y aparatos electrónicos están muy relacionados con los videojuegos ya desde hace mucho tiempo desde que aparecieran en 1947 el primer videojuego. En la actualidad los videojuegos son unos programas informáticos de los que en la computación personal más de cómputo requieren a los ordenadores, una buena parte de la presión para mejorar los computadores proviene de los videojuegos con tarjetas gráficas muy potentes, cantidades de memoria consideradas enormes hasta hace una década, procesadores más potentes en la guerra actual por añadir más núcleos a las CPU. Recientemente los sistemas operativos y entornos de escritorio han empezado a aprovechar de las capacidades de las tarjetas gráficas o GPU para proporcionar efectos visuales y acelerar algunas operaciones de cálculo más eficientemente que en la CPU.

Primeros videojuegos

Esta es una muestra de la evolución gráfica que han experimentado los juegos desde 1995 hasta 2018, dos décadas en este caso con el juego de ación y aventuras Tomb Raider.

La industria de juego sigue creciendo con las nuevas generaciones ya siendo nativos digitales. Desde hace un tiempo se están organizando competiciones deportivas en diferentes juegos populares y se están retransmitiendo en internet en la plataforma especializada en videojuegos Twitch. Estas competiciones promovidas por actores importantes del hardware interesados en potenciar el sector como Nvidia, Intel, AMD u otros fabricantes de hardware y estudios de desarrollo de videojuegos como [Blizzar][blizzar] ofrecen a los finalistas y campeones importantes premios económicos. Tanto que algunas personas se están dedicando ya como profesionalmente con absoluta dedicación a competir y entrenar aprovechando sus habilidades y conocimiento profundo de los juegos en los que están especializados.

Estadio de una final de League of legends

Algunos de los juegos actuales en los que se realizan competiciones son Hearthstone, League of legends, Clash Royale, … que han sido diseñados no solo como para el entretenimiento como los juegos de hace unas pocas décadas para competir entre humano e inteligencia artificial más o menos inteligente o automática de la máquina sino para ser jugados de forma competitiva entre humanos principalmente.

Es plausible que en un futuro estas competiciones se conviertan en eventos deportivos con el potencial de ser el equivalente en los eSports como hoy lo son la liga de campeones europea, la copa del mundo de fútbol, la Super Bowl o las finales de la NBA ya sea en modalidades de por equipos o de selecciones por país.

Hace unas semanas veía en directo una final del juego para móvil Clash Royale, estaba muy bien organizada con un escenario muy cuidado y locutores en directo retransmitiendo en directo la final. Igual que ver una final de fútbol es entretenido y emocionante ver una final de un juego de ordenador en una competición tiene varios de los mismos ingredientes para ser igual de entretenido. Es difícil pronosticar que lleguen al nivel de una Champions League, mundial o europeo de fútbol pero dentro de unos años los gustos pueden cambiar más aún si los señores feudales que dirigen el fútbol tratan de ordeñar a los aficionados con la televisión de pago dejando al margen a muchas personas que no se lo pueden permitir, en cualquier caso es muy posible que los eSports sigan creciendo en popularidad solo está por ver a que ritmo.

Este es un documental sobre lo que rodea a las competiciones deportivas en equipos y sobre los eSports. El documental se titula «De chico solitario a estrella», aunque el documental se titula así añado que no tiene por que ser ese estereotipo de chico, joven, solitario y poco social ni siquiera chico.

» Leer más, comentarios, etc...

Blog Bitix

Sobre las competiciones deportivas de juegos o eSports

agosto 15, 2018 08:00

El sector de los videojuegos es una industria que mueve miles de millones de euros en todo el mundo mayor que sectores con más historia como la industria del cine, los juegos triple AAA poseen inversiones y desarrollos cinematográficos. Los computadores y aparatos electrónicos están muy relacionados con los videojuegos ya desde hace mucho tiempo desde que aparecieran en 1947 el primer videojuego. En la actualidad los videojuegos son unos programas informáticos de los que en la computación personal más de cómputo requieren a los ordenadores, una buena parte de la presión para mejorar los computadores proviene de los videojuegos con tarjetas gráficas muy potentes, cantidades de memoria consideradas enormes hasta hace una década, procesadores más potentes en la guerra actual por añadir más núcleos a las CPU. Recientemente los sistemas operativos y entornos de escritorio han empezado a aprovechar de las capacidades de las tarjetas gráficas o GPU para proporcionar efectos visuales y acelerar algunas operaciones de cálculo más eficientemente que en la CPU.

Primeros videojuegos

Esta es una muestra de la evolución gráfica que han experimentado los juegos desde 1995 hasta 2018, dos décadas en este caso con el juego de ación y aventuras Tomb Raider.

La industria de juego sigue creciendo con las nuevas generaciones ya siendo nativos digitales. Desde hace un tiempo se están organizando competiciones deportivas en diferentes juegos populares y se están retransmitiendo en internet en la plataforma especializada en videojuegos [Twitch][twitch]. Estas competiciones promovidas por actores importantes del hardware interesados en potenciar el sector como Nvidia, Intel, AMD u otros fabricantes de hardware y estudios de desarrollo de videojuegos como [Blizzar][blizzar] ofrecen a los finalistas y campeones importantes premios económicos. Tanto que algunas personas se están dedicando ya como profesionalmente con absoluta dedicación a competir y entrenar aprovechando sus habilidades y conocimiento profundo de los juegos en los que están especializados.

Estadio de una final de League of legends

Algunos de los juegos actuales en los que se realizan competiciones son Hearthstone, League of legends, Clash Royale, …

Es plausible que en un futuro estas competiciones se conviertan en eventos deportivos con el potencial de ser el equivalente en los eSports como hoy lo son la liga de campeones europea, la copa del mundo de fútbol, la Super Bowl o las finales de la NBA ya sea en modalidades de por equipos o de selecciones por país.

Hace unas semanas veía en directo una final del juego para móvil Clash Royale, estaba muy bien organizada con un escenario muy cuidado y locutores en directo retransmitiendo en directo la final. Igual que ver una final de fútbol es entretenido y emocionante ver una final de un juego de ordenador en una competición tiene varios de los mismos ingredientes para ser igual de entretenido. Es difícil pronosticar que lleguen al nivel de una Champions League, mundial o europeo de fútbol pero dentro de unos años los gustos pueden cambiar, en cualquier caso es muy posible que sigan creciendo en popularidad.

Este es un documental sobre lo que rodea a las competiciones deportivas en equipos y sobre los eSport. El documental se titula «De chico solitario a estrella», aunque el documental se titula así añado que no tiene por que ser ese estereotipo de chico, joven, solitario y poco social ni siquiera chico.

» Leer más, comentarios, etc...

Blog Bitix

Java Magazine, la publicación gratuita sobre Java

agosto 13, 2018 05:00

Java

La revista Java Magazine es una publicación bimensual gratuita que contiene artículos técnicos sobre temas muy variados relacionados con Java. Las revistas pueden consultarse directamente en la web o de forma más cómoda descargándola a nuestro ordenador en formato de archivo PDF. También es posible suscribirse a una lista de distribución para recibir mediante un correo electrónico una notificación cuando se publique un nuevo número de la revista o estar atento y seguir al twitter de la revista @Oraclejavamag. Su longitud ronda algo menos de 100 páginas por número.

Estas son las portadas de la revista de los tres últimos años y medio, desde el 2015 hasta junio del 2018, en las que se incluye los principales temas tratados en cada revista. Durante este tiempo publicando por supuesto algún número dedicado a Java 9 y Java 10, Java EE 8, JSF, JavaMail, JAX-RS, Spring Boot, JVM, JUnit, IoT, HTTP/2, JavaFX, Gradle, Lombok, JCommander, Byte Buddy, Jsoup, WebSockets, JPA, CDI, Servlet 4.0, testing, miroservicios y contenedores y muchos más temas.

Java Magazine 2018
Java Magazine 2017
Java Magazine 2016
Java Magazine 2015

La mayoría de artículos que incluyen suelen ser muy interesantes y de muy buena calidad de los que casi siempre se aprende algo, algunos artículos están escritos por personas con muy altos conocimientos sobre Java, algunos han sido galardonados como Java Champion, y en algunos otros casos son los desarrolladores principales de algunas de la librerías más populares en el ecosistema Java.

Si estás interesado en Java seguir esta revista y leer sus artículos es una buena recomendación.

» Leer más, comentarios, etc...

Blog Bitix

Personalizar el mensaje emitido de un objeto en log4j

agosto 10, 2018 04:00

Java

Usar una librería como log4j es probablemente indispensable en una aplicación para obtener información de su funcionamiento, mensajes informativos, advertencias, errores o excepciones que se están produciendo o se han producido. Los mensajes que se emiten contienen información útil para monitorización en tiempo real o su inspección pasado un tiempo.

En cada punto de la aplicación en la que se desea emitir una traza es necesario proporcionar el formato del mensaje y sus parámetros extraídos de las propiedades de los objetos con la intención obtener una traza con los valores de determinadas propiedades. Si es habitual emitir una traza de ciertas clases para evitar poner la misma traza en diferentes puntos de la aplicación log4j posee una funcionalidad para transformar en objeto en un mensaje personalizado como se comenta en su documentación para mensajes.

El método toString() muy posiblemente no es la mejor solución para transformar un objeto a un String de modo que sea emitido por log4j, quizá su valor no sea lo desedeado, se use este método para otro tipo de funcionalidad y no sirve en el caso de querer diferentes mensajes en diferentes lugares de la aplicación.

En log4j implementando una clase de tipo Message se transforman esas instancias en el mensaje de información personalizado. En el caso de la implementación de Message en SimpleProductMessage genera una traza con solo su identificativo y su nombre para la clase Product. En el caso de ProductMessage genera una traza más completa con su identificativo, nombre y color.

El método heredado de getFormattedMessage() es el encargado de generar la traza en este caso utilizando como apoyo los métodos también heredados getFormat() que contiene el patrón del mensaje y getParameters() que devuelve como parámetros para el patrón del mensaje los valores de las propiedades.

En los siguientes casos se utilizan diferentes formas para emitir la traza. En el primer caso se utiliza la forma habitual de proporcionar el patrón y sus parámetros, el segundo caso utiliza el método toString() del objeto. En el tercer y cuarto caso se utilizan las clases que implementan la interfaz Message emitiendo un mensaje diferente cada una de ellas sin tener que proporcionar el patrón ni extraer las propiedades de la clase Producto ya que son estas implementaciones en las que se delega esto.

En todos estos casos las trazas emitidas son las mismas salvo en el caso de ProductMessage que muestra una traza con más información.

En la API de log4j hay multitud de clases Message ya implementadas, por ejemplo, MapMessage para objetos del tipo Map entre otros muchos.

El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub y probarlo en tu equipo ejecutando el comando ./gradlew run.

» Leer más, comentarios, etc...

Variable not found

El filtro [ApiController] en ASP.NET Core MVC 2.1

agosto 06, 2018 06:00

ASP.NET Core MVCUno de los objetivos de ASP.NET Core ha sido siempre servir como infraestructura para la creación de servicios HTTP o APIs web, por lo que ya desde las primeras versiones se incluían funcionalidades específicamente diseñadas para facilitar esta tarea.

ASP.NET Core 2.1 continúa profundizando en esa línea e incluye entre sus novedades el nuevo atributo [ApiController], un decorador aplicable a controladores que los identifica como puntos de entrada de APIS, aplicando de forma automática una serie de convenciones bastante útiles a la hora de crear este tipo de componentes:
[ApiController]
[Route("api/[controller]")]
public class ValuesController : ControllerBase
{
...
}
Fijaos que, a diferencia de ASP.NET Web API (.NET Framework), se ha optado por utilizar un atributo en lugar de emplear herencia (en aquél framework existía la clase ApiController).
A continuación veremos qué debemos tener en cuenta a la hora de aplicar este atributo a nuestros controladores y qué convenciones son las que estaremos asumiendo al utilizarlo.

Obligatoriedad de usar rutas explícitas

El atributo [Route] es obligatorioLa aplicación de [ApiController] a un controlador hace obligatorio el uso de rutado por atributos hacia sus acciones. Es decir, los controladores decorados con [ApiController] no serán accesibles utilizando rutas por convenciones, como las definidas en el método Configure() de la clase Startup. De no ser así, se lanzará una excepción durante el arranque de la aplicación y no se podrá ejecutar.

Por tanto, este atributo vendrá siempre acompañado del correspondiente [Route], ya sea a nivel de controlador, o en sus acciones.
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
...
}

Inferencia del origen de parámetros

Al decorar un controlador con [ApiController], el binder usará el siguiente criterio, en orden de aplicación, para determinar desde dónde obtener los valores para los parámetros de las acciones:
  • Los parámetros de tipo complejo (clases, básicamente) se obtendrán desde el cuerpo de la petición. Sería equivalente a decorar el parámetro con [FromBody] en versiones anteriores a ASP.NET Core 2.1, por lo que, como ocurría anteriormente, sólo puede existir un parámetro de este tipo en las acciones.
     
  • Los valores para los parámetros de tipo IFormFile e IFormFileCollection serán tomados desde los valores recibidos como campos de formulario. Equivalente a usar [FromForm] en versiones anteriores.
     
  • Los parámetros cuyo nombre coincida con un valor presente en la ruta de la petición serán tomados desde ella, es decir, como si estuvieran decorados con [FromRoute].
     
  • El resto de parámetros se asumirá que proceden de la query string, equivalente a aplicar FromQuery] sobre ellos.
Por ejemplo, en una acción código como la siguiente, el valor del parámetro id se obtendrá desde la ruta de la petición, Invoice desde el cuerpo de la petición, y returnUrl desde la query string, todo ello sin necesidad de especificarlo expresamente:
[ApiController]
[Route("api/[controller]")]
public class InvoiceController: ControllerBase
{
[HttpPost("update/{id}")]
public ActionResult<InvoiceCreationResult> Update(int id, InvoiceInfo invoice, string returnUrl)
{
...
}
}

Errores HTTP 400 automáticos cuando el estado del modelo es inválido

Cuando entra una petición dirigida hacia una acción perteneciente a un controlador decorado con [ApiController], el binder cargará sus parámetros y aplicará automáticamente las validaciones asociadas a los datos de entrada. Como es habitual, el resultado de dicha validación lo tendremos en la propiedad ModelState.IsValid.

Pues bien, por defecto, el framework comprobará todos los objetos recibidos, y retornará un error HTTP 400 cuando se produzcan errores de validación. A continuación puedes ver un ejemplo de acción que devuelve el mismo objeto que recibe como parámetro, y el resultado obtenido de algunas peticiones:
public class Friend
{
[Required]
public string Name { get; set; }
[Range(0, 120)]
public int Age { get; set; }
}

[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase
{
[HttpPost]
public ActionResult<Friend> Friend(Friend f)
{
return f;
}
}
PeticiónRespuesta
Enviamos un objeto correcto:
POST https://localhost:44399/api/test/ HTTP/1.1
Host: localhost:44399
Content-Length: 34
Content-Type: application/json

{
   name: "John",
   age: 34
}
HTTP 200, con el mismo objeto recibido:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Server: Kestrel
Content-Length: 24

{"name":"John","age":34}
Objeto con contenidos inválidos en los campos:
POST https://localhost:44399/api/test/ HTTP/1.1
Host: localhost:44399
Content-Length: 31
Content-Type: application/json

{
   name: "",
   age: 200
}
HTTP 400 con el resultado de las validaciones incorrectas:
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
Server: Kestrel
Content-Length: 91

{
   "Age":["The field Age must be between 0 and 120."],
   "Name":["The Name field is required."]
}
Ni siquiera enviamos un objeto:
POST https://localhost:44399/api/test/ HTTP/1.1
Host: localhost:44399
Content-Length: 0
HTTP 400 indicando un error en el objeto:
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
Server: Kestrel
Content-Length: 33

{"":["The input was not valid."]}

Personalización o desactivación de algunos comportamientos

Aunque las convenciones asociadas al uso de [ApiController] son bastante razonables, si por cualquier motivo queremos desactivar alguno de los comportamientos por defecto, podemos hacerlo desde el método ConfigureServices() de la clase Startup.

En el siguiente código muestra cómo desactivarlas todas (ya, mucho sentido no tendría, pero me vale como ejemplo ;))
services.Configure<ApiBehaviorOptions>(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
});
Ojo, que estas líneas deben incluirse después de haber añadido los servicios de MVC con services.AddMvc(), porque de lo contrario no funcionará.
También podemos configurar el tipo de resultado que se retornará cuando se detecte que el estado del modelo es inválido. Por ejemplo, en el siguiente código se establece como respuesta un resultado del tipo NotFoundResult(), lo que provocará que nuestros clientes obtengan un HTTP 404 como respuesta a una petición con datos inválidos:
services.Configure<ApiBehaviorOptions>(options =>
{
...
options.InvalidModelStateResponseFactory = context => new NotFoundResult();
});
¡Y eso es todo! Espero que lo que hemos visto os sea de utilidad, y gracias a estas pequeñas novedades os resulte más sencillo el desarrollo de APIs HTTP con ASP.NET Core :)

Publicado en Variable not found.

» Leer más, comentarios, etc...

Navegapolis

LOS 6 FACTORES DE LA PRODUCTIVIDAD DEL TRABAJADOR DEL CONOCIMIENTO

agosto 04, 2018 10:23

6 factores

La expresión "trabajador del conocimiento" fue acuñada por Peter Druker a finales de la década de 1950, que intuyó adelantándose a su tiempo la importancia de los trabajos que requieren un conocimiento profesional especializado.

Los analistas de datos, programadores, investigadores, abogados o profesores son ejemplos de trabajadores del conocimiento. Se trata de personas con un alto nivel de formación y experiencia, cuyo trabajo requiere la aplicación de su conocimiento tácito de forma creativa e innovadora.

Valorar y mejorar la productividad de este tipo de trabajos no es fácil porque el objetivo no es cantidad, sino calidad. Y las estrategias basadas en incrementar el tiempo o  la presión con la que se realiza el trabajo se vuelven en contra del objetivo al empobrecer la calidad y valor.

Andrew Mawson, Karen Plum, Rob Briner, Eric Barends y Denise Rousseau identifican los 6 factores clave para mejora la productividad de los factores del conocimiento(1) :

» Leer más, comentarios, etc...

Blog Bitix

Después de la guerra del número de núcleos en los procesadores, ¿vendrá la guerra de la computación heterogénea o manycores?

agosto 03, 2018 10:30

Intel
AMD

Hace alguna década los procesadores eran de un solo núcleo y hasta la aparición de Windows NT y GNU/Linux los sistemas operativos no se aprovechaban plenamente las capacidades de multiprogramación de los procesadores que ya se incluían desde los Intel 386.

La mejora de rendimiento en los procesadores se conseguía a base de mejores diseños en los procesadores como la segmentación, superescalaridad, caches de datos e caches de instrucciones más grandes que era posible debido también en parte al mayor número de transistores que permitían incluir los procesos de litografía de tamaño más reducidos para los transistores, también por la adición de nuevas instrucciones en el conjunto de la arquitectura o ISA, o mayor número de registros y de mayor tamaño entre otras cosas.

Un menor tamaño de los transistores permite menor consumo de energía con menor calor a disipar al mismo tiempo que alcanzar mayores velocidades de funcionamiento para el procesador. Desde unas decenas de Khz, luego decenas Mhz, más tarde varios cientos de Mhz hasta alcanzar el hito del 1 Ghz en el año 2000, cada uno se atribuye ser el primero en alcanzarlo por pate de Intel con el Pentium III y por AMD con una de sus buenas épocas con los Athlon, o hasta el punto actual límite de entre 2 y 4 Ghz.

Aumentar más la velocidad de funcionamiento en herzios de los procesadores en los niveles actuales provoca que el calor disipado aumente drásticamente y reducir el tamaño de los transistores está empezando a ser costoso (como le está costando ya a Intel pasar de los 14nm a los 10nm, 5 años ya empleando en diferentes generaciones los mismos 14nm) y dentro de no tanto se alcanzará el límite atómico de los materiales que se usan actualmente previsiblemente en los 2-3 nm. Mejores diseños en los procesadores permite aumentar el número de instrucciones por ciclo de reloj o IPC pero entre cada generación no suele estar más de un 3 y 10%. De modo que para aumentar el rendimiento más significativamente al no poder aumentar la velocidad y las mejoras de diseño no proporcionan aumentos tan significativos como en anterioridad la estrategia actual ha sido incluir más núcleos, desde los Intel Core 2 Duo y los AMD Athlon x2 lo normal ha sido que tengan dos núcleos y ahora están empezando a estar disponibles para el consumidor personal procesadores de 4, 8, 16 e incluso 32 núcleos que con SMT como Intel lo denomina en su implementación Hyper Threading son capaces de manejar el doble de hilos, con multiprocesamiento real en vez de simulado como los procesadores de un único núcleo.

Por un tiempo el aumento de núcleos permitirá aumentar en mayor medida el rendimiento en aquellas tareas paralelizables o permitiendo manejar más tareas que con otras técnicas. Si empleando 12 nanómetros AMD ha sido capaz de empaquetar 32 núcleos en los Threadripper de la serie 2000 con 7 nanómetros por que no iba ha ser capaz de empaquetar 64. Sin embargo, aumentar el número de núcleos indefinidamente no es escalable manteniendo la coherencia de las caches (que todos los procesadores vean el mismo valor de una posición de memoria) dada la carga que suponer mantener esa coherencia en todas las caches de un gran número de núcleos. Tampoco por los fallos de fabricación que se producen lo que obliga a desactivar núcleos y venderlos con menos núcleos activos, a mayor número de núcleos mayor probabilidad de que algunos contengan fallos.

Me pregunto si llegado el límite de no poder incluir más transistores en el mismo espacio sin el espacio que dejaba la reducción de nanómetros llegará un punto en el que no se podrán incluir más núcleos o una gran cantidad de núcleos iguales no es lo más eficiente cuando solo unos pocos está siendo utilizados o hay diversidad de tareas, unas que requieren alto rendimiento por usar de forma intensiva la CPU y otras que no por estar restringidas por operaciones de entrada y salida mucho más lentas que la capacidad de la CPU. En sus diseños de procesadores ARM permite una arquitectura big.LITTLE donde no todos los núcleos son iguales, posee núcleos de diferente tipo unos pocos como los Cortex-A75 ofrecen gran rendimiento a base de mayor consumo siendo más grandes y otros pocos como los Cortex-A55 con menor rendimiento pero más eficientes energéticamente y pequeños utilizando el sistema en cada momento los más adecuados para las tareas en ejecución.

Pero en la arquitectura x86/x64 de Intel y AMD aún no hay todavía una implementación de algo similar a lo empleado por ARM. Las restricciones y límites impuestos de ser cada vez más difícil reducir los nanómetros y no poder incluir más transistores en el mismo tamaño quizá haga que los que se puedan incluir deban ser mejor aprovechados y haga que Intel o AMD desarrollen una nueva arquitectura x86 con soporte de big.LITTLE similar a la de ARM. Cuando se llege al límite de 2 nanómetros ya la litografía ya no será lo que permita aumentar el rendimiento o se necesitarán nuevos materiales o procesos de fabricación, seguramente se requerirán nuevos diseños de arquitectura.

Bueno, la posible arquitectura big.LITTLE para x86 es una conjetura mía, muy posiblemente los ingenieros de Intel y AMD encuentren otras soluciones para seguir haciendo que cada generación de procesadores tenga un aumento de rendimiento significativo. La que hice sobre la convergencia que sería la siguiente disrupción tecnológica aún no se ha producido.

Una de las soluciones previsibles es que se empleen otros materiales distintos a los que desde hace décadas con el silicio se ha estado empleado: grafeno, siliceno, molibdenita o interconexiones ópticas. Permitiendo mayores frecuencias y con menor calor disipado lo que equivaldrá a poder seguir aumentando la capacidad de cómputo.

Otra es aprovechar más la computación heterogénea para delegar tareas que son más eficientes realizarlas en un procesador especializado en vez de uno de propósito general como la CPU, un ejemplo de este caso es la GPU para los gráficos pero empleando la capacidad de estas también para tareas de propósito general de cálculos, una API como OpenCL permite realizar cálculos en la GPU para procesamiento de audio, vídeo, imagen, criptografía, … Otro serían los DSP para procesamiento de señales como audio o vídeo. Una forma de computación heterogénea hace en el caso de la CPU y GPU que compartan la misma memoria del sistema evitando tener que hacer copias de los datos entre memorias al tenerlas dedicadas en exclusiva a cada una de los procesadores.

Finalmente, pueden estar los procesadores manycore que a diferencia de los multicore actuales integran un número de núcleos más grande en varios órdenes de magnitud (100, 1000) e independientes que palía el problema de los multicore y su escalabilidad en número de núcleos por mantener la coherencia de las caches. Y para estos casos es más adecuado la arquitectura de procesadores ARM mucho más simple que la arquitectura x86, con procesadores más pequeños y más eficientes pero mayor número de ellos. Unido a si Qualcomm consigue trauducir las instrucciones x86 sobre las de ARM manteniendo la compatibilidad con todo el software puede poner en serios aprietos la arquitectura x86 y hacer una realidad la citada convergencia entre móvil y PC. Siempre y cuando Intel lo permita, al vez amenazado su hegemonía como recurso podrá defenderse de forma legal con juicios de patentes.

Y en esa guerra de computación heterogénea y manycore, aunque eso es mucho decir, puede que salga vencedora ARM y la actual guerra de núcleos entre Intel y AMD quede como una anécdota en la historia como ya hay muchas otras.

Si quieres conocer más en detalle los procesadores tanto de su historia, evolución y funcionamiento más minucioso la enciclopedia El mundo de Bitman de @iandatux recoge en varios volúmenes una ingente cantidad de información que leyendo el indice de contenidos de cada libro se presenta muy interesate, diría que la obra disponible más completa sobre los procesadores, además en español. Si te interesa el tema me parece imprescincdible, en la descripción de los libros en Amazon están los índices completos. Por ejemplo, concretamente el volumen V cubre los materiales candidatos a emplearse en el futuro, los límites de los semiconductores actuales y el futuro en los procesadores que comento brevemente en este artículo:

Dentro de unos años, lustros o alguna década revisaré estos artículos de predicción a ver cuanto hay de acierto en la evolución de la tecnología que se produzca finalmente.

» Leer más, comentarios, etc...

Koalite

Siete años

julio 23, 2018 05:06

Otra vez llego por los pelos, pero llego. No está siendo nada fácil este año darle continuidad al blog. Pese a todo, ya van casi 350 entradas desde que empecé a escribirlo, que no está del todo mal. Este año además he vuelto a mezclar posts más teóricos, con otros más técnicos y mis típicos posts de quejarme.

Ya decía el año pasado que me estaba costando mantener mi frecuencia de publicación programada de un post cada dos semanas y que eso no tenía visos de cambiar en un futuro cercano, y así ha sido.

Mi intención con este blog siempre ha sido, y sigue siendo, aprender cosas y disfrutar escribiendo. Eso no ha cambiado. En realidad, pocas veces he aprendido más rápido a lo largo de mi vida, pero es un aprendizaje enfocado a mi otro proyecto.

Mi otro proyecto personal sigue avanzando muy bien después de 16 meses (ahora le ha llegado el momento de escalar, literalmente), y la verdad es que ahora mismo es donde prefiero invertir mi tiempo y energía.

¿Eso quiere decir que esto se termina? Ni idea. Me gustaría que no fuera así. De momento, me apetece descansar, pasar el verano centrado en otras cosas y dejar esto en pausa. Ya veremos en septiembre qué pasa.

De todas formas, sigo abierto a discutir de cualquier cosa entretenida en twitter o por correo.

52285

Feliz verano a todos.

No hay posts relacionados.

» Leer más, comentarios, etc...

Bitácora de Javier Gutiérrez Chamorro (Guti)

Improve, ingenuity, support, resume, designed y location

julio 20, 2018 06:49

Continuamos con Remover, resumir y otros términos, en esta ocasión incorporando las sugerencias de nuestros lectores: Kabe, bianamaran y las mías propias. Para aportar algo de variedad al asunto, nos centraremos en anglicismos, muchos de ellos provenientes del entorno tecnológico, en esta ocasión, partiendo de sus términos en inglés, que se adaptan equivocadamente al español. […]

La entrada Improve, ingenuity, support, resume, designed y location aparece primero en Bitácora de Javier Gutiérrez Chamorro (Guti).

» Leer más, comentarios, etc...

Bitácora de Javier Gutiérrez Chamorro (Guti)

RAD Studio Community Edition (gratis)

julio 19, 2018 06:10

Os traigo un anuncio muy interesante, puesto que como muchos sugeríamos y deseábamos, finalmente Embarcadero ha decidido liberar una versión gratuita y verdaderamente funcional de RAD Studio, es decir, tanto de C++ Builder como de Delphi. Se trata de RAD Studio Community Edition, o dicho de otro modo, de Delphi Community Edition y C++ Builder […]

La entrada RAD Studio Community Edition (gratis) aparece primero en Bitácora de Javier Gutiérrez Chamorro (Guti).

» Leer más, comentarios, etc...

Picando Código

Humble Book Bundle: Linux Geek

julio 18, 2018 09:48

Humble Bundle tiene un nuevo paquete de e-books sobre Linux , GDB, Perl, GIMP, Inkscape, Blender, Python, y más de No Starch Press.

Linux Geek Book Bundle

Pagando el monto mínimo de USD 1, obtenemos: Automate the Boring Stuff with Python: Practical Programming for Total Beginners, The Artist’s Guide to GIMP: Creative Techniques for Photographers, Artists, and Designers, The Art of Debugging with GDB, DDD, and Eclipse, Perl One-Liners: 130 Programs That Get Things Done, The Book of GNS3: Build Virtual Network Labs Using Cisco, Juniper, and More y No Starch Sampler. Éste último un compilado de capítulos de muestra de varios libros sobre Linux, redes y seguridad.

Pagando USD 8 o más, también obtenemos: The Book of Inkscape: The Definitive Guide to the Free Graphics Editor, The Book of GIMP: A Complete Guide to Nearly Everything, The Book of PF: A No-Nonsense Guide to the OpenBSD Firewall, The GNU Make Book, Blender Master Class: A Hands-On Guide to Modeling, Sculpting, Materials, and Rendering y Doing Math with Python: Use Programming to Explore Algebra, Statistics, Calculus, and More!

Pagando USD 15 o más, el paquete incluye: How Linux Works: What Every Superuser Should Know, Wicked Cool Shell Scripts: 101 Scripts for Linux, OS X, and UNIX Systems, Absolute OpenBSD: Unix for the Practical Paranoid, Arduino Project Handbook Vol. 1: 25 Practical Projects to Get You Started y Think Like a Programmer: An Introduction to Creative Problem Solving.

Por último, pagando USD 30 o más, obtenemos The Linux Programming Interface: A Linux and UNIX System Programming Handbook.

Los ebooks están disponibles en PDF, ePUB y MOBI, por lo que pueden ser leídos en casi cualquier dispositivo. Como se acostumbra en los paquetes Humble Bundle, además de elegir el precio, podemos elegir dónde destinamos el dinero que pagamos, incluyendo una organización de beneficencia.
En este caso se trata de Electronic Frontier Foundation, la fundación sin fines de lucro que defiende nuestros derechos en el mundo digital. Activistas, abogados y tecnólogos que luchan en las cortes y el congreso para proteger la privacidad y libre expresión en línea en todo el mundo.

Visita el Linux Geek Book Bundle.

Linux Geek Book Bundle

» Leer más, comentarios, etc...

Adrianistán

Computación cuántica para torpes: introducción para programadores

julio 17, 2018 01:57

Hace ya bastante tiempo quese viene hablando de ordenadores cuánticos. ¿Qué son? ¿En qué se diferencian de los ordenadores clásicos? ¿Son de verdad tan potente como dicen?

En este largo artículo, ideal para el verano, vamos a ver los principios fundamentales de los ordenadores cuánticos más allá de lo que la típica revista o web te podría contar. Veremos qué es un qubit y algunas puertas lógicas interesantes, así como su aplicación.

Los ordenadores cuánticos actuales requieren temperaturas de funcionamiento cercanas al cero absoluto

Notación de Dirac

Lo primero antes de entrar en materia cuántica, será adaptar nuestra notación clásica, a otra más potente. Esta notación que vamos a ver, llamada notación de Dirac o Bra-ket, nos será muy útil ya que los bits clásicos no son más que un caso concreto de qubit en esta notación.

En esta notación tenemos que representar los bits como matrices. Un conjunto de N bits se representa con una matriz de 1 columna y \(2^N\) filas. En todas las posiciones existen ceros salvo para la posición que representa la combinación que representa. Veamos algunos ejemplos sencillos:

Un bit con valor 0 se representa así

\(
| 0 \rangle = \begin{pmatrix}
1\\
0
\end{pmatrix}\)

Un bit con valor 1 se representa así:

\(
| 1 \rangle = \begin{pmatrix}
0\\
1
\end{pmatrix}\)

Aquí contamos como en informática, empezando desde cero. Como ves la posición 0 del vector solo es 1 cuando representa el bit 0. Si la posición que tiene el 1 es la segunda, representa el bit 1.

La parte que va a la izquierda del igual se llama ket. En este caso hemos representado ket 0 y ket 1.

Si tenemos más bits se puede hacer de la misma forma. Vamos a representtar ket 10. 10 en binario es 2, así que estará en la posición tercera.

\(
| 10 \rangle = \begin{pmatrix}
0\\
0\\
1\\
0
\end{pmatrix}\)

Puertas lógicas como producto de matrices

¿Recuerdas el producto de matrices de tus clases de álgebra? Resulta que todas las puertas lógicas clásicas pueden representarse como producto de matrices. Por ejemplo, la puerta lógica NOT se puede implementar con esta matriz:

\(
\begin{pmatrix}
0 & 1 \\
1 & 0 \\
\end{pmatrix}
\)

Y aquí la vemos en acción

\(
\begin{pmatrix}
0 & 1 \\
1 & 0 \\
\end{pmatrix}\begin{pmatrix}
1 \\
0
\end{pmatrix}
=
\begin{pmatrix}
0 \\
1
\end{pmatrix}
\)

También podría hacerse con la puerta AND que toma como entrada dos bits.

\(
\begin{pmatrix}
1 & 1 & 1 & 0 \\
0 & 0 & 0 & 1
\end{pmatrix}
\begin{pmatrix}
0 \\
0 \\
0 \\
1
\end{pmatrix}
=
\begin{pmatrix}
0 \\
1
\end{pmatrix}
\)

Un teclado con puertas cuánticas

Juntando bits

Para formar bits más grandes ya sabemos que tenemos que tener una matriz tan grande como combinaciones haya (\(2^N\) posiciones, N bits). Existe una forma de calcular automáticamente la posición que hay que marcar y es hacer el producto tensorial. Si no sabes calcularlo no importa mucho, porque apenas lo vamos a usar, pero puedes ver un ejemplo de como funciona. En este ejemplo, queremos juntar los bits 1 y 1 (3 en decimal).

\(
\begin{pmatrix}
0 \\
1
\end{pmatrix}
\otimes
\begin{pmatrix}
0 \\
1
\end{pmatrix}
=
\begin{pmatrix}
0 \\
0 \\
0 \\
1
\end{pmatrix}
\)

Qubits

Hasta ahora no hemos visto nada realmente nuevo, solo hemos preparado el terreno para dejar paso a los qubits. Personalmente desconocía que podían usarse matrices para operar con bits y aunque no es tan práctico como otros sistemas, lo cierto es que es muy explícito y elegante.

Los qubits son bits como los que hemos visto antes pero tienen un estado indeterminado. No es que tengan un valor de forma secreta y no sepamos cuál es. Podríamos decir que son los dos valores clásicos a la vez, como el gato de Schrodinger. Cuando realizamos una observación sobre el qubit, este colapsa y podemos ver uno de los dos estados. ¿Cuál vemos? No podemos saberlo a priori, pero hay probabilidades. Los bits clásicos no son más que qubits cuyas probabilidades de colapsar a 0 o 1 es del 100%, por tanto no hay duda y su valor sí que está determinado.

¿Cómo representamos los qubits y sus estados cuánticos? Con números complejos. Si recuerdas, estos eran los que tenían una parte real y una imaginaria. No obstante, voy a tomar solo los números reales para simplificar. Los números reales son números complejos válidos, pero los complejos son mucho más extensos.

La esfera de Bloch permite representar todos los estados cuánticos (números complejos)

Para calcular la probabilidad que tiene un estado cuántico de colapsar a un valor, hacemos el módulo y elevamos al cuadrado: \(|a|^2\).

Todo qubit además debe cumplir una propiedad fundamental:

\(
\begin{pmatrix}
a \\
b
\end{pmatrix}
\text{ es un qubit}
\Leftrightarrow
|a|^2 + |b|^2 = 1
\)

Y es que la probabilidad de ser 0 y de ser 1 sumadas deben equivaler al suceso seguro, es decir, 1. 100% de probabilidades de que de 0 o 1.

Con esto ya podemos definir algunos qubits.

\(
\begin{pmatrix}
\frac{1}{\sqrt{2}} \\
\frac{1}{\sqrt{2}}
\end{pmatrix}
\)

Este es mi qubit preferido. Representa el estado de superposición cuántica. Cada valor tiene el 50% de probabilidades de salir. \(|\frac{1}{\sqrt{2}}|^2 = \frac{1}{2}\). Cuando colapsemos el qubit al observarlo será como lanzar una moneda al aire.

Otro detalle que a veces se nos pasa por alto es que los qubits pueden contener valores negativos. Estos qubits son físicamente diferentes a los positivos, pero tienen las mismas probabilidades de colapsar en los mismos valores que los positivos.

\(
\begin{pmatrix}
-1 \\
0
\end{pmatrix}
\)

Es un qubit válido, que colapsa con 100% de probilidad a 0.

¿Cómo se representan los qubits en notación de Dirac? Representando la probabilidad que tiene cada combinación de bits de aparecer. Para un qubit sería algo así:

\(
\alpha | 0 \rangle + \beta | 1 \rangle
\)

Siendo \(\alpha\) y \(\beta\) las probabilidades de colapsar a cada estado.

Puertas cuánticas

Ahora vamos a ver cuáles son las puertas lógicas más importantes del mundo cuántico.

Negación (Pauli X)

Esta es exactamente igual que en el mundo clásico, con la misma matriz que hemos visto antes. Su símbolo es el cuadrado con una X.

Aquí vemos una imagen del simulador IBM Q usando la puerta X cuántica. IBM nos deja ejecutarlo en ordenadores cuánticos reales. Veamos los resultados.

¡Terrible! La mayoría de casos, el ordenador cuántico responde 1, el valor correcto, pero un 13% de los casos no. Teóricamente había una probabilidad del 100% y en la práctica solo es del 86.3%. ¡Y solo es una puerta X! Es por ello que los procesadores cuánticos todavía necesitan mejorar mucho. Google, Microsoft e IBM están investigando de forma independiente en ordenadores cuánticos. Veremos quién consigue tener antes ordenadores cuánticos precisos (aunque hay expertos que piensan que nunca se podrá lograr).

CNOT

Esta puerta es muy interesante. Toma dos qubits, uno de control, que permanece invariable al traspasar la puerta y otro de datos. Al qubit de datos se le aplica la puerta X si el qubit de control está activo. Su matriz es la siguiente:

\(
CNOT = \begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 0 & 1 \\
0 & 0 & 1 & 0
\end{pmatrix}
\)

Se reprensenta de esta forma:

O similar, porque los símbolos de computación cuántica no están todavía muy estandarizados. El punto grande es el qubit de control y el punto pequeño está sobre el qubit de datos.

HADAMARD

Esta puerta es quizá la más famosa del mundo cuántico. Veamos su matriz:

\(
\begin{pmatrix}
\frac{1}{\sqrt{2}} & \frac{1}{\sqrt{2}} \\
\frac{1}{\sqrt{2}} & -\frac{1}{\sqrt{2}}
\end{pmatrix}
\)

Esta puerta permite poner un qubit clásico en estado de superposición cuántica. Y también deshacerlo. Es muy usada en algoritmos cuánticos. Se representa con un cuadrado y una H.

Los resultados en el ordenador cuántico real de IBM Q son:

Cuando debería de ser bastante más cercano a 50% en los dos valores.

Con esto ya tenemos las puertas más usadas. Básicamente con Hadamard, X y CNOT se pueden implementar casi todos los circuitos cuánticos. Solo nos faltarían las puertas que operan entran en números complejos para poder implementar todos los circuitos.

Algoritmo de Deutsch-Jozsa

El algoritmo de Deutsch-Jozsa es uno de los algoritmos cuánticos más sencillos de entender y que mejoran drásticamente el rendimiento respecto a un algoritmo clásico.

El planteamiento básico es que tenemos una caja negra que aplica una función sobre un bit. Estas funciones pueden ser: set-to-0, set-to-1 (ambas constantes), identidad (no cambiar nada) y X (ambas dinámicas) . Si queremos saber que función contiene la caja negra, ¿Cuántas veces tenemos que pasar valores? En una CPU clásica tendríamos que hacerlo dos veces para poder determinar que función contiene la caja negra. En una CPU cuántica… también. No hay diferencia. Pero, si cambiamos la pregunta a ¿de qué categoría es la función de la caja negra?, la cosa cambia. En una CPU clásica seguiríamos necesitando 2 pruebas, pero en una CPU cuántica y con un circuito por el exterior, podemos aprovechar la superposición cuántica para realizar una sola prueba y determinar si en el interior hay una función constante o dinámica.

Vamos a ver estas 4 funciones de la caja negra como son:

¿Se te ocurre como puedes crear un circuito fuera de la caja negra que con una sola prueba, ya sepa si estamos ante las funciones Set-0, Set-1 o Identidad, Negación?

El circuito es el siguiente:

Tal y como está diseñado si en q[1] medimos 0, la función es de tipo constante y si medimos 1, es de tipo dinámica. Un desarrollo matemático de los productos de matrices, como el que hay en Wikipedia, te mostrará como siempre es cierto. Este también es un ejemplo de como los ordenadores cuánticos pueden dar resultados totalmente deterministas.

Esta idea, se puede generalizar y extrapolar a otros problemas, generando una colección muy interesante de algoritmos que se ejecutan en tiempo exponencialmente menor que en una CPU clásica.

Algoritmos de Shor y de Grover

Estos dos algoritmos han sido llamados los killer apps de la computación cuántica, ya que son algoritmos que mejoran sustancialmente (uno de forma exponencial, otro de forma cuadrática) los tiempos de problemas reales.

El algoritmo de Shor fue el primero en ser descubierto, en 1994 por Peter Shor. Sirve para factorizar números (es decir, sacar los números primos que multiplicados generan el número original). Lo puede hacer en \(O((\log{n})^3)\). De este modo, los algoritmos tipo RSA que se basan en la factorización de números podrían romperse en tiempo polinómico, por lo cuál RSA ya no serviría como protección. El algoritmo de Shor no da siempre los resultados correctos, pero tiene una probabilidad de éxito superior a la de fracaso, por lo que con repetir múltiples veces la ejecución podríamos estar casi seguros del resultado.

El algoritmo de Grover fue descubierto en 1996 por Lov Grover y permite buscar en una lista no ordenada de datos en \(O(\sqrt{n})\) mientras que en una computadora clásica sería \(O(n)\).

Estos dos algoritmos sin duda marcan lo que se ha llamada la supremacía cuántica y que ocurrirá cuando los ordenadores cuánticos puedan ejecutar con suficiente precisión estos algoritmos y su utilidad en el mundo real supere a la de los algoritmos clásicos.

Entrelazamiento cuántico

Ya hemos visto las bases de los circuitos cuánticos. Ahora veamos algunas consecuencias de todo lo anterior. Cosas cuánticas que parecen hasta cierto punto fuera de la lógica. ¿Qué ocurre si tenemos varios qubits en un estado como este?

\(
\begin{pmatrix}
\frac{1}{\sqrt{2}} \\
0 \\
0 \\
\frac{1}{\sqrt{2}}
\end{pmatrix}
\)

En este estado solo puede colapsar a 00 o a 11. ¿Esto qué significa? Significa que los qubits están entrelazados entre sí, uno depende de otro, si los separamos y uno colapsa a 0, el otro colapsa a 0. Si uno colapsa a 1, el otro colapsa a 1.

Es importante destacar que los qubits pueden separarse en este estados. Los qubits alejados a millones de kilómetros siguen entrelazados y el valor al que deciden colapsar se decide de forma instantánea. Esto quiere decir que se sincronizan a una velocidad superior a la de la luz. El truco es que no se transmite información, por eso el universo lo permite, pero esto permite realizar la teletransportación cuántica.

La forma de entrelazar qubits es muy sencilla, con una puerta Hadamard y una CNOT.

IBM Q todavía tiene que mejorar, pero se aprecia claramente el entrelazamiento cuántico.

Teletransportación cuántica

La teletransportación existe, al menos entre qubits. Y es instantánea (más o menos). La teletransportación cuántica la podemos provocar usando varios qubits entrelazados. Necesitamos 3 qubits. El qubit que va a ser teletransportado, un qubit del emisor y un qubit del receptor. La idea es entrelazar el emisor con el receptor (qubit de destino) y posteriormente el qubit del emisor con el qubit que va a ser transportado.

No he sido capaz de hacer que IBM Q haga una teletransportación, así que aquí viene un esquema distinto. T es el qubit a transportar, A es el emisor y B el receptor. En este ejemplo se usa la puerta Pauli Z, cuya matriz es la indicada.

El truco de la teletransportación instantánea tiene que ver con que A y B tienen que estar entrelazados, por tanto, han tenido que ser transportados a sus respectivos lugares anteriormente a velocidad inferior a la luz.

Esto teletransporta qubits pero no hace copias. Esto es debido al Teorema de No Clonación.

Lenguajes de programación

Mientras esperamos a que los ordenadores cuánticos sean lo suficientemente estables, ya existen lenguajes de programación que podemos usar en simuladores. Quizá el más conocido sea Q# de Microsoft (funciona en Linux, tranquilos), que guarda similitudes con C#. Otro bastante usado es OpenQasm de IBM, algo más parecido a ensamblador.

namespace Quantum.Bell
{
    open Microsoft.Quantum.Primitive;
    open Microsoft.Quantum.Canon;

    operation Set (desired: Result, q1: Qubit) : ()
    {
        body
        {
            let current = M(q1);
            if (desired != current)
            {
                X(q1);
            }
        }
    }
    operation BellTest (count : Int, initial: Result) : (Int,Int,Int)
    {
        body
        {
            mutable numOnes = 0;
            mutable agree = 0;
            using (qubits = Qubit[0])
            {
                for (test in 1..count)
                {
                    Set (initial, qubits[0]);
                    Set (Zero, qubits[1]);

                    H(qubits[0]);
                    CNOT(qubits[0],qubits[1]);
                    let res = M (qubits[0]);

                    if (M (qubits[1]) == res) 
                    {
                        set agree = agree + 1;
                    }

                    // Count the number of ones we saw:
                    if (res == One)
                    {
                        set numOnes = numOnes + 1;
                    }
                }

                Set(Zero, qubits[0]);
            }
            // Return number of times we saw a |0> and number of times we saw a |1>
            return (count-numOnes, numOnes, agree);
        }
    }
}

Este es un ejemplo de lanzar la moneda con entrelazamiento cuántico en Q#, el lenguaje cuántico de Microsoft.

Referencias

Quantum Computing for Computer Scientists
Cats, Qubits, and Teleportation: The Spooky World of Quantum Algorithms
Microsoft Quantum Development Kit: Introduction and step-by-step demo
Qubit

La entrada Computación cuántica para torpes: introducción para programadores se publicó primero en Adrianistán.

» Leer más, comentarios, etc...

Adrianistán

Usar AVA para tests en una API hecha en Node.js y Express

julio 15, 2018 07:01

Testear nuestras aplicaciones es algo fundamental si queremos garantizar un mínimo de calidad. En este breve post, explicaré como he usado AVA para crear tests para mis APIs: tanto unitarios como de integración con AVA.

AVA es una herramienta de testing, que nos permite describir los tests de forma muy sencilla. De todas las herramientas que he probado, AVA es muy preferida. Es muy sencilla, ejecuta los tests en paralelo y permite escribir código en ES6 (usa Babel por debajo). Además tiene bastante soporte siendo el framework de testing usando por muchos proyectos ya.

Instalamos AVA de la forma típica:

npm install ava --save-dev

A continuación creamos un fichero cuya terminación sea .test.js, por ejemplo, suma.test.js. El lugar da igual.

Una opción de diseño es poner los test unitarios al lado de las funciones en sí, otra opción es crear una carpeta para todos los tests, ya que los de integración van a ir casi siempre ahí. Para ejecutar los tests, simplemente:

ava

El interior de suma.test.js debe importar la función test de AVA y las funciones que quiera probar.

Los tests se definen como una llamada a la función test con la descripción del test y a continuación un callback (asíncrono si queremos) con el objeto que controla los tests (llamado t normalmente). Veamos un ejemplo simple:

import test from "ava";
import {suma} from "./operaciones";

test("Suma",t => {
    t.is(suma(1,2),3);
});

El objeto t soporta múltiples operaciones, siendo is la más básica. Is pide que sus dos argumentos sean iguales entre sí, como Assert.Equal de xUnit.

Veamos que más soporta Ava.

  • t.pass(): Continúa el test (sigue)
  • t.fail(): Falla el test (no sigue)
  • t.truthy(val): Continúa el test si val es verdaderoso (usando la lógica de JavaScript) o falla el test
  • t.true(val): Continúa el test si val es verdadero (más estricto que el anterior) o falla.
  • t.is(val1,val2): Continúa el test si val1 y val2 son iguales (superficialmente) o falla.
  • t.deepEqual(val1,val2): Continúa el test si val1 y val2 son iguales (profundamente) o falla.
  • t.throws(funcion): Ejecuta la función especificada esperando que lance una excepción. Si no lo hace, falla el test. Se puede especificar el tipo de excepción que esperamos en el segundo argumento.
  • t.notThrows(funcion): Exactamente lo contrario que la anterior.

Y algunas más, pero estas son las esenciales.

import test from "ava";

function sum(a,b){
    return a+b;
}

function login(username,password){
    if(username === null || password === null){
        throw new Error("Missing username or password");
    }
}

test("Test example: Sum",t => {
    t.is(sum(1,2),3);
});

test("Login fail username null", t => {
    t.throws(()=>{
        login(null,"123456");
    });
});
test("Login fail password null", t => {
    t.throws(()=>{
        login("username",null);
    });
});

También podemos definir funciones que se ejecuten antes y después de nuestros tests, y una sola vez o con cada test. Podemos usar test.before, test.beforeEach, test.after y test.afterEach en vez de test. Por ejemplo, si tienes una base de datos que necesita inicialización, puedes definir ese código en test.before y la limpieza en test.after.

import test from "ava";
import db from "../db";

test.before(async () => {
    // Iniciar el ORM Sequelize
    await db.sync();
});

 

Con esto ya podemos hacer tests unitarios, pero no podemos probar la aplicación web al 100%. Entra en acción supertest que nos permitirá tener un servidor Express simulado para que los tests puedan probar la aplicación al completo.

Supertest

Instalamos supertest

npm install supertest --save-dev

En el fichero de test necesitamos crear un objeto de tipo aplicación de Express. Este objeto puede ser el mismo que usas en tu aplicación real o ser una versión simplificada con lo que quieras probar.

import test from "ava";
import request from "supertest";
import auth from "http-auth";
import express from "express";

function setup(){
    const app = express();

    let basic = auth.basic({
        realm: "Upload Password"
    }, function (username, password, callback) {
        callback(username === "admin" && password === "123456");
    });

    app.get("/upload",auth.connect(basic),function(req,res){
        res.sendFile("upload.html");       
    });
    return app;
}

test("Página upload requiere autenticación HTTP Basic", async t => {
    let res = await request(setup())
        .get("/upload")
        .send();
    t.is(res.status,401);
    t.true(res.header["www-authenticate"] !== undefined);
});

Aquí la función de test es asíncrona, AVA es compatible con ambos tipos. Supertest es muy completo y permite probar APIs enteras con su sencilla interfaz que junto con AVA, se convierte en algo casi obligatorio para una aplicación que vaya a producción.

La entrada Usar AVA para tests en una API hecha en Node.js y Express se publicó primero en Adrianistán.

» Leer más, comentarios, etc...

Bitácora de Javier Gutiérrez Chamorro (Guti)

WinAPI contra C

julio 14, 2018 09:09

Muchas veces tiendo a usar funciones implementadas en la API de Windows en vez de las nativas de C/C++. El motivo es que al estar disponibles en el propio sistema evitamos que se enlacen en nuestra aplicación, y así el ejecutable resultante sea más compacto. El inconveniente es que probablemente sean más lentas, particularmente porque […]

La entrada WinAPI contra C aparece primero en Bitácora de Javier Gutiérrez Chamorro (Guti).

» Leer más, comentarios, etc...

Variable not found

Task.Factory.StartNew(EnjoySummer, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);

julio 12, 2018 06:55

Pues eso, que parecía que no llegaba y las semanas se hacían cada vez más cuesta arriba, pero por fin es el momento de descansar un poco e intentar conseguir un merecido reinicio mental.

Durante las próximas semanas dejaré el blog a merced de las olas, pues estaré disfrutando con la familia en las maravillosas playas de Cádiz: sol, paseos, refrescantes bañitos en las aguas del Atlántico y chiringuitos playeros con aroma a pescado fresco. Un buen plan, sin duda ;)

Costa Ballena, Cádiz
Imagen original

Nos vemos a la vuelta, ya en el mes de septiembre, con la batería al 100% y listos para seguir buscando la variable ;)

¡Felices vacaciones a todos!

Publicado con ánimo vacacional en Variable not found.

» Leer más, comentarios, etc...

Adrianistán

La perlificación de Python

julio 10, 2018 09:59

You know, FOX turned into a hardcore sex channel so gradually I didn’t even notice

Marge Simpson, Los Simpson

Recientemente ha salido Python 3.7, con interesantes novedades. También han salido los primeros artículos hablando de las novedades que podrá traer Python 3.8. Como muchos ya conoceréis, y si no es así explico, Python funciona a base de PEPs (Python Enhancement Proposal). Cualquier persona puede abrir un PEP, que es un documento que describe la funcionalidad que se quiere añadir/modificar/eliminar. Estas PEPs se discuten y finalmente Guido, creador de Python, las aprueba y se codifican.

Dentro de las PEP relacionadas con Python 3.8 hay algunas bastante controvertidas que han hecho saltar la voz de alarma. No ha faltado gente que ha opinado que cada vez Python se parece más a Perl. Este proceso habría empezado con Python 3 pero se habría ido haciendo más evidente hasta llegar a hoy. Cada vez con más sintaxis poco utilizada, con más elementos, más cómodo de escribir para el experimentado aunque menos legible si no dominas el lenguaje.

Y resulta curioso, porque Python es en parte una respuesta a la excesiva complejidad que podían tener los programas hechos en Perl. Su popularidad se debe a que es fácil de aprender y eso parece que ya no está tan claro.

Con la introducción de operadores como := o ?? o anotaciones como @dataclass se va, en cierta medida, perdiendo el espíritu original de Python. Y es cierto que otros lenguajes tienen algo similar, pero precisamente Python había sido muy selecto en incluir un conjunto bastante reducido de características, que todo el mundo pudiese dominar. Al final se sacrifica legibilidad y facilidad de aprendizaje por una ergonomía que beneficia a unos pocos en unos casos concretos.

Lenguajes de programación barrocos

Universidad de Valladolid, ejemplo de barroco civil. Foto: https://artevalladolid.blogspot.com

Python lleva un tiempo entrando en un proceso de perlificación pero en mi opinión no es el único lenguaje que ha entrado en una espiral parecida. Cada vez más lenguajes han pasado del renacimiento, donde se buscaba la consistencia, la simetría, la sencillez sin perder la funcionalidad, hacia el barroco, donde los lenguajes son más recargados, con más elementos sintácticos, que cubren mejor casos concretos, pero que de por sí no son tan esenciales, no cambian aspectos fundamentales del lenguaje y normalmente introducen diversas formas de hacer algo en un mismo lenguaje.

Veamos más ejemplos: en C++20 se propuso añadir funcionalidad de dibujado 2D a la librería estándar (propuesta que fue rechazada en una historia bastante larga para este post) y se han propuesto conceptos, módulos, comparación de tres vías, reflexión, metaclases,… En C# 8.0 se han propuesto también bastantes cosas como records, tipos non-nullable, interfaces con métodos ya implementados (traits) y rangos. Y eso sin contar con las características que estos dos lenguajes ya tienen, que son bastante más extensos que Python.

Retablo lateral de la Iglesia de San Miguel y San Julián (Valladolid). Barroco puro. Foto: https://commons.wikimedia.org/wiki/File:San_Miguel_-_retablo_relicario.jpg

Hay un horror vacui, horror al vacío, a funcionalidades. Siempre se añade y casi nunca se elimina. ¿Pero es realmente necesario? Es evidente que durante mucho tiempo, los lenguajes evolucionaban de forma muy lenta y muchos de los cambios que han hecho eran necesarios. Desde hace unos años, se ha aumentado la velocidad de los cambios, pero esto no puede seguir así eternamente, porque el ritmo que llevan muchas veces es superior al de los avances en lenguajes de programación y la retrocompatibilidad impide ir quitando cosas al mismo ritmo que se añaden. De este modo, todos los lenguajes que entran en esta espiral crecen y crecen. No se llegan a pulir, simplemente crecen.

La perfección no se alcanza cuando no hay nada más que añadir, sino cuando no hay nada más que quitar

Antoine de SaintExupéry

Uno podría comparar esto con lenguajes naturales, como el español o el inglés. En estos idiomas, pese a existir reglas, existen numerosas excepciones. Es posible que lenguajes como Python se estén viendo influenciados por las mismas mecánicas humanas que rigen los lenguajes naturales y que han hecho que existan excepciones. Tendría bastante sentido que ocurriese así. Pero personalmente, me gustaría que aprender Python no costase tanto como aprender alemán o francés.

Los procesos comunitarios

Para mí, gran parte de esta sobrecarga viene dada por los procesos comunitarios. En un proceso comunitario como PEP, comité de C++ o similares es mucho más fácil añadir que eliminar. En C++ la situación ha llegado a un punto en el que Bjarne Stroustrup, creador de C++, ha pedido que se relajen con las propuestas en Remember the Vasa!, en honor a un bonito barco sueco que se hundió por exceso de carga. No tanto por su peso, sino por su disposición y las reformas que hubo que hacer para que todo encajase.

El Vasa fue recuperado después de su naufragio y se expone en Estocolmo. Foto: https://rachelannsblog.wordpress.com/2016/08/03/set-sail-set-at-the-bottom-of-the-sea/

Es por ello que las personas encargadas de elegir que se añade al lenguaje o no deben de ser muy conscientes de lo que supone, ya que una vez se introduzca, va a ser casi imposible eliminarlo.

No estoy en contra de añadir nuevas características (¡al contrario!) pero se debe respetar la visión de conjunto del lenguaje, que todo cuadre y esté cohesionado. No siempre tener más es mejor.

¿Te ha gustado el artículo?

Si es así, puedes ayudar al blog. Dentro de unos días es el Amazon Prime Day. Como muchos de vosotros seguro que os compraréis algo, no quiero dejar la oportunidad de deciros que este blog tiene enlace de referidos y que por cada cosa que compréis con el enlace, me llevo una pequeña parte (a vosotros no os va a costar más caro).

Enlace Amazon.es

Será muy bien recibido

 

La entrada La perlificación de Python se publicó primero en Adrianistán.

» Leer más, comentarios, etc...

Variable not found

Problem Details: una forma estándar de retornar errores desde APIs HTTP (y cómo usarlo desde ASP.NET Core)

julio 10, 2018 06:55

ASP.NET Core MVCLos que lleváis tiempo programando APIs HTTP, ya sea con ASP.NET Core o con otras tecnologías, seguro que en muchas ocasiones habéis tenido que decidir cómo retornar al cliente, de forma más o menos normalizada, los errores producidos en el lado servidor.

Lo habitual es echar mano de los status code de HTTP para indicar problemas en el proceso de una petición; de hecho, este protocolo dispone de un rico conjunto de códigos que en principio parecen cubrir todas nuestras necesidades.

Pero no siempre es así. Por ejemplo, si tenemos un servicio que permite a los clientes de una empresa formalizar un pedido a través de un API y una llamada a este servicio retorna un error HTTP 403 (forbidden), claramente estamos indicando que el solicitante no tiene permisos para hacer un pedido. Sin embargo, no tenemos una forma clara de indicar cuál es la causa de esta prohibición (¿quizás las credenciales no son correctas? ¿o quizás el cliente no tiene crédito en la empresa? ¿o puede ser que el administrador lo haya denegado expresamente?)

Para aportar más detalles sobre el problema, normalmente necesitaremos retornar en el cuerpo de la respuesta información extra usando estructuras o formatos personalizados, probablemente distintos de una aplicación a otra, y documentarlos apropiadamente para que los clientes puedan entenderlos. Y aquí es donde entra en juego el estándar “Problem details”.

El estándar Problem details (RFC7807)

Consciente de la necesidad de normalizar este tipo de escenarios, la Internet Engineering Task Force (IEFT) propuso hace unos años el estándar Problem Details for HTTP APIs (RFC7807), promoviendo el uso de una estructura JSON normalizada en la que es posible ampliar información sobre un error producido durante el proceso de la petición a la API.

Estas respuestas, empaquetadas con un content type “application/problem+json” (aunque también podrían ser “application/problem+xml”), tienen una pinta como la siguiente:
HTTP/1.1 403 Forbidden
Content-Type: application/problem+json
Content-Language: en

{
"status": 403,
"type": "https://www.b2bcommerce.com/orders/problems/disabled-customer",
"title": "You can't submit orders",
"detail": "You must finish your registration process before submitting orders",
"instance": "/orders/12/123456",
}
En la estructura anterior se observan varias propiedades que forman parte del estándar:
  • status, si existe, debe contener el código HTTP original del error. Puede ser interesante cuando intermediarios como proxies u otros middlewares pueden alterar el código original.
     
  • type es una URI absoluta o relativa, por defecto “about:blank”, que permite identificar cuál es el problema exacto y su posible solución. Según la especificación, el contenido de esa URI debería ser una descripción del problema legible por personas (por ejemplo, escrita usando HTML).
     
  • title puede contener un texto breve que describa el problema, sobre todo destinados a aquellos consumidores que no sean capaces de interpretar correctamente el significado del campo type.
     
  • En detail podemos especificar información adicional sobre el problema, pero más enfocada a su resolución. Como en el caso anterior, debe ser legible por humanos, y no estructuras de datos que deban ser procesadas por el consumidor.
     
  • Por último, instance es una URL, absoluta o relativa, que puede apuntar a la instancia protagonista del problema.
Aparte de estos campos, el estándar permite el uso de extensiones, es decir, de campos personalizados que aporten aún más información al cliente. El siguiente bloque muestra, por ejemplo, el resultado de una petición con valores incorrectos en sus parámetros:
HTTP/1.1 400 Bad Request
Content-Type: application/problem+json
Content-Language: en

{
"type": "https://mysite.com/validation",
"title": "Invalid request parameters",
"invalid-params":
[
{
"name": "displayName",
"reason": "This field is required"
},
{
"name": "age",
"reason": "Must be a integer between 0 and 120"
},
{
"name": "email",
"reason": "Must be a valid email address"
}
]
}
Es muy recomendable leer la especificación completa en https://tools.ietf.org/html/rfc7807

Problem details en ASP.NET Core 2.1

ASP.NET Core 2.1 incluye un soporte aún muy básico para facilitar la adopción de este estándar en nuestros servicios HTTP, pero al menos nos facilita la tarea en algunos escenarios.

En primer lugar, en el espacio de nombres Microsoft.AspNetCore.Mvc encontramos la clase ProblemDetails, que modela la estructura de datos definida por la especificación:
public class ProblemDetails
{
public string Type { get; set; }
public string Title { get; set; }
public int? Status { get; set; }
public string Detail { get; set; }
public string Instance { get; set; }
}
Esto ya nos da la posibilidad de utilizarla directamente para retornar al cliente problem details, por ejemplo como sigue:
[HttpPost]
public ActionResult Submit(Order order)
{
const int maxProducts = 10;
if (order.ProductsCount > maxProducts)
{
var details = new ProblemDetails()
{
Type = "https://www.b2bcommerce.com/orders/too-many-products",
Title = "The order has too many products",
Detail = $"You can't submit orders with more than {maxProducts} products",
Instance = Url.Action("Get", "Orders", new { id = order.Id }),
Status = 403
};
return new ObjectResult(details)
{
ContentTypes = {"application/problem+json"},
StatusCode = 403,
};
}
...
}
Una secuencia de petición y respuesta para comprobar el funcionamiento del código anterior podría ser:
========================================================================
POST https://localhost:44399/api/orders HTTP/1.1
Host: localhost:44399
Content-Length: 37
Content-type: application/json

{
id: 19,
productsCount: 22
}

========================================================================
HTTP/1.1 403 Forbidden
Content-Type: application/problem+json; charset=utf-8
Server: Kestrel
X-Powered-By: ASP.NET
Content-Length: 208

{
"type":"https://www.b2bcommerce.com/orders/too-many-products",
"title":"The order has too many products",
"status":403,
"detail":"You can't submit orders with more than 10 products",
"instance":"/api/Orders/19"
}
Aunque crear el ObjectResult de forma manual es algo farragoso, sería bastante sencillo crear un helper o action result que nos ayudara a construir y retornar este tipo de objetos.
Tenemos también la clase ValidationProblemDetails, que, heredando de ProblemDetails, está diseñada expresamente para retornar errores de validación estructurados. Esta clase añade la propiedad Errors que es un diccionario en el que las claves son los nombres de las propiedades validadas con error, y el valor contiene un array de strings describiendo los problemas encontrados.

De hecho, esta clase está tan enfocada a los errores de validación que incluso podemos instanciarla enviándole un ModelState:
[HttpPost]
public ActionResult Submit([FromBody]Order order)
{
if (!ModelState.IsValid)
{
var details = new ValidationProblemDetails(ModelState);
return new ObjectResult(details)
{
ContentTypes = {"application/problem+json"},
StatusCode = 400,
};
}
return Ok(order);
}
Para simplificar aún más este escenario, también se ha añadido en ControllerBase el método ValidationProblem(), que automáticamente retornará un error 400 con la descripción de los errores:
[HttpPost]
public ActionResult Submit([FromBody]Order order)
{
if (!ModelState.IsValid)
{
return ValidationProblem();
}
...
}
Misteriosamente, el retornar el resultado de la invocación a ValidationProblem() no establecerá el content type a "application/problem+json", cuando esto tendría bastante sentido. Supongo que será para evitar que exploten clientes que no estén preparados para recibir ese tipo de contenido.
En cualquier caso, el resultado devuelto por el servicio anterior podría ser el siguiente:
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
Server: Kestrel
X-Powered-By: ASP.NET
Content-Length: 188

{
"errors": {
"ProductsCount": ["The field ProductsCount must be between 1 and 10."]
}
,
"type":null,
"title":"One or more validation errors occurred.",
"status":null,
"detail":null,
"instance":null
}

¿Y cómo se integra esto con el filtro [ApiController]?

Hace unos días hablábamos del nuevo filtro [ApiController], que permite identificar un controlador como endpoint de un API, y aplicarle automáticamente usa serie de convenciones, como el retorno automático de errores 400 cuando se detectan errores de validación.

También veíamos que, jugando un poco con su configuración, era posible establecer la factoría de resultados para las respuestas a peticiones con problemas de validación, por lo que resulta sencillo utilizar este punto de extensión para crear y configurar la respuesta bad request alineada con el estándar:
services.Configure<ApiBehaviorOptions>(options =>
{
options.InvalidModelStateResponseFactory = context =>
{
var problemDetails = new ValidationProblemDetails(context.ModelState)
{
Instance = context.HttpContext.Request.Path,
Status = 400,
Type = "https://myserver.com/problems/validation",
Detail = "Invalid input data. See additional details in 'errors' property."
};
return new BadRequestObjectResult(problemDetails)
{
ContentTypes = { "application/problem+json", "application/problem+xml" }
};
};
});
¡Y eso es todo, al menos de momento! Espero que os haya resultado interesante, y útil para conocer este nuevo estándar y su, aunque aún básica, integración en ASP.NET Core.

Publicado en Variable not found.

» Leer más, comentarios, etc...

Variable not found

Enlaces interesantes 329

julio 09, 2018 06:55

Enlaces interesantes
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

.NET / .NET Core

ASP.NET / ASP.NET Core

Azure / Cloud

Conceptos / Patrones / Buenas prácticas

Data

HTML / CSS / Javascript

Visual Studio / Complementos / Herramientas

Otros

Publicado en Variable not found.

» Leer más, comentarios, etc...

Koalite

APIs con Node, TypeScript, Koa y TypeORM

julio 09, 2018 05:06

En mi (parsimoniosa) búsqueda de plataformas alternativas a .NET más de una vez me he llegado a plantear el uso de NodeJS + TypeScript. A fin de cuentas NodeJS es multiplataforma, ya tiene cierta madurez y es supuestamente estable. Con TypeScript llevo ya un par de años y, pese a sus “cosillas”, estoy razonablemente contento con él.

Por eso cuando hace unos días contactó conmigo Javier Avilés para hablarme sobre un repositorio que ha montado como plantilla para crear APIs con Node, TypeScript, Koa y TypeORM me pareció interesante echarle un vistazo.

OJO: Si has llegado aquí buscando un tutorial sobre cómo crear APIs con Node y TypeScript, mejor léete directamente la documentación de la plantilla creada por Javier. Ahí encontrarás información más útil que en este post. Aquí me limitaré a hacer un repaso somero a lo que me ha parecido la plantilla.

Las acciones web

De NodeJS no hay mucho que contar a estas alturas, y sobre TypeScript ya he escrito suficiente, por lo que intentaré centrarme en otras cosas. Puesto que el proyecto es para montar un API Web, parece razonable empezar por ver qué tipo de servidor web y framework se está usando.

Como framework para crear el API se está usando koa. Sin estar muy metido en node, diría que es una de las librerías/frameworks más populares para servidores web junto con express (del que incluso escribí un tutorial cuando hacía ese tipo de cosas). Conocía koa un poco por sus primeras versiones y recuerdo que hacía un uso llamativo de los generadores para huir del callback hell. En las versiones actuales se aprovecha async/await para conseguir dar un aspecto líneal al código asíncrono haciéndolo bastante claro y legible.

Al igual que la mayoría de frameworks web de lenguajes que no viven encorsetados en clases, la gestión de peticiones y respuestas se realiza mediante funciones que reciben la petición y generan la respuesta, en este caso ambas empaquetas en un objeto context. Lo bueno de este enfoque es que evita código repetitivo y ayuda a que todo sea más fácil de componer:

app.use(async ctx => {
  ctx.body = 'Hello World';
});

Es un estilo que me gustó mucho cuando conocí node, y más aún cuando jugué con él en clojure. Lo cierto es que la filosofía de la web, basada en petición/respuesta, se ajusta muy bien a ser modelada con funciones en lugar de con clases. Además, eso hace que todo sea muy homogéneo, ya conceptos típicos de frameworks webs como middlewares se reducen a crear decoradores sobre funciones.

Precisamente esta es una de las cosas que no me convencen de la plantilla que estamos analizando: el uso de clases estáticas para agrupar estas funciones que sirven de manejadores de peticiones:

export default class UserController {
  public static async getUsers (ctx: BaseContext) {
    // ...
  }
}

El uso de una clase para encapsular en método estático no aporta nada (a menos que me esté perdido algo) y en lenguajes como TypeScript lo consideraría un code smell.

Las rutas

En cualquier aplicación web acaba siendo necesario gestionar rutas, y en este caso se está usando koa-router. No tengo ni idea de si hay más routers para koa o de lo bueno o malo que es éste, pero parece fácil de manejar con el típico API basado en métodos con los nombres de los verbos:

var app = new Koa();
var router = new Router();

router.get('/', (ctx, next) => {
  // ctx.router available
});

app
  .use(router.routes())
  .use(router.allowedMethods());

Entre las librerías que conozco hay varias opciones para gestionar el registro de rutas. Algunas se basan puramente en convenciones (al estilo RoR), otras permiten utilizar metainformación en forma de atributos o anotaciones (uno de los varios estilos soportados ASPNET MVC), y las hay que registran las rutas explícitamente.

En el caso de la plantilla se está haciendo un registro explícito de las rutas y además se hace todo en un único fichero:

// routes.ts

router.get('/users', controller.user.getUsers);
router.get('/users/:id', controller.user.getUser);
// ...

Personalmente me gusta ese estilo. Creo que es cómodo tener centralizada la definición de rutas y poder comprobar de un vistazo qué rutas existen en la aplicación y qué formato siguen. En el caso de que el número de rutas creciese mucho siempre se podría partir en varios ficheros por áreas de aplicación.

La contrapartida que tiene es que cuando añades un nuevo manejador de rutas necesitas tocar en dos sitios: el fichero donde defines la función y el fichero que contiene el registro de rutas. Para mi es un mal menor, pero no deja de ser un incordio y puede dar lugar a fallos si te olvida registrar la ruta del manejador que acabas de crear.

Una cosa que me gusta de la plantilla es que no se usa un contenedor de inversión de control. He visto otras implementaciones de este estilo que tratan de copiar demasiado los patrones de uso de plataformas como .NET y Java, y acaban replicándolas pieza a pieza con componentes que no son realmente necesarios.

Los datos

Para tratar con los datos se está usando TypeORM, una librería que se define a si misma como un ORM que soporta los patrones de Active Record y Data Mapper.

Para mi eso se queda un poco lejos de lo que espero de un ORM. Como Data Mapper estaría al nivel de micro ORMs tipo Dapper o Massive. Como Active Record… bueno, la verdad es que excepto las inspiradas en Rails, no conozco muchas librerías que hayan triunfado con ese modelo.

En muchos casos la mejor opción es usar un Data Mapper que te simplifique la generación de consultas y el mapeo de resultados a objetos. Pero hay que tener en cuenta las partes que te estás perdiendo por uno usar un ORM completo, y que van mucho más allá de generar automáticamente SQL y materializar objetos: identity map, unit of work, persistencia por alcance, etc.

El uso de TypeORM parece sencillo, aunque si eres de los que piensa que tu modelo debe ignorar la persistencia, vete olvidando. Todo se basa en el uso de decoradores sobre tus entidades:

@Entity()
export class User {
    @PrimaryGeneratedColumn()
    id: number;

    @Column({
        length: 80
    })
    @Length(10, 80)
    name: string;

    @Column({
        length: 100
    })
    @Length(10, 100)
    @IsEmail()
    email: string;
}

No me apasiona la idea de contaminar mi modelo de dominio con cosas relacionadas con la base de datos, pero lo cierto es que en el momento en que decides usar TypeORM me da la sensación de que tampoco es que vayas a tener un modelo de dominio muy rico y vas a usar otro tipo de diseño, así que no es tan grave.

En la plantilla se utiliza también class-validator, una librería para incluir reglas de validación de forma declarativa en nuestras “entidades”. De ahí sale por ejemplo el decorador IsEmail del ejemplo anterior.

Hace muchos años escribí en contra de mezclar la validación con las entidades y sigo pensando lo mismo. Una entidad por definición debería mantener sus invariantes y no puede encontrarse en un estado inválido. Sin embargo, por mucho que aquí las llamemos entidades no estamos trabajando más que con DTOs, por lo que tiene más sentido unirlos a las reglas de validación.

Actualización: Me explica Javier que realmente TypeORM sí que tiene persistencia por alcance (usando los decoradores correspondientes) e incluso un cierto soporte para UoW a través de transacciones.

El proyecto

El proyecto usa las herramientas típicas de node y TypeScript. Además permite usar docker para facilitar las pruebas usando una máquina ya preparada con postgreSQL.

No sabía que se podía usar la propiedad engines en el fichero package.json para fijar las versiones de node y npm que requiere el proyecto, pero me ha parecido muy útil teniendo en cuenta lo (no) estable que es todo el ecosistema de Javascript.

Para la parte de TypeScript usa ts-node, que permite ejecutar TypeScript en node compilándolo al vuelo. Lo conocía por haberlo usado con alguna librería de testing. Aun así, para la compilación de producción se está generando javascript, imagino que para evitar tener que pagar el coste de la compilación. No sé si realmente es necesario (supongo que una vez compilado queda todo en memoria y no hay que estar recompilando nada en cada petición), pero parece más limpio y evitas tener la dependencia sobre TypeScript en el entorno de producción.

El código está organizado en carpetas basadas en roles (controllers, entities, …). Nuevamente es cuestión de gustos, pero prefiero organizarlo en base a funcionalidades porque creo que es mejor tener cerca físicamente los ficheros que vas a tener que tocar a la vez.

Echo de menos algunos tests, aunque sean de ejemplo. Cuando desarrollas un API Web muchas veces no tiene mucho sentido recurrir a tests unitarios, y montar test de integración supone más esfuerzo, por lo que tener un ejemplo de cómo se podrían escribir vendría bien. Teniendo además la imagen de docker para levantar la base de datos imagino que no debería ser demasiado complicado preparar el entorno.

En resumen

Me ha gustado la plantilla que ha preparado Javier para este tipo de proyectos. Puede servir como base para desarrollar un API Web basada en TypeScript y Koa, y es lo bastante pequeña como para que pueda leerte todo el código en un rato y entenderlo sin problemas. Entre las cosas que me han gusto un poco menos está el uso (para mi innecesario) de métodos estáticos y la organización basada en roles en lugar de funcionalidades, pero son detalles menores.

Se agradece que no haya intentado meter demasiadas cosas innecesarias y que no sea una copia directa de un proyecto en Sprint o ASP.NET MVC, como pasa en otras plantillas basadas en TypeScript que tiene un aspecto demasiado enterprise/javero/nettero para mi gusto.

Posts relacionados:

  1. TypeScript, un lenguaje diseñado para las herramientas
  2. Extender tipos existentes en TypeScript
  3. Mantenimiento de invariantes en TypeScript

» Leer más, comentarios, etc...

Bitácora de Javier Gutiérrez Chamorro (Guti)

C++ Builder in the requirements

julio 08, 2018 11:43

Como integrante del programa MVP de Embarcadero fui invitado para confeccionar a un call for papers acerca de C++ Builder. El tiempo apremiaba, así que opté por desarrollar con mayor formalisto, que no rigurosidad, lo que os explicaba en ¿Por qué C++ Builder. De esa manera es como surgió mi autoría en el memorando (whitepaper) […]

La entrada C++ Builder in the requirements aparece primero en Bitácora de Javier Gutiérrez Chamorro (Guti).

» Leer más, comentarios, etc...

Navegapolis

Scrum no se logra con pensamiento de grupo, sino con inteligencia colaborativa

julio 07, 2018 04:29

Un equipo autogestionado no tiene por qué ser ágil, ya que al igual que ocurre con los individuos, los equipos se conducen por su propia inteligencia —inteligencia colectiva—(1) que puede ser colaborativa, o simplemente pensamiento de grupo.

Aplicar prácticas ágiles en equipos autogestionados no es suficiente. Se necesita además inteligencia colaborativa.

Los equipos ágiles actúan con inteligencia colaborativa, no con pensamiento de grupo.

Inteligencia colaborativa:

Es una forma de inteligencia emergente de la acción de muchos individuos que interactúan entre sí en el contexto de la cultura digital. En ella cada individuo actúa de manera autónoma desde su posición, participando en una red para crear algo o solucionar algún problema.

Wikipedia-es "Inteligencia colaborativa" 8-jul-2018

Pensamiento de grupo:

Pensamiento de grupo (groupthink en inglés) es una expresión acuñada por el psicólogo Irving Janis en 1972 para describir el proceso por el cual un grupo puede tomar decisiones malas o irracionales. En una situación de pensamiento en grupo, cada miembro del grupo intenta conformar su opinión a la que creen que es el consenso del grupo. Esto parece ser una manera muy racional de afrontar la situación. Sin embargo, resulta en una situación en la cual el grupo en definitiva se pone de acuerdo en determinada acción que cada miembro individualmente considera desaconsejable.

La definición original de Janis era: «Un modo de pensamiento que las personas adoptan cuando están profundamente involucradas en un grupo cohesivo, cuando los esfuerzos de los miembros por unanimidad hacen caso omiso de su motivación para valorar realísticamente cursos de acción alternativos» ... El pensamiento de grupo tiende a ocurrir en comités y en grades organizaciones.

Wikipedia-es "Pensamiento de grupo" 8-jul-2018

 

 

pensamiento de grupo

(1) Referencias - MIT - Anita Williams.

» Leer más, comentarios, etc...

Poesía Binaria

Píldora: Utilizar arrays con nombre dinámico en Bash

julio 04, 2018 07:34

Arrays con nombre dinámico en Bash

Una de las grandes ventajas de los lenguajes interpretados es que podemos almacenar en una variable el nombre de otra variable y trabajar con su valor. ¿Punteros? Bueno, al final es parecido a la utilización de punteros en C, aunque aquí podemos hacer referencia por el mismo nombre de la variable incluso, previo filtrado y con mucho cuidado, preguntarle al usuario el de la variable para trabajar con ella.

Esto nos puede dar mucha flexibilidad en nuestro código. Por ejemplo, yo lo he utilizado para perfeccionar mi script de lectura de ficheros de configuración al que le podemos pasar también el nombre de la variable donde almacenar la configuración.

Arrays con nombre dinámico

En Bash, acceder a una variable cuyo nombre está contenido dentro de otra variable es sencillo, podemos hacerlo llamando a ${!NOMBREDEVARIABLE}. Podemos ver un ejemplo en el post referenciado.
El problema es que cuando son arrays no es tan inmediato. El objetivo es que, teniendo una variable que contiene el nombre del array podamos acceder a su información de una forma sencilla. Y El problema aquí viene en la versión de Bash que estemos utilizando. En este caso debemos hacerlo de una forma u otra dependiendo de si utilizamos una versión inferior a la 4.3 (más o menos salió en 2014) o si tenemos una versión posterior.

Ejemplo para Bash < 4.3

Lo siento, mira que no me gusta utilizar eval, pero claro, para estas versiones del intérprete necesitamos crear una cadena de caracteres con la llamada que vamos a hacer y luego evaluar dicha cadena de caracteres. Esto nos dará el valor que buscamos. Por ejemplo:

1
2
3
4
5
6
MIARRAY=("cero" "uno" "dos" "tres")
REFERENCIA="MIARRAY"

# Lo que necesitamos es acceder a cada uno de los elementos de MIARRAY a través de REFERENCIA.

eval echo \${$REFERENCIA[2]}

Si os fijáis, al construir la cadena. El primer símbolo de dólar ($) lo escapamos con la barra para que no se interprete. El que sí tiene que interpretar es el segundo, para que $REFERENCIA se transforme en el nombre del array.

Lo podemos hacer con arrays asociativos también sin problema, pero es algo complicado y realizamos demasiadas tareas para hacer referencia a una variable. Además no queda muy elegante o intuitivo tener que escapar un dólar y otro no.

Ejemplo para Bash >= 4.3

Para estas versiones, disponemos de un modificador en la orden declare (también llamada typeset) a través del cual podemos crear una variable de referencia que se comportará exactamente igual que nuestro array:

1
2
3
4
MIARRAY=("cero" "uno" "dos" "tres")
declare -n REFERENCIA="MIARRAY"

echo ${REFERENCIA[2]}

Además, de esta forma, el nombre de la variable puede venir dado en otra variable, con lo que podemos permitir que el usuario especifique el nombre de variable. Eso sí, con mucho cuidado.

Foto principal: unsplash-logoRuben Ortega

The post Píldora: Utilizar arrays con nombre dinámico en Bash appeared first on Poesía Binaria.

» Leer más, comentarios, etc...

Variable not found

Enlaces interesantes 328

julio 02, 2018 02:00

Enlaces interesantes
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

.NET / .NET Core

ASP.NET / ASP.NET Core

Azure / Cloud

Conceptos / Patrones / Buenas prácticas

Data

HTML / CSS / Javascript

Visual Studio / Complementos / Herramientas

Xamarin

Otros

Publicado en Variable not found.

» Leer más, comentarios, etc...

Variable not found

¡Microsoft MVP 2018-2019!

julio 02, 2018 06:58

MVP Award ProgramEn esta ocasión sólo quería compartir con vosotros la gran alegría que supone ser honrado de nuevo con el galardón Microsoft MVP por las contribuciones y aportaciones realizadas a la comunidad de desarrolladores a lo largo del año pasado.

Son ya ocho años consecutivos y debería haberme acostumbrado a este subidón de primeros de julio, pero, como no suelo ser consciente de que ha llegado el día de los nombramientos, sigo recibiendo el conocido email de nombramiento casi con la misma emoción que aquella primera vez en que me pilló completamente desprevenido.

Muchas gracias a todos vosotros, amigos y amigas de Variable not found, porque si estoy aquí es porque me habéis regalado vuestro incondicional apoyo durante todos estos años.

Muchas gracias también al equipo del programa MVP en Microsoft y, en particular, a nuestra querida MVP lead Cristina González, por el gran trabajo que realizan.

Muchas gracias todos los que dedicáis vuestro tiempo la comunidad, seáis MVP o no, porque hacéis posible que todos aprendamos y mejoremos un poco más cada día.

Y, por supuesto, muchas gracias también a mi mujer e hijas, Inma, Inmita y María, porque ellas son las que permiten, con su infinita paciencia y comprensión, que pueda dedicar a mi pasión por el software más de lo que estrictamente requieren mis obligaciones profesionales.

Aprovecho también para enviar mi enhorabuena a los MVP renovados recientemente, y un caluroso abrazo de bienvenida a los que lo han sido por primera vez (es un momento muy bonito, ¡disfrutadlo!)

Sólo espero estar a la altura de esta distinción, compartida con gente de todo el mundo a la que admiro tanto personal como profesionalmente, y entre los que me enorgullezco de contar con grandes amigos. Y ahora, con esta dosis extra de motivación, ¡a seguir trabajando!

Desarrollador supermotivado
Source: Giphy

Publicado en Variable not found.

» Leer más, comentarios, etc...

Meta-Info

¿Que es?

Planeta Código es un agregador de weblogs sobre programación y desarrollo en castellano. Si eres lector te permite seguirlos de modo cómodo en esta misma página o mediante el fichero de subscripción.

rss subscripción

Sponsors

Puedes utilizar las siguientes imagenes para enlazar PlanetaCodigo:
planetacodigo

planetacodigo

Si tienes un weblog de programación y quieres ser añadido aquí, envíame un email solicitándolo.

Idea: Juanjo Navarro

Diseño: Albin