Contenedores: cómo es el ciclo de vida de una aplicación en Kubernetes

21/03/2019
Artículo original

Hace poco os explicaba en un artículo qué es Kubernetes, cuál es su arquitectura y su funcionamiento básico. Léelo antes de continuar si no tienes claros estos conceptos.

En esta ocasión voy a continuar con aquella explicación analizando cómo es el ciclo de vida de una aplicación que está desplegada con Kubernetes.

Lo primero que debemos tener claro es que en Kubernetes nunca se ejecutan contenedores de forma directa. Es decir, no se puede desplegar un contenedor o parar un contenedor. En su lugar se opera con lo que se llaman pods.

Un pod es la unidad mínima de despliegue y operación en Kubernetes. Es decir, desplegamos pods, escalamos pods y son los pods los que se ejecutan en los distintos nodos.

La relación entre pod y contenedor no tiene por qué ser de uno a uno: es decir, en un único pod se pueden ejecutar varios contenedores. Solo recuerda que en este caso se escalarán y desplegarán de forma conjunta (ya que se escala o despliega todo el pod).

Aunque es posible, teóricamente, desplegar en un pod una web y su API en dos contenedores, eso no es lo que suele hacer. En la gran mayoría de casos las relaciones entre pod y contenedor son, efectivamente, de uno a uno. Pero que un pod pueda ejecutar varios contenedores habilita ciertos escenarios avanzados como p. ej. tener un contenedor que ofrezca servicios a otro contenedor (como podría ser hacer de proxy, de logger o similar).

Es importante tener presente que todos los contenedores que se ejecutan en un mismo pod comparten espacio de red. Es decir, se comunican entre ellos usando localhost y no pueden abrir los mismos puertos. También comparten el espacio IPC por lo que pueden usar cualquier técnica de IPC (como semáforos) para comunicarse entre ellos.

Los distintos estados de un pod

Un pod pasa por varias fases a lo largo de su ciclo de vida:

  • Pending: el pod ha sido creado, pero aún no se han creado sus contenedores ni se ha decidido qué nodo lo va a ejecutar.
  • Running: los contenedores del pod han sido creados y el pod ya se está ejecutando en un nodo. Al menos un contenedor del pod se está ejecutando o está en proceso de creación.

Esto es importante: que un pod esté en estado running no significa que sus contenedores estén ejecutándose. P. ej. se pueden estar iniciando o reiniciando.

  • Succeeded: los contenedores del pod han finalizado (todos) su ejecución de forma satisfactoria.
  • Failed: los contenedores del pod han finalizado (todos) su ejecución y al menos uno de ellos lo ha hecho con error.
  • Unknown: el estado del pod no se puede saber. Esto suele indicar un error de comunicación con el nodo minion que está ejecutando el pod.
  • CrashLoopBackOff: el pod está corriendo, pero uno de sus contenedores se está reiniciando debido a que ha terminado (generalmente de forma errónea).

Es importante separar el ciclo de vida del pod del ciclo de vida de sus contenedores. Un pod puede estar en la fase de running pero uno de sus contenedores puede no estar ejecutándose. Cuando un pod está en fase de CrashLoopBackOff eso significa que uno de los contenedores está en proceso de reinicio, pero otros contenedores del pod pueden estar ejecutándose.

Muchas veces se dice que Kubernetes reinicia un pod pero esa expresión no es estrictamente cierta: Kubernetes reinicia contenedores de un pod, pero el pod en sí mismo sigue ejecutándose durante todo este tiempo. Que Kubernetes decida reiniciar o no los contenedores de un pod (y en qué casos) depende de la configuración del pod. Es decir, para ciertos pods no hay posibilidad de que entren nunca en fase de Succeeded ya que su misión es estar ejecutándose permanentemente (p. ej. una API), por lo que si un contenedor termina será reiniciado por Kubernetes.

Los pods se consideran "objetos transitorios", en el sentido de que hay determinados eventos del clúster a los cuales no sobreviven. P. ej. si el nodo minion se cae, todos los pods que se estén ejecutándose en él se caen también. Los pods no se mueven de nodo ni se reinician (sí se reinician sus contenedores como se ha comentado antes).

En general no se suele crear nunca pods de forma directa, en su lugar usamos lo que llamamos un controlador. Un controlador es el responsable de garantizar que en todo momento se cumple una cierta condición al respecto de los pods que controla, como que en todo momento haya N instancias de este pod.

Hago aquí un inciso de nomenclatura: cuando digo "N instancias de un pod" me refiero a N pods idénticos (ejecutando los mismos contenedores y con la misma configuración) pero son N pods.

Si estamos usando un controlador y deseamos tener en todo momento 2 instancias de un determinado pod y uno de los dos pods se muere (porque se muere su nodo p. ej.), el controlador creará otro pod para asegurar de que siga habiendo dos instancias.

Cuando tenemos N instancias, los N pods se consideran todos "idénticos". Si por algún motivo (p. ej. debe desescalarse) debe eliminarse algún pod, el controlador eliminará uno cualquiera, sin preferencias. Eso encaja con el modelo stateless de aplicación en el que los contenedores encajan perfectamente. Es decir, como desarrollador debes asegurar que tus contenedores sean stateless, ya que en cualquier momento Kubernetes puede decidir eliminar el pod (y por lo tanto el contenedor) y recrearlo en otra parte.

Este modelo stateless no siempre aplica: a veces, si tenemos N instancias de un pod hay alguno que juega un rol especial y por lo tanto se requiere que estos tengan identidad. Un ejemplo es una configuración de base de datos en modo maestro/esclavo. Si uno de los pods se cae, el nuevo que se cree debe ser del mismo tipo, y no solo eso, sino que debe recibir el estado que tenía el pod caído. Kubernetes es capaz de gestionar estos casos mediante un controlador específico (llamado StatefulSet), pero lo ideal es que nuestras aplicaciones sean stateless.

La calculadora de Windows es el proyecto más popular de todo GitHub desde que Microsoft liberó su código

20/03/2019
Artículo original

La calculadora de Windows es el proyecto más popular de todo GitHub desde que Microsoft liberó su código

A principios de marzo, Microsoft decidió liberar el código de la calculadora de Windows y lo publicó en GitHub. Es claramente una aplicación que no necesita presentación, y también una que se une a la ya bastante larga lista de colaboraciones que ha venido haciendo Microsoft al ecosistema open source.

Lo que quizás es más sorprendente de todo esto, es el enorme interés que ha generado entre la comunidad de desarrolladores. Tanto interés así, que el repositorio de la calculadora de Windows ha sido el proyecto más popular durante todo el mes en GitHub.

La calculadora tiene casi 14.000 estrellas en GitHub, y curiosamente, el único repositorio que le llega cerca en popularidad, es otro proyecto sumamente interesante liberado esa misma semana: Ghidra, la herramienta de ingeniría inversa de la NSA que también pasó a ser de código abierto en marzo.

Contando bugs en la Calculadora de Windows

Calculadora De Windows

Gracias a que Microsoft liberó el código de la app, son muchos los desarrolladores que pueden no solo usar el código para sus propios proyectos, o para aprender, sino los que pueden evaluarlo y sugerir mejoras.

Esto es parte de lo bonito del open source, y la comunidad está bastante interesada en aprovechar la oportunidad para demostrar la importancia del análisis estático, incluso en proyectos pequeños como este.

Es así como un grupo de desarrolladores ya ha encontrado un número significativo de fragmentos de código sospechoso y bugs en la simple herramienta, desde fugas de memoria, a información que envía la calculadora a los servidores de Microsoft.

El código de la calculadora de Windows fue liberado con la misma licencia que el gestor de archivos de Windows 3.0, es decir una licencia MIT que es sumamente permisiva. Esta pone muy pocas restricciones para la reutilización del código, es compatible con muchas licencias copyleft, incluyendo la GPL, y por ello es la licencia más popular en todo GitHub.

Logpoints en Chrome: una excelente utilidad para depurar y no ensuciar el código

16/03/2019
Artículo original

Una de las novedades que trae Chrome 73 es pequeña pero súper-interesante. Se trata de los Logpoints.

Un logpoint es un tipo especial de punto de interrupción que podemos añadir a nuestro código JavaScript y que, en lugar de detener la ejecución del código, se limita a "loguear" a la consola lo que le digamos. Esto nos evita tener que andar metiendo console.log constantemente en el código tan solo para ver algunos valores.

Obviamente disponemos de muchas otras maneras de ver los valores durante la ejecución, siendo el más obvio el de añadir "watches" (o "ojeadores", como me gusta llamarlos a mi), para ir viendo cómo cambian ciertos valores y expresiones. Sin embargo console.log sigue siendo muy interesante si, por ejemplo, queremos tener un histórico de todos los valores que pasan por una variable sin tener que estar siguiendo la ejecución paso a paso del código.

Así, podemos añadir un logpoint pulsando con el botón secundario sobre el número de línea en donde nos interese meterlo, así:

Animación que muestra cómo se pone el punto de log

y escribimos la expresión que queramos que aparezca en la consola de depuración al pasar por ese punto. El nuevo logpoint se verá de color naranja.

La expresión no tiene por qué ser simplemente el nombre de una variable, sino que cualquier expresión o código JavaScript válido que pudieras meter en un console.log puedes escribirlo también aquí.

A partir de este momento, cada vez que el código pase por ahí se nos mostrará por consola la expresión que le hayamos indicado:

El resultado de mostrar por consola la expresión anterior

En este caso se trata de un objeto representando un anuncio, con todas sus propiedades, que podemos examinar con detalle desplegándolo en la consola.

Nota: si te fijas en la figura anterior, aunque se muestra el objeto completo lo que no vemos es cuál era su nombre, por lo que si teneos varios puntos de log con datos parecidos a mostrar, puede ser fácil perdernos. Un truco interesante es envolver la variable que vamos a mostrar entre llaves, en este caso así: {anuncio}. Al hacerlo, lo que se muestra por consola es un objeto con una única propiedad llamada anuncio que contiene a nuestro objeto.Esto nos ayuda a ver también el nombre de lo que estamos mostrando y facilita el seguimiento en estos casos:

El resultado esta vez envuelto en un objeto

Si pulsamos sobre el punto de log con el ratón, al igual que pasa con cualquier punto de interrupción se elimina. Pero ojo, porque si lo vuelves a pulsar reaparece pero no conserva sus propiedades, es decir, obtenemos un punto de interrupción normal y corriente de color azul, en el que se detendrá el código.

Si pulsamos sobre él con el botón derecho se nos da la opción de editarlo, y desde el mini-diálogo de edición, aparte de cambiar la expresión a mostrar podemos desplegar las opciones para transformarlo en un punto de interrupción normal o condicionado:

Animación que muestra cómo se edita el punto de log

Finalmente, cabe preguntarse una cosa: cuando se llega a un logpoint y se muestra algo por consola ¿el código de la línea actual se ha ejecutado ya o no?. Es decir, ¿el logpoint es equivalente a poner un console.log antes o después de esa línea?

La respuesta es que es equivalente a ponerlo antes. Por lo tanto cuando lo colocas la línea actual todavía no se ha ejecutado. Tenlo en cuenta al utilizarlos.

¡Espero que te resulte útil!

SAP hace Open Source su herramienta de análisis de vulnerabilidades para Java y Python

15/03/2019
Artículo original

SAP acaba de hacer Open Source y liberar por tanto el código de su herramienta de evaluación de vulnerabilidades de código VAT (Vulnerability Assesment Tool).

La herramienta sirve para analizar código de Java y de Python, y ha sido probada durante dos años internamente, realizando más de 20.000 análisis en unos 600 proyectos de la compañía.

Se centra en la detección de componentes Open Source que utilice tu proyecto y que sean vulnerables, y utiliza tanto análisis estático como testeo automatizado para determinar el contexto en el que se ejecuta el código y mejorar la precisión de los resultados. Así:

  • Detecta si hay dependencias de componentes de código abierto que tengan vulnerabilidades conocidas y además te informa de novedades de seguridad relacionadas con ellos.
  • Recaba evidencias sobre la ejecución del código vulnerable en diversos contextos de la aplicación
  • Da soporte a los desarrolladores para que puedan arreglar los problemas.

Trata de abordar todos los problemas especificados en el Top10 de OWASP A9, que suelen ser las causas de la mayor parte de las brechas de seguridad. Utiliza las bases de datos de vulnerabilidades  del gobierno estadounidense, y la lista CVE. Funciona tanto en desarrollo como en producción.

Según SAP, la mayor parte de los problemas de seguridad que se producen en las aplicaciones expuestas a Internet son causadas por no actualizar componentes que se sabe que son vulnerables. Muchas empresas tardan meses en hacerlo y otras no lo hacen nunca. Con VAT la idea es que puedas arreglarlas a las pocas horas o como mucho, días.

Se puede usar directamente como un contenedor Docker para ponerlo a funcionar de manera rápida y sencilla. Y por supuesto se puede descargar el código fuente y compilarlo.

Aquí te dejamos la página en Github del proyecto.

¿Qué es Kubernetes y cómo funciona?

14/03/2019
Artículo original

Imagen ornamental creada por campusMVP

Con el auge actual de los contenedores es posible que te hayas empezado a plantear el poner tu aplicación en contenedores. O es posible que ya lo estés haciendo. Sea cual sea tu caso, es probable que estés usando (o considerando el uso) de Kubernetes. En este artículo vamos a ver qué es Kubernetes y cómo funciona. No es el objetivo de este post el que veas "cómo desarrollar para Kubernetes" sino que entiendas qué componentes forman parte de Kubernetes y cuál es el rol de cada uno de ellos.

¿Qué hace Kubernetes?

Esa es la primera pregunta que debemos responder: para entender cómo funciona, es importante que veamos qué rol juega Kubernetes. Como seguramente sabrás se lo cataloga como un "orquestador de contenedores", lo que lo sitúa en la misma lista de productos como Swarm, Marathon o EC2.

Aquí te dejamos una lista con los 10 mejores orquestadores de Docker

Un orquestador es el encargado de gestionar el ciclo de vida de los contenedores de una aplicación (cierto es que el concepto de "orquestador" en general es mucho más amplio, pero en este artículo nos centraremos solo en los orquestadores de contenedores). Por lo tanto, los servicios que suele ofrecer un orquestador son los siguientes:

  • Manejo del clúster (permitir añadir o quitar nodos al clúster)
  • Gestión del ciclo de vida de los contenedores (p. ej. reiniciar contenedores que fallen)
  • Service Discovery (que un contenedor pueda encontrar las rutas IP/DNS de otro contenedor)
  • Servicios de red y load-balancing (repartir la carga entre las distintas máquinas del clúster)
  • Servicios de monitorización
  • Servicios de chequeo de estado de salud (del clúster y de cada uno de los contenedores)

Kubernetes ofrece todos esos servicios (y algunos más como auto-escalado o gestión del estado) y se ha convertido en el estándar de facto para el despliegue de aplicaciones basadas en contenedores.

La arquitectura de Kubernetes

Debes ver a Kubernetes más como un "proyecto" que como un "producto": en efecto, Kubernetes se apoya en muchos otros productos ya previamente existentes (como etcd) y los combina con otros desarrollos propios. Instalar y configurar un clúster de Kubernetes on-premises no es algo sencillo y es precisamente por eso que los servicios de Kubernetes "manejados" son tan populares. Estos servicios permiten disponer de un clúster Kubernetes correctamente instalado y levantado en cuestión minutos.

Los servicios "manejados" son los proporcionados por un proveedor de cloud y gestionados por éste, como por ejemplo AKS, EKS o GKE.

Arquitectura de Kubernetes

Un clúster de Kubernetes se compone de varias máquinas. Cada una de esas máquinas (nodos) debe jugar uno de los siguientes roles:

  • Nodo master
  • Nodo minion

No hay más: una máquina o es un nodo master o es un nodo minion. A pesar de que Kubernetes puede funcionar con un solo nodo, un clúster de Kubernetes productivo debería tener un mínimo de 5 máquinas (tres nodos master y dos minion).

Nodos master

Los nodos master son los encargados de coordinar el clúster. Por lo general los nodos master no ejecutan contenedores. Aunque está permitido que lo hagan, no es un escenario recomendado en producción. Todo clúster de Kubernetes debe tener al menos un nodo master.

Los nodos master son los encargados de decidir en qué nodo (minion) se ejecuta cada contenedor, de mantener el estado del clúster, de asegurar que en todo momento hay el número deseado de contenedores en ejecución y de actualizar las aplicaciones de forma coordinada cuando se despliegan nuevas versiones.

Un nodo master ejecuta los siguientes procesos:

  • etcd: Etcd es una base de datos de tipo (clave, valor) que se utiliza para mantener la configuración global del clúster. La información contenida en etcd es crítica y debe tenerse siempre un plan de copias de seguridad.
  • kube-apiserver: los nodos master exponen una API que es usada para los nodos minion y los clientes del clúster para comunicarse.
  • kube-scheduler: es el componente de Kubernetes encargado de decidir en qué nodo se ejecuta un determinado contenedor.
  • kube-controller-manager: es el encargado de ejecutar los distintos controladores. Un "controlador" es el encargado de asegurar que en todo momento se cumple el estado deseado de la aplicación y del clúster (p. ej. que en todo momento haya 5 instancias de un contenedor determinado).

Un nodo master no ejecuta contenedores, así que no necesita tener instalado Docker y ninguno del resto de elementos necesarios para un nodo minion que enseguida veremos.

¿Por qué un clúster productivo debe tener un mínimo de 3 nodos máster?

Esto es debido a etcd. Recuerda que etcd se usa para guardar el estado global del clúster y su información es crítica. Si tienes tres nodos de etcd y pierdes uno, el sistema puede seguir funcionando, ya que los dos nodos restantes pueden seguir verificándose el uno al otro. Pero ya no puedes perder ningún otro. Por eso, los nodos de etcd se escalan siempre de dos en dos: si tienes tres te puedes permitir perder uno, si tienes cinco puedes perder dos y así sucesivamente. Por supuesto se asume que estas pérdidas son temporales (es decir un nodo se cae y el clúster sigue funcionando mientras añadimos otro nodo).

Precisamente como Kubernetes se compone de varios productos, es complicado crear un clúster de alta disponibilidad: en el párrafo anterior se mencionaba etcd, pero la disponibilidad del resto de componentes debe tenerse en cuenta también. De hecho hay instalaciones de Kubernetes en las que etcd corre en nodos separados: es decir tenemos un mínimo de tres nodos master (sin etcd), tres nodos más con etcd y dos nodos minion.

En definitiva: gestionar un clúster de Kubernetes con alta disponibilidad no es nada sencillo.

Nodos minion

Un nodo minion es aquel que ejecuta los contenedores desplegados en el clúster. Se compone de tres elementos básicos:

  • Motor de contenedores: obviamente el motor de contenedores debe estar instalado en el clúster. Mucha gente presupone que Kubernetes solo puede ejecutar contenedores Docker pero eso no es estríctamente cierto. De serie, Kubernetes puede ejecutar Docker y rkt siendo posible integrarlo con otros motores existentes a través de CRI.
  • kube-proxy: encargado de gestionar la red virtual y las IPs virtuales asignadas a cada contenedor.
  • kubelet: el componente más importante de un nodo minion, cuya función principal es asegurarse de que todos los contenedores que deben ejecutarse en este nodo se están ejecutando. Es decir, cuando a kubelet se le ordena poner en marcha un contenedor, lo pone en marcha y luego monitoriza que siga en marcha (reiniciándolo si el contenedor termina debido a una excepción no controlada) hasta que le llega la orden de parar el contenedor.

Otros elementos de Kubernetes

Al margen de los elementos anteriores hay un conjunto de addons que se ejecutan en el clúster. Estos addons son como contenedores (pods en la terminología de Kubernetes) y son opcionales: pueden estar presentes o no. Suelen ejecutarse en el espacio de nombres kube-system y ofrecen servicios transversales. Los más conocidos son:

  • Web Dashboard: ofrece una interfaz web gráfica para monitorizar y gestionar el clúster:

Imagen del Dashboard

  • Monitorización de clúster, basado en cAdvisor y que kubelet expone para ser consultado.
  • Sistemas de logging centralizado.
  • DNS interno: este addon es especial porque, a pesar de ser opcional por definición, se puede considerar como si fuese obligatorio ya que casi siempre se asume que tenemos un sistema de DNS dentro del clúster. La mayoría de clústeres usan kube-dns para ello.

Estos son los addons principales, pero hay muchos más.

El ecosistema de TensorFlow para programadores principiantes y expertos en Machine Learning: cursos, lenguajes y Edge Computing

13/03/2019
Artículo original

El ecosistema de TensorFlow para programadores principiantes y expertos en Machine Learning: cursos, lenguajes y Edge Computing

TensorFlow es la apuesta clave de Google para construir el ecosistema del futuro del Machine Learning que pueda ser ejecutado en la nube, en aplicaciones o en dispositivos hardware de todo tipo.

Precisamente, los esfuerzos en su última TensorFlow Dev Summit 2019 han ido enfocados en facilitar y simplificar el uso del framework, incorporando más API tanto para los programadores principiantes como para los más expertos. De este modo, todos podremos aprovecharnos de las nuevas mejoras para crear modelos de aprendizaje más fácilmente para la mayor número de casos de uso y desplegarlos en cualquier dispositivos.

Han impulsado el despliegue de los algoritmos de forma local en dispositivos hardware con la release final de TensorFlow Lite 1.0 sin necesidad de recurrir a la nube u otro sistema centralizado para ser procesados. Un claro ejemplo de que el Edge Computing forma parte de la estrategia clave de Google para dotar a cualquier dispositivo, ya sea IoT o móvil, de todas las ventajas del aprendizaje automático.

En los tres años que han pasado desde su lanzamiento, TensorFlow ha sentando las bases de un ecosistema de Machine Learning end-to-end, ayudando a potenciar la revolución del Deep Learning. Cada vez hay más desarrolladores que hacen uso de algoritmos para implementar nuevas funcionalidades a los usuarios o acelerar tareas hasta ahora tediosas como la clasificación de imágenes, la captura y reconocimiento de documentos o el reconocimiento de voz y la síntesis del lenguaje natural en los asistentes virtuales (Google Assistant o Alexa)

No es extraño que TensorFlow sea el proyecto con mayor número de contribuciones en Github año tras años, con más de 1.800 contribuciones. Acumulando más de 41 millones de descargas en tres años de historia y decenas de ejemplos de uso en distintas plataformas.

Tensorflow

El camino hacia TensorFlow 2.0

TensorFlow ha sentando las bases de un ecosistema de Machine Learning end-to-end, ayudando a potenciar la revolución del Deep Learning

TensorFlow 2.0 Alpha se ha fijado el objetivo de simplificar su uso, ampliando las posibilidades para ser una plataforma de ML más abierta que puede ser utilizada tanto por investigadores que quieran realizar experimentos y estudios, desarrolladores dispuestos a automatizar cualquier clase tarea o empresas que quieran facilitar la experiencia de uso de sus usuarios a través del inteligencia artificial.

Uno de los pilares de TensorFlow 2.0 es la integración más estrecha con Keras como la API de alto nivel para construir y entrenar modelos de Deep Learning. Keras tiene diversas ventajas:

  • Enfocada en el usuario. Keras tiene una interfaz más simple y consistente, adaptada a los casos de uso más comunes. Facilitando un feedback más claro para entender los errores de implementación.
  • Ser más modular y reutilizable. De este modo los modelos de Keras puede componer estructuras más complejas a través de capas y optimizadores sin necesidad de un modelo específico para entrenar.
  • Pensado tanto para principiantes como para expertos. Aprovechando como idea fundamental el background de los diversos tipos de programadores que se están involucrando desde el principio en el desarrollo de Deep Learning. Keras provee una API mucho más clara sin necesidad de ser un experto con años de experiencia.

También se han incorporado una amplia colección de datasets públicos preparados para ser utilizados con TensorFlow. Cualquier desarrollador que se haya aventurado a trabajar en Machine Learning sabe, esto representa el ingrediente principal para crear modelos y entrenar los algoritmos que después emplearemos. Tener esa ingente cantidad de datos ayuda bastante.

Para la migración de TensorFlow 1.x a 2.0 se han creado diversas herramientas para convertir y migrar los modelos. Ya que se han realizado actualizaciones necesarias para que sean más óptimos y pueden ser desplegados en más plataformas.

El ecosistema sigue creciendo con numerosas librerías para crear un entorno de trabajo más seguro y privado. Como el lanzamiento de la librería TensorFlow Federated, cuya intención es descentralizar el proceso de entrenamiento para compartirlo con múltiples participantes que puedan ejecutarlo localmente y envíen los resultados sin exponer necesariamente los datos capturados, sólo compartiendo el aprendizaje obtenido para la generación de los algoritmos. Un claro ejemplo de esto es el aprendizaje automático de los teclados virtuales, como el de GBoard de Google, que no expone datos sensibles, ya que va a aprendiendo localmente en el propio dispositivo.

Federated Tensor Flow Gboard

Al hilo de esto, el equilibrio entre Machine Learning y la privacidad es una tarea compleja, por ello se ha lanzado la librería de TensorFlow Privacy que permite definir distintos escenarios y grados para salvaguardar los datos más sensible y anonimizar la información de entrenamiento de los modelos.

Python no está solo en TensorFlow, más lenguajes como Swift o Javascript se unen a la plataforma

Python sigue siendo una pieza fundamental en el ecosistema Machine Learning y a la vez ha recibido un gran impulso al ser uno de los lenguajes principales

Obviamente, Python sigue siendo una pieza fundamental en el ecosistema Machine Learning y a la vez ha recibido un gran impulso al ser uno de los lenguajes principales con decenas de librerías entre las más utilizadas, a parte de su gran madurez. No sólo en TensorFlow, sino en otras plataformas como PyTorch.

Pero el ecosistema de TensorFlow ha abierto sus puertas incorporando librerías como TensorFlow.js, que finalmente alcanza la versión 1.0 Con más de 300.000 descargas y 100 contribuciones. Permite ejecutar proyectos ML en el navegador o el en backend con Node.js, tanto modelos ya pre entrenados como construir entrenamientos.

Empresas como Uber o Airbnb ya lo están utilizando en entornos de producción. Hay una amplia galería de ejemplos y casos de uso utilizando JavaScript junto a TensorFlow

Tensor Flow Switf

Otra de las grandes novedades es el avance en la implementación de TensorFlow en Swift con su versión 0.2. De esta forma incorporan un nuevo lenguaje de propósito general como Swift al paradigma ML con todas las funcionalidades para que los desarrolladores puedan acceder a todos los operadores de TensorFlow. Todo ello construido sobre las bases de Jupyter y LLDB.

Ejecutar localmente nuestros modelos con Tensor Lite: la apuesta por el Edge computing

Edge computing se basa en ejecutar modelos y hacer inferencias directamente en local sin depender de que tengan que ser enviados los datos para ser analizados a la nube.

El objetivo de TensorFlow Lite es impulsar definitivamente el Edge Computing en los millones de dispositivos que a día de hoy son capaces de ejecutar TensorFlow. Es la solución para ejecutar modelos y hacer inferencias directamente sin depender de que tengan que ser enviados los datos para ser analizados a la nube.

En Mayo de 2017 fue presentado en la conferencia de desarrolladores de Google IO con una versión preview. Esta semana ha alcanzado la versión definitiva TensorFlow Lite 1.0. Lo que ayudará a implementar diversos casos de uso como la generación de texto predictivo, la clasificación de imágenes, la detección de objetos, el reconocimiento de audio o la síntesis de voz, entre otros muchos escenarios que se pueden implementar.

Esto permite una mejora de rendimiento considerable debido a la conversión al modelo de TensorFlow Lite que permite la herramienta, como por el aumento de rendimiento para ser ejecutado en las GPU de cada dispositivo, incluyendo Android, por ejemplo.

Con ello, TensorFlow Mobile comienza a ser deprecado, salvo que realmente queramos realizar entrenamientos directamente desde el mismo dispositivo. Ya han confirmado que dentro del roadmap de esta versión Lite están trabajando en esto mismo, desvelaron ciertas funcionalidades interesantes como el aprendizaje acelerado con la asignación de pesos para mejorar la inferencia e incorporar ese aprendizaje en sucesivas ejecuciones.

Para completar los novedades, se presentó Google Coral una placa hardware que permite desplegar modelos usando TensorFlow Lite y toda la potencia de la Edge TPU de Google.

Tensor Flow Coral Board

Aprender sobre TensorFlow y Machine Learning cada vez más fácil con estos cursos

En 2016, Udacity lanzó el primer curso sobre TensorFlow en colaboración con Google. Desde entonces, más de 400.000 estudiantes se han apuntado al curso. Aprovechando el lanzamiento de Tensor Flow 2.0 Alpha, se ha renovado el curso por completo para hacerlo más accesible a cualquier desarrollador sin requerir un profundo conocimiento en matemáticas. Tal como ellos afirman: “Si puedes programar, puedes construir aplicaciones AI con Tensor Flow”

Cursos Tensorflow Udacity Deeplearning

El curso de Udacity está guiado por el equipo de desarrollo de Google, a día de hoy está disponible la formación de los primeros 2 meses de la planificación, pero irán añadiendo más contenido a lo largo de las semanas. En la primera parte podrás aprender los conceptos fundamentales detrás del machine learning y cómo construir tu primera red neuronal usando TensorFlow. Disponen de numerosos ejercicios y codelabs escritos por el propio equipo de Tensor Flow.

También se ha incorporado nuevo material en deeplearning.ai con un curso de introducción a AI, ML y DL, parte del career path de Tensor Flow: from Basics to Mastery series de Coursera. Entre los instructores se encuentra Andrew Ng, uno de los más importantes impulsores del Machine Learning desde sus inicios.

Y otra de las plataformas orientadas a la formación en AI, Fast.ai ha incorporado dos cursos sobre el uso de TensorFlow Lite para desarrolladores móviles y otro sobre el uso de Swift en TensorFlow.

Definitivamente, tenemos muchas oportunidades para empezar a aprender más sobre la revolución del Machine Learning junto a TensorFlow, una de las plataformas end-to-end más completas para este fin.

El ecosistema de TensorFlow para programadores principiantes y expertos en Machine Learning: cursos, lenguajes y Edge Computing

13/03/2019
Artículo original

El ecosistema de TensorFlow para programadores principiantes y expertos en Machine Learning: cursos, lenguajes y Edge Computing

TensorFlow es la apuesta clave de Google para construir el ecosistema del futuro del Machine Learning que pueda ser ejecutado en la nube, en aplicaciones o en dispositivos hardware de todo tipo.

Precisamente, los esfuerzos en su última TensorFlow Dev Summit 2019 han ido enfocados en facilitar y simplificar el uso del framework, incorporando más API tanto para los programadores principiantes como para los más expertos. De este modo, todos podremos aprovecharnos de las nuevas mejoras para crear modelos de aprendizaje más fácilmente para la mayor número de casos de uso y desplegarlos en cualquier dispositivos.

Han impulsado el despliegue de los algoritmos de forma local en dispositivos hardware con la release final de TensorFlow Lite 1.0 sin necesidad de recurrir a la nube u otro sistema centralizado para ser procesados. Un claro ejemplo de que el Edge Computing forma parte de la estrategia clave de Google para dotar a cualquier dispositivo, ya sea IoT o móvil, de todas las ventajas del aprendizaje automático.

En los tres años que han pasado desde su lanzamiento, TensorFlow ha sentando las bases de un ecosistema de Machine Learning end-to-end, ayudando a potenciar la revolución del Deep Learning. Cada vez hay más desarrolladores que hacen uso de algoritmos para implementar nuevas funcionalidades a los usuarios o acelerar tareas hasta ahora tediosas como la clasificación de imágenes, la captura y reconocimiento de documentos o el reconocimiento de voz y la síntesis del lenguaje natural en los asistentes virtuales (Google Assistant o Alexa)

No es extraño que TensorFlow sea el proyecto con mayor número de contribuciones en Github año tras años, con más de 1.800 contribuciones. Acumulando más de 41 millones de descargas en tres años de historia y decenas de ejemplos de uso en distintas plataformas.

Tensorflow

El camino hacia TensorFlow 2.0

TensorFlow ha sentando las bases de un ecosistema de Machine Learning end-to-end, ayudando a potenciar la revolución del Deep Learning

TensorFlow 2.0 Alpha se ha fijado el objetivo de simplificar su uso, ampliando las posibilidades para ser una plataforma de ML más abierta que puede ser utilizada tanto por investigadores que quieran realizar experimentos y estudios, desarrolladores dispuestos a automatizar cualquier clase tarea o empresas que quieran facilitar la experiencia de uso de sus usuarios a través del inteligencia artificial.

Uno de los pilares de TensorFlow 2.0 es la integración más estrecha con Keras como la API de alto nivel para construir y entrenar modelos de Deep Learning. Keras tiene diversas ventajas:

  • Enfocada en el usuario. Keras tiene una interfaz más simple y consistente, adaptada a los casos de uso más comunes. Facilitando un feedback más claro para entender los errores de implementación.
  • Ser más modular y reutilizable. De este modo los modelos de Keras puede componer estructuras más complejas a través de capas y optimizadores sin necesidad de un modelo específico para entrenar.
  • Pensado tanto para principiantes como para expertos. Aprovechando como idea fundamental el background de los diversos tipos de programadores que se están involucrando desde el principio en el desarrollo de Deep Learning. Keras provee una API mucho más clara sin necesidad de ser un experto con años de experiencia.

También se han incorporado una amplia colección de datasets públicos preparados para ser utilizados con TensorFlow. Cualquier desarrollador que se haya aventurado a trabajar en Machine Learning sabe, esto representa el ingrediente principal para crear modelos y entrenar los algoritmos que después emplearemos. Tener esa ingente cantidad de datos ayuda bastante.

Para la migración de TensorFlow 1.x a 2.0 se han creado diversas herramientas para convertir y migrar los modelos. Ya que se han realizado actualizaciones necesarias para que sean más óptimos y pueden ser desplegados en más plataformas.

El ecosistema sigue creciendo con numerosas librerías para crear un entorno de trabajo más seguro y privado. Como el lanzamiento de la librería TensorFlow Federated, cuya intención es descentralizar el proceso de entrenamiento para compartirlo con múltiples participantes que puedan ejecutarlo localmente y envíen los resultados sin exponer necesariamente los datos capturados, sólo compartiendo el aprendizaje obtenido para la generación de los algoritmos. Un claro ejemplo de esto es el aprendizaje automático de los teclados virtuales, como el de GBoard de Google, que no expone datos sensibles, ya que va a aprendiendo localmente en el propio dispositivo.

Federated Tensor Flow Gboard

Al hilo de esto, el equilibrio entre Machine Learning y la privacidad es una tarea compleja, por ello se ha lanzado la librería de TensorFlow Privacy que permite definir distintos escenarios y grados para salvaguardar los datos más sensible y anonimizar la información de entrenamiento de los modelos.

Python no está solo en TensorFlow, más lenguajes como Swift o Javascript se unen a la plataforma

Python sigue siendo una pieza fundamental en el ecosistema Machine Learning y a la vez ha recibido un gran impulso al ser uno de los lenguajes principales

Obviamente, Python sigue siendo una pieza fundamental en el ecosistema Machine Learning y a la vez ha recibido un gran impulso al ser uno de los lenguajes principales con decenas de librerías entre las más utilizadas, a parte de su gran madurez. No sólo en TensorFlow, sino en otras plataformas como PyTorch.

Pero el ecosistema de TensorFlow ha abierto sus puertas incorporando librerías como TensorFlow.js, que finalmente alcanza la versión 1.0 Con más de 300.000 descargas y 100 contribuciones. Permite ejecutar proyectos ML en el navegador o el en backend con Node.js, tanto modelos ya pre entrenados como construir entrenamientos.

Empresas como Uber o Airbnb ya lo están utilizando en entornos de producción. Hay una amplia galería de ejemplos y casos de uso utilizando JavaScript junto a TensorFlow

Tensor Flow Switf

Otra de las grandes novedades es el avance en la implementación de** TensorFlow en Swift** con su versión 0.2. De esta forma incorporan un nuevo lenguaje de propósito general como Swift al paradigma ML con todas las funcionalidades para que los desarrolladores puedan acceder a todos los operadores de TensorFlow. Todo ello construido sobre las bases de Jupyter y LLDB.

Ejecutar localmente nuestros modelos con Tensor Lite: la apuesta por el Edge computing

Edge computing se basa en ejecutar modelos y hacer inferencias directamente en local sin depender de que tengan que ser enviados los datos para ser analizados a la nube.

El objetivo de TensorFlow Lite es impulsar definitivamente el Edge Computing en los millones de dispositivos que a día de hoy son capaces de ejecutar TensorFlow. Es la solución para ejecutar modelos y hacer inferencias directamente sin depender de que tengan que ser enviados los datos para ser analizados a la nube.

En Mayo de 2017 fue presentado en la conferencia de desarrolladores de Google IO con una versión preview. Esta semana ha alcanzado la versión definitiva TensorFlow Lite 1.0. Lo que ayudará a implementar diversos casos de uso como la generación de texto predictivo, la clasificación de imágenes, la detección de objetos, el reconocimiento de audio o la síntesis de voz, entre otros muchos escenarios que se pueden implementar.

Esto permite una mejora de rendimiento considerable debido a la conversión al modelo de TensorFlow Lite que permite la herramienta, como por el aumento de rendimiento para ser ejecutado en las GPU de cada dispositivo, incluyendo Android, por ejemplo.

Con ello, TensorFlow Mobile comienza a ser deprecado, salvo que realmente queramos realizar entrenamientos directamente desde el mismo dispositivo. Ya han confirmado que dentro del roadmap de esta versión Lite están trabajando en esto mismo, desvelaron ciertas funcionalidades interesantes como el aprendizaje acelerado con la asignación de pesos para mejorar la inferencia e incorporar ese aprendizaje en sucesivas ejecuciones.

Para completar los novedades, se presentó Google Coral una placa hardware que permite desplegar modelos usando TensorFlow Lite y toda la potencia de la Edge TPU de Google.

Tensor Flow Coral Board

Aprender sobre TensorFlow y Machine Learning cada vez más fácil con estos cursos

En 2016, Udacity lanzó el primer curso sobre TensorFlow en colaboración con Google. Desde entonces, más de 400.000 estudiantes se han apuntado al curso. Aprovechando el lanzamiento de Tensor Flow 2.0 Alpha, se ha renovado el curso por completo para hacerlo más accesible a cualquier desarrollador sin requerir un profundo conocimiento en matemáticas. Tal como ellos afirman: “Si puedes programar, puedes construir aplicaciones AI con Tensor Flow”

Cursos Tensorflow Udacity Deeplearning

El curso de Udacity está guiado por el equipo de desarrollo de Google, a día de hoy está disponible la formación de los primeros 2 meses de la planificación, pero irán añadiendo más contenido a lo largo de las semanas. En la primera parte podrás aprender los conceptos fundamentales detrás del machine learning y cómo construir tu primera red neuronal usando TensorFlow. Disponen de numerosos ejercicios y codelabs escritos por el propio equipo de Tensor Flow.

También se ha incorporado nuevo material en deeplearning.ai con un curso de introducción a AI, ML y DL, parte del career path de Tensor Flow: from Basics to Mastery series de Coursera. Entre los instructores se encuentra Andrew Ng, uno de los más importantes impulsores del Machine Learning desde sus inicios.

Y otra de las plataformas orientadas a la formación en AI, Fast.ai ha incorporado dos cursos sobre el uso de TensorFlow Lite para desarrolladores móviles y otro sobre el uso de Swift en TensorFlow.

Definitivamente, tenemos muchas oportunidades para empezar a aprender más sobre la revolución del Machine Learning junto a TensorFlow, una de las plataformas end-to-end más completas para este fin.

¿Cómo utilizar las fuentes de Google desde tu propio servidor en vez de desde Google?

13/03/2019
Artículo original

Google Fonts es un recurso maravilloso y gratuito para acceder a decenas o centenares de fuentes tipográficas de manera rápida y con rendimiento, ya que además se sirven desde la CDN de Google.

Sin embargo algunas personas prefieren servir las fuentes desde su propio servidor, sin depender de los servidores de Google.

Recomendación: no se me ocurre un caso en el que sea mejor que sirvas las fuentes desde tu servidor en lugar de desde Google. Con toda seguridad las servirá más rápido Google que tu servidor, y además los usuarios puede que la tengan ya cacheada por haber visitado antes otras páginas que también la usan desde la misma ubicación. Salvo que tengas un buen motivo es mejor no usarlas en local.

A pesar de la advertencia anterior y dado que me lo han preguntado, voy a explicar cómo conseguir "gorronear" esas fuentes y utilizarlas desde tu propio servidor o en local.

¡Allá vamos!

1.- Descarga el CSS desde Google

Imagina que la fuente en la que tienes interés es, por ejemplo, Flavors:

Cómo añadir la fuente Flavors en Google Fonts

El código que debes poner en tu página para usar la fuente desde Google es el siguiente:

<link href='https://fonts.googleapis.com/css?family=Flavors' rel='stylesheet'>

Ahora visita la URL de esa hoja de estilos con el navegador, por ejemplo en nuestro caso esta:

https://fonts.googleapis.com/css?family=Flavors

Esto te mostrará en una pestaña el contenido de ese archivo CSS. Cópialo, por ejemplo, a una subcarpeta CSS de la carpeta en la que está tu página y llámale por ejemplo Flavors-Fuente.css.

2.- Obtén el archivo de la fuente

Abre el CSS que acabas de guardar a disco con un editor cualquiera (el mismo bloc de notas te vale). Verás que tiene un simple estilo dentro, este:

@font-face {
font-family: 'Flavors';
font-style: normal;
font-weight: 400;
src: local('Flavors'), local('Flavors-Regular'), url(https://fonts.gstatic.com/s/flavors/v7/FBV2dDrhxqmveJTpXkvvNw.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

Fíjate en la propiedad src del final. La ubicación de la fuente se indica con url y es, en este caso:

https://fonts.gstatic.com/s/flavors/v7/FBV2dDrhxqmveJTpXkvvNw.woff2

Vete al navegador y escribe esta dirección. Te descargarás la fuente (en formato Woff2 en este caso). Cópiala a una subcarpeta dentro de la carpeta CSS, por ejemplo fuentes y llámale al archivo: "Flavors.woff2".

3.- Cambia la fuente de Google por la "local"

Ahora abre el archivo .css que copiaste y cambia la ruta de la fuente en los servidores de Google por la ruta relativa a la fuente que acabas de copiar. El CSS te quedaría así:

@font-face {
font-family: 'Flavors';
font-style: normal;
font-weight: 400;
src: local('Flavors'), local('Flavors-Regular'), url(css/fuentes/Flavors.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

4.- Sustituye el CSS en la página Web para que apunte al tuyo "local":

Ahora abre la página .html en la que quieres usar esta fuente y simplemente apunta al archivo .css anterior en lugar de al de Google, así:

<link href='CSS/Flavors-Fuente.css' rel='stylesheet'>

¡Listo!

A partir de ese momento la fuente se servirá desde tu servidor Web y no desde los de Google, como buscabas.

IMPORTANTE: para que esto funcione bien en un servidor Web real, tu servidor Web tiene que poder servir correctamente los archivos de tipo .woff2. Si no se descarga es porque le falta configurar el tipo MIME adecuado para este tipo de archivos, que es "application/font-woff". Si no sabes de qué te hablo no te preocupes: habla con el administrador de tu servidor o del hosting que utilices si es que lo necesitas cambiar.  En general no deberías tener problema. Recuerda la recomendación del principio: generalmente, mucho mejor servir desde Google Fonts directamente.

¡Espero que te resulte útil!

La Evolución del lenguaje C#

11/03/2019
Artículo original

Este artículo es una traducción de "The Evolution of C#" originalmente escrito por el MVP de Microsoft, Damir Arh en DotNetCurry. Este artículo fue traducido con el permiso expreso del autor, de DotNetCurry y de la revista DNC, que es una revista gratuita para desarrolladores .NET y JavaScript (en inglés).

Aunque ya han pasado más de 15 años desde el lanzamiento de la primera versión de C#, el lenguaje no parece muy antiguo. Una de las razones es que ha sido actualizado con regularidad.

Cada dos o tres años, se lanzaba una nueva versión con nuevas funcionalidades en el lenguaje. Desde la aparición de C# 7.0 a principios de 2017, la cadencia de actualizaciones ha aumentado todavía más mediante versiones menores del lenguaje.

En el plazo de un año, se publicaron tres nuevas versiones menores (C# 7.1, 7.2 y 7.3).

Lea más en C# 7.1, 7.2 y 7.3 - Nuevas funcionalidades (Actualizado) (en inglés).

Si nos fijásemos en código escrito con C# 1.0 en 2002, se vería muy distinto al código que utilizamos hoy en día.

La mayor parte de las diferencias son el resultado de la utilización de construcciones del lenguaje que no existían en aquel entonces. Sin embargo, junto con el desarrollo del lenguaje, también se añadieron nuevas clases a la plataforma .NET que se benefician de las nuevas capacidades del lenguaje. Todo esto hace que el C# de ahora sea mucho más expresivo y conciso.

Llevemos a cabo una incursión histórica haciendo un repaso de las principales versiones de C#.

Para cada versión, analizaremos los cambios más importantes y compararemos el código que podría ser programado después de su lanzamiento, con el que se tenía que crear antes. Cuando lleguemos a C# 1.0, difícilmente seremos capaces de reconocer el código como C#.

Versiones y Evolución de C#

Imagen ornamental

C# 7.0

En el momento en el que se escribió este artículo, la última versión principal era la 7.0. Su lanzamiento fue en 2017, que sigue siendo bastante reciente, y por lo tanto sus nuevas funcionalidades aún no se utilizan a menudo.

La mayoría de nosotros todavía estamos muy habituados a programar en C# sin aprovechar su potencia ni todas las ventajas que nos ofrece.

La característica principal de C# 7.0 era la búsqueda de patrones que añadía soporte en la comprobación de tipos en sentencias switch:

switch (weapon)
{
    case Sword sword when sword.Durability > 0:
        enemy.Health -= sword.Damage;
        sword.Durability--;
        break;
    case Bow bow when bow.Arrows > 0:
        enemy.Health -= bow.Damage;
        bow.Arrows--;
        break;
}

Hay múltiples nuevas funcionalidades del lenguaje utilizadas en el compacto fragmento de código anterior:

  • Las instrucciones case comprueban el tipo de valor de la variable weapon.
  • En la misma instrucción, declaro una nueva variable del tipo coincidente que se puede utilizar en el bloque de código correspondiente.
  • La última parte de la instrucción después de la palabra clave when especifica una condición adicional para restringir aún más la ejecución del código.

Por otra parte, el operador is se amplió con soporte para hacer también búsqueda de patrones, por lo que ahora se puede utilizar para declarar una nueva variable similar a las instrucciones case:

if (weapon is Sword sword)
{
    // código con la nueva variable de ámbito "sword"
}

En las versiones anteriores del lenguaje sin todas estas funcionalidades, el bloque de código equivalente hubiese sido mucho más largo:

if (weapon is Sword)
{
    var sword = weapon as Sword;
    if (sword.Durability > 0)
    {
        enemy.Health -= sword.Damage;
        sword.Durability--;
    }
}
else if (weapon is Bow)
{
    var bow = weapon as Bow;
    if (bow.Arrows > 0)
    {
        enemy.Health -= bow.Damage;
        bow.Arrows--;
    }
}

En C# 7.0 se añadieron también otras funcionalidades menores:

(i) Las variables out

Que permiten la declaración de variables en el lugar donde se usan por primera vez como argumentos de un método.

if (dictionary.TryGetValue(key, out var value))
{
    return value;
}
else
{
    return null;
}

Antes de que se añadiese esta característica, teníamos que declarar la variable de valor por anticipado:

string value;

if (dictionary.TryGetValue(key, out value))
{
    return value;
}
else
{
    return null;
}

(ii) Tuplas

Se pueden utilizar tuplas para agrupar múltiples variables en un único valor sobre la marcha, según sea necesario, por ejemplo, para los valores de retorno de los métodos:

public (int weight, int count) Stocktake(IEnumerable<IWeapon> weapons)
{
    return (weapons.Sum(weapon => weapon.Weight), weapons.Count());
}

Sin ellas teníamos que declarar un nuevo tipo para hacerlo, incluso si sólo lo necesitábamos en un único sitio:

public Inventory Stocktake(IEnumerable<IWeapon> weapons)
{
    return new Inventory
    {
        Weight = weapons.Sum(weapon => weapon.Weight),
        Count = weapons.Count()
    };
}

Para saber más sobre las nuevas características de C# 7.0, consulta mi artículo C# 7 - ¿Qué hay de nuevo? (en inglés) de una edición anterior de la revista DNC. Para saber más sobre las ediciones menores de C# 7, consulta mi artículo C# 7.1, 7.2 y 7.3 - Novedades (Actualizado) (en inglés) en la revista DNC.

C# 6.0

C# 6.0 fue lanzado en 2015. Coincidió con la completa reprogramación del compilador, denominado Roslyn. Una parte importante de esta versión fueron los servicios de compilación que desde entonces se han utilizado con gran éxito en Visual Studio y otros editores:

  • Visual Studio 2015 y 2017 lo utilizan para el resaltado de sintaxis, navegación por el código, refactorización y otras funciones de edición de código.
  • Muchos otros editores, como Visual Studio Code, Sublime Text, Emacs y otros, proporcionan funcionalidades similares con la ayuda de OmniSharp, un conjunto independiente de herramientas para C# diseñado para integrarse en los editores de código.
  • Muchos analizadores de código estáticos de terceros utilizan los servicios del lenguaje como base. Éstos pueden ser usados dentro de Visual Studio, pero también en el proceso de compilación.

Para obtener más información sobre Roslyn y los servicios de compilador, consulta mi artículo Plataforma de compilador .NET (a.k.a. Roslyn) - Una visión general (en inglés) en la revista DotNetCurry (DNC).

Solamente hubo unos pocos cambios en el lenguaje. Eran en su mayoría azúcar sintáctico, pero muchos de ellos siguen siendo lo suficientemente provechosos como para ser utilizados hoy en día:

Inicializador de diccionarios

Un inicializador de diccionario se puede utilizar para establecer el valor inicial de un diccionario:

var dictionary = new Dictionary<int, string>
{
    [1] = "One",
    [2] = "Two",
    [3] = "Three",
    [4] = "Four",
    [5] = "Five"
};

Sin él, tenías que utilizar en su lugar un inicializador de colecciones:

var dictionary = new Dictionary<int,string>()
{
    { 1, "One" },
    { 2, "Two" },
    { 3, "Three" },
    { 4, "Four" },
    { 5, "Five" }
}

Operador nameof

El operador 'nameof' devuelve el nombre de un símbolo:

public void Method(string input)
{
    if (input == null)
    {
        throw new ArgumentNullException(nameof(input));
    }
    // Implementación del método
}

Es ideal para evitar el uso de cadenas de texto en código que fácilmente pueden desincronizarse cuando se renombran los símbolos:

public void Method(string input)
{
    if (input == null)
    {
        throw new ArgumentNullException("input");
    }
    // Implementación del método
}

Operador de condición de nulo

El operador de condición null reduce el proceso de comprobación de los valores nulos:

var length = input?.Length ?? 0;

No solo se necesita más código para conseguir lo mismo sin él, sino que es mucho más probable que nos olvidemos de añadir esa comprobación:

int length;
if (input == null)
{
    length =0;
}
else
{
    length = input.Length;
}

Importación estática

La importación estática permite la invocación directa de métodos estáticos:

using static System.Math;
var sqrt = Sqrt(input);

Antes de su implantación, era necesario hacer referencia siempre a su clase estática:

var sqrt = Math.Sqrt(input);

La interpolación de cadenas de texto

La interpolación de cadenas simplificó el formateado de las mismas:

var output = $"Length of '{input}' is {input.Length} characters.";

No sólo evita la llamada a String.format, sino que también facilita la lectura del patrón de formato:

var output = String.Format("Length of '{0}' is {1} characters.", input, input.Length);

Por no hablar de que tener argumentos del patrón de formato fuera del patrón hace que sea más probable que se enumeren en el orden equivocado.

Para saber más sobre C# 6, puedes leer mi artículo Actualizando el actual Código C# a C# 6.0 (en inglés) en la revista DotNetCurry (DNC).

C# 5.0

Microsoft lanzó C# 5.0 en 2012 e introdujo una nueva función de lenguaje muy importante: la sintaxis async/await para llamadas asíncronas.

Hizo que la programación asíncrona fuera mucho más accesible para todos. La funcionalidad iba acompañada de un amplio conjunto de nuevos métodos asíncronos para operaciones de entrada y salida en el framework .NET 4.5, que se lanzó al mismo tiempo.

Con la nueva sintaxis, el código asíncrono se parecía mucho al código sincrónico:

public async Task<int> CountWords(string filename)
{
    using (var reader = new StreamReader(filename))
    {
        var text = await reader.ReadToEndAsync();
        return text.Split(' ').Length;
    }
}

En caso de que no estés familiarizado con las palabras clave async y await, ten en cuenta que la llamada de I/O al método ReadToEndAsync no tiene bloqueos. La palabra clave await libera el hilo para otros usos hasta que el fichero leído se complete de forma asíncrona. Es entonces cuando la ejecución continúa de nuevo en el mismo hilo (la mayoría de las veces).

Para saber más sobre async/await, consulta mi artículo Programación asíncrona en C# usando Async Await - Buenas prácticas (en inglés) en la revista DotNetCurry (DNC).

Sin la sintaxis async/await, el mismo código sería mucho más difícil de escribir y de entender:

public Task<int> CountWords(string filename)
{
    var reader = new StreamReader(filename);
    return reader.ReadToEndAsync()
        .ContinueWith(task =>
        {
            reader.Close();
            return task.Result.Split(' ').Length;
        });
}

Nótese cómo debo componer manualmente la continuación de la tarea usando el método Task.ContinueWith.

Tampoco puedo utilizar la instrucción using para cerrar el flujo porque sin la palabra clave await para pausar la ejecución del método, el flujo podía cerrarse antes de que la lectura asíncrona se completase.

E incluso este código está usando el método ReadToEndAsync añadido al framework .NET cuando se liberó C# 5.0. Anteriormente, sólo se disponía de una versión síncrona del método. Para liberar el hilo de llamada durante su duración, tenía que estar envuelto en una tarea, (Task):

public Task<int> CountWords(string filename)
{
    return Task.Run(() =>
    {
        using (var reader = new StreamReader(filename))
        {
            return reader.ReadToEnd().Split(' ').Length;
        }
    });
}

Aunque esto permitió que el hilo de llamada (normalmente el hilo principal o el hilo de interfaz de usuario) realizase otra tarea durante la operación de E/S (Entrada/Salida), otro hilo del conjunto de hilos todavía estaba bloqueado durante ese tiempo. Este código sólo tiene apariencia de asíncrono, pero sigue siendo sincrónico en su núcleo.

Para realizar operaciones de E/S asíncronas reales es necesario utilizar una API mucho más antigua y básica en la clase FileStream:

public Task<int> CountWords(string filename)
{
    var fileInfo = new FileInfo(filename);
 
    var stream = new FileStream(filename, FileMode.Open);
    var buffer = new byte[fileInfo.Length];
    return Task.Factory.FromAsync(stream.BeginRead, stream.EndRead, buffer, 0, buffer.Length, null)
        .ContinueWith(_ =>
        {
            stream.Close();
            return Encoding.UTF8.GetString(buffer).Split(' ').Length;
        });
}

Sólo había un único método asíncrono disponible para la lectura de archivos y sólo nos permitía leer los bytes de un archivo en pequeños trozos, por lo tanto, nosotros mismos estamos decodificando el texto.

Además, el código anterior lee todo el archivo a la vez, lo que no escala bien cuando se trata de archivos grandes. Y seguimos utilizando el método de ayuda FromAsync, que sólo se introdujo en el framework 4 de .NET junto con la propia clase Task. Anteriormente nos teníamos que conformar con usar el patrón del modelo de programación asíncrono (APM) directamente en todas las partes de nuestro código, teniendo que llamar a la pareja de métodos BeginOperation y EndOperation para cada operación asíncrona.

No es de extrañar que las I/Os asíncronas raramente se utilizaran antes de C# 5.0.

C# 4.0

En 2010, se lanzó C# 4.0.

Se enfocó en el enlace dinámico para simplificar la interoperabilidad con COM y los lenguajes dinámicos. Dado que Microsoft Office y muchas otras aplicaciones de gran tamaño pueden ahora ampliarse utilizando la plataforma .NET directamente sin depender de la interoperabilidad COM, vemos poco uso del enlace dinámico en la mayoría del código C# en la actualidad.

Para obtener más información sobre enlaces dinámicos, consulta mi artículo Enlace dinámico en C# (en inglés) en la revista DNC.

No obstante, al mismo tiempo se añadió una funcionalidad importante, que se convirtió en parte esencial del lenguaje y que hoy en día se utiliza con mucha frecuencia sin que se le dé demasiada importancia: los parámetros opcionales y con nombre. Son una gran alternativa a la programación de muchas sobrecargas de la misma función:

public void Write(string text, bool centered = false, bool bold = false)
{
    // output text
}

Este único método puede ser llamado proporcionándole cualquier combinación de parámetros opcionales:

Write("Sample text");
Write("Sample text", true);
Write("Sample text", false, true);
Write("Sample text", bold: true);

Antes de C# 4.0, para lograr este resultado teníamos que escribir tres sobrecargas diferentes:

public void Write(string text, bool centered, bool bold)
{
    // output text
}
 
public void Write(string text, bool centered)
{
    Write(text, centered, false);
}
 
public void Write(string text)
{
    Write(text, false);
}

Y aún así, este código sólo es compatible con las tres primeras llamadas del ejemplo original. Sin los parámetros nombrados, tendríamos que crear un método adicional con un nombre diferente para soportar la última combinación de parámetros, es decir, para especificar sólo los parámetros de texto y negrita, pero manteniendo el valor por defecto para el parámetro centered:

public void WriteBold(string text, bool bold)
{
    Write(text, false, bold);
}

C# 3.0

C# 3.0 del año 2007 fue otro hito importante en el desarrollo del lenguaje. Las funcionalidades introducidas giran en torno a la posibilidad de utilizar LINQ (Language INtegrated Query):

  • Los métodos de extensión aparentan ser llamados como miembros de un tipo aunque estén definidos en otra parte.
  • Las expresiones lambda proporcionan una sintaxis más corta para los métodos anónimos.
  • Los tipos anónimos son tipos ad-hoc que no tienen que ser definidos de antemano.

Todo lo anterior nos ha llevado al método de sintaxis LINQ al que todos estamos tan acostumbrados hoy en día:

var minors = persons.Where(person => person.Age < 18)
.Select(person => new { person.Name, person.Age })
.ToList();

Antes de C# 3.0, no había manera de escribir dicho código declarativo en C#. La funcionalidad tenía que ser codificada imperativamente:

List<NameAndAge> minors = new List<NameAndAge>();
foreach(Person person in persons)
{
    if (person.Age > 18)
    {
        minors.Add(new NameAndAge(person.Name, person.Age));
    }
}

Obsérvese cómo usé el tipo completo para declarar la variable en la primera línea de código. La palabra clave var que la mayoría de nosotros usamos todo el tiempo también fue introducida en C# 3.0. Aunque este código no parece mucho más largo que la versión LINQ, hay que tener en cuenta que todavía tenemos que definir el tipo NameAndAge:

public class NameAndAge
{
    private string name;
    public string Name
    {
        get
        {
            return name;
        }
        set
        {
            name = value;
        }
    }
 
    private int age;
    public int Age
    {
        get
        {
            return age;
        }
        set
        {
            age = value;
        }
    }
 
    public NameAndAge(string name, int age)
    {
        Name = name;
        Age = age;
    }
}

El código de clase es mucho más largo de lo que estamos acostumbrados debido a otras dos funciones que fueron añadidas en C# 3.0:

  • Sin las propiedades auto-implementadas debo declarar manualmente los campos de respaldo, así como los getters y setters triviales para cada propiedad.
  • El constructor para establecer los valores de las propiedades es necesario porque no había sintaxis del inicializador antes de C# 3.0.

C# 2.0

Hemos llegado al año 2005 cuando se lanzó C# 2.0. Muchos consideran que esta es la primera versión del lenguaje lo suficientemente madura para ser utilizada en proyectos reales. Introdujo muchas funcionalidades de las que no podemos prescindir hoy en día, aunque la más importante e impactante de todas fue, sin duda, el soporte de los genéricos.

Nadie se puede imaginar C# sin genéricos. Todas las colecciones que seguimos utilizando hoy en día son genéricas:

List<int> numbers = new List<int>();
numbers.Add(1);
numbers.Add(2);
numbers.Add(3);
 
int sum = 0;
for (int i = 0; i < numbers.Count; i++)
{
    sum += numbers[i];
}

Sin genéricos, no había colecciones fuertemente tipadas en el framework .NET. En lugar del código de arriba, nos teníamos que conformar con lo siguiente:

ArrayList numbers = new ArrayList();
numbers.Add(1);
numbers.Add(2);
numbers.Add(3);
 
int sum = 0;
for (int i = 0; i < numbers.Count; i++)
{
    sum += (int)numbers[i];
}

Aunque el código puede parecer similar, hay una diferencia importante: este código no es de tipado seguro. Fácilmente podría añadir valores de otros tipos a la colección, no sólo int. Además, fíjate cómo convierto el valor que obtengo de la colección antes de usarla. Debo hacerlo porque está tipado como objeto dentro de la colección.

Por supuesto, este código es muy propenso a contener errores. Afortunadamente, había otra solución disponible si quería tener tipado seguro. Podría crear mi propia colección tipada:

public class IntList : CollectionBase
{
    public int this[int index]
    {
        get
        {
            return (int)List[index];
        }
        set
        {
            List[index] = value;
        }
    }
 
    public int Add(int value)
    {
        return List.Add(value);
    }
 
    public int IndexOf(int value)
    {
        return List.IndexOf(value);
    }
 
    public void Insert(int index, int value)
    {
        List.Insert(index, value);
    }
 
    public void Remove(int value)
    {
        List.Remove(value);
    }
 
    public bool Contains(int value)
    {
        return List.Contains(value);
    }
 
    protected override void OnValidate(Object value)
    {
        if (value.GetType() != typeof(System.Int32))
        {
            throw new ArgumentException("Value must be of type Int32.", "value");
        }
    }
}

El código que lo usa seguiría siendo similar, pero al menos sería de tipado seguro, tal y como estamos acostumbrados con los genéricos:

IntList numbers = new IntList();
numbers.Add(1);
numbers.Add(2);
numbers.Add(3);
 
int sum = 0;
for (int i = 0; i < numbers.Count; i++)
{
    sum += numbers[i];
}

Sin embargo, la colección IntList sólo se puede utilizar para almacenar int. Debo implementar una colección de tipado fuerte diferente si quiero almacenar valores de un tipo diferente, repitiendo código de manera absurda.

Y el código resultante sigue siendo significativamente menos eficaz para los tipos de valor porque se debe hacer un boxing de los valores antes de ser almacenados en la colección y se debe hacer un unboxing cuando se necesitan.

Hay muchas otras funcionalidades sin las que no podemos vivir hoy en día y que no fueron implementadas antes de C# 2.0:

  • Tipos anulables
  • Iteradores
  • Métodos anónimos
  • ...

Conclusión

C# ha sido el lenguaje principal para el desarrollo en .NET desde la versión 1.0, pero ha evolucionado mucho desde entonces. Gracias a las funcionalidades que se le fueron añadiendo versión tras versión, se mantiene al día con las nuevas tendencias del mundo de la programación y sigue siendo una buena alternativa a los nuevos lenguajes que han aparecido desde entonces.

Ocasionalmente, incluso logra iniciar una nueva tendencia como lo hizo con las palabras clave async y await, que más tarde han sido adoptadas por otros lenguajes. Con soporte para tipos de referencia anulables y muchas otras nuevas funciones anunciadas para C# 8.0, no hay que temer que el lenguaje deje de evolucionar.

Si estás interesado en conocer las próximas características de C# 8, consulta este post (en inglés).

Este artículo ha sido revisado técnicament por Yacoub Massad.

Así es 'Low Code Platform', una herramienta que permite crear apps de comercio electrónico o banca sin saber programar

08/03/2019
Artículo original

Así es 'Low Code Platform', una herramienta que permite crear apps de comercio electrónico o banca sin saber programar

El Mobile World Congress 2019 nos ha dejado muchas grandes novedades en telefonía. Hemos podido conocer los primeros smartphones plegables de dos grandes marcas como Samsung y Huawei, junto a otros modelos que, este año sí, estrenan la capacidad de conectarse a redes 5G. A ello se han sumado, como cada año, novedades en coche conectado, wearables e incluso areneros inteligentes para gatos.

Pero el Mobile también es mucho software que, aunque no tengamos apenas tiempo de probar, está y muchas veces deja anuncios y novedades muy interesantes. En nuestro caso, hemos conocido Low Code Platform de la mano de VeriTran, una plataforma que nos resulta muy interesante por cómo ayuda a empresas crear aplicaciones para iOS y Android sin necesidad de programar.

Qué ofrece Low Code Platform

VeriTran es una compañía argentina centrada en el desarrollo de aplicaciones y soluciones para la banca y el sector financiero desde hace más de 14 años, para el que llegó a crear aplicaciones antes de la llegada de los smartphones modernos. Presumen de haber liderado la transformación digital en Latinoamérica y de haber implementado sus soluciones en más de 40 entidades, entre las que se encuentran el BBVA, BancoEstado, Banorte o BancoCiudad. Con todas ellas dan servicio a 12 millones de usuarios bancarios que realizan 6.000 millones de transacciones anualmente.

Ahora mismo está muy centrada en la transformación digital y los pagos móviles, por lo que tienen alianzas con actores como Visa, Mastercard, Samsung o Microsoft. Lo que más nos interesó de su oferta fue la Low Code Platform, que sin escribir una sola línea de código permite crear de cero aplicaciones con el modelo de "arrastrar y soltar" que tan de moda se está poniendo.

VeriTran ofrece un servicio que permite integrar funciones muy específicas y solicitadas de banca, comercio o seguros en una aplicación creada en pocos pasos.

A diferencia de otras ocasiones en las que hemos hablado de otras plataformas que permiten crear aplicaciones y webs desde cero, la de VeriTran no está enfocada a aprender o a que buenas ideas salgan adelante sin saber de programación. Low Code Platform está enfocada a que empresas que quieran construir aplicaciones sólidas de banca y otros sectores puedan hacerlo.

En ese sentido, la compañía piensa que es una pérdida de tiempo y recursos tener que empezar de cero y volver a escribir el código de partes de las aplicaciones que suelen ser prácticamente calcadas unas de otras, como la pantalla de identificación, la integración de la seguridad y la biometría, el manejo de las bases de datos, notificaciones, etc.

Para evitar tener que pasar por la creación de todo eso, Marcelo González, CEO de VeriTran, nos comentaba en el MWC que "han creado app templates, que son como unas plantillas que ofrecen toda la funcionalidad que se necesita al crear una aplicación de banca, comercio electrónico, seguros médicos, etc. ¿Cuántas veces se ha programado la pantalla de log-in? ¿Las notificaciones push? ¿La geolocalización?"

"Nosotros, como muchas compañías, tenemos todo eso hecho, pero lo que ofrecemos es que se puedan crear aplicaciones potentísimas con las manos, arrastrando y pegando como crearías una presentación de PowerPoint", recalcó Marcelo González. Eso sí, como decíamos, está "más pensado para personas con experiencia de usuario, que para desarrolladores".

Nos quedaba la duda de si el sistema permite que un desarrollador incluya código propio, y la respuesta es que sí. Aunque las plantillas cubran la mayoría de casos, se puede programar lo que específicamente se pretenda que haga una parte diferenciada. Es decir, pese al modelo prefabricado, hay lugar para la flexibilidad. Según nos contaron los responsables, integrar bases de datos de clientes ya existentes e incluso de tarjetas de crédito y cuentas es algo que está soportado, e incluso han hecho con grandes bancos.

Marketplace Estas son algunas de las funciones que se pueden añadir en una aplicación de banca.

Con un solo diseño de plantilla, el sistema genera aplicaciones de iOS y Android, y "eventualmente web". Ante la sospecha de que las aplicaciones que se creasen fueran híbridas o basadas en HTML5, el CEO de la compañía nos respondió que no, utilizan código nativo, y pueden "funcionar 100% offline".

El proceso de publicación se puede hacer desde la plataforma o de la forma tradicional en cada una de las dos plataformas, publicando el paquete. Otro detalle del que presumen es que "el usuario puede recibir novedades en las aplicaciones sin necesidad de recurrir a actualizaciones en las tiendas". Con tan sólo modificarlas en la plataforma, los usuarios pueden ver los nuevos cambios.

La monetización

Coste

¿Cómo se monetiza? A diferencia de plataformas de aprendizaje de aplicaciones más sencillas, la de VeriTran está pensada para empresas, por lo que su monetización no funciona con publicidad, sino con un pago por número de usuarios.

Inicialmente se pagan 250 dólares mensuales para una masa de 100 usuarios. Es decir, 2,5 dólares por usuario. Sin embargo, a medida que se añaden más usuarios al servicio de cada empresa, el coste por usuario es decreciende, va bajando. Si la actividad de la aplicación pasa de 250.000 usuarios, VeriTran ofrece planes específicos para las empresas.

Página Siguiente