El ciclo de DevOps, una guía para iniciarse en las fases que lo componen

14/05/2018
Artículo original

Devops Loop Illustrations

Hay términos que están de moda, tienen mucha capacidad de empoderamiento, y producen movimientos innovadores en las empresas. Sobre todo, las dedicadas a negocios relacionados con la economía digital.

Uno de ellos es, junto con microservicios, Agile, o transformación digital, el término DevOps.

Este es un concepto, cuasi una filosofía, del cual en este artículo voy a centrarme en la descripción de las fases del ciclo iterativo que lo componen; con el objetivo de aclarar conceptos básicos que debo tener interiorizados antes de emprender su adopción.

Fases en DevOps

Traffic Lights 2147790 960 720

En la actualidad, DevOps se puede definir como un símbolo de infinito o un circulo que define las diferentes áreas y fases que lo componen:

  • Plan
  • Desarrollo
  • Integración continua
  • Despliegue
  • Operación
  • Monitorización

Es importante comprender que es una de las múltiples representaciones, no el canon definitivo. Habiendo simplificaciones totalmente válidas en forma de cuatro fases principales, o descomposiciones detalladas de cada una de ellas.

Otra idea imprescindible de interiorizar es que se trata de la definición de un flujo iterativo, por lo cual diferentes procesos pueden estar comprendidos en diferentes fases de forma orgánica y superpuesta, siempre ajustándose a los conceptos fundamentales de valor y mejora continua.

Debo evitar caer en la tentación de considerarlo como un ciclo en cascada, en donde las fases están delimitadas rígidamente por una frontera que las separa, o que solamente se puede iniciar una fase cuando la anterior ha finalizado del todo.

Ahora, voy a mirar con más detalle cada fase, permitiéndome una licencia muy habitual en los procesos DevOps, que es utilizar el framework Scrum (y sus arquetipos) como metodología de trabajo para hacer más sencillas las explicaciones.

Gestión y planificación

Stratgia Proceso De Planificacion Estrategica

Todo proyecto necesita una visión que indique a los participantes -sean directos o indirectos- el motivo y fin último del trabajo a realizar; definiendo un conjunto mínimo de funcionalidades que permitan aportar Valor en cada iteración, los criterios de aceptación a cumplir y la definición de acabado; para cada una de las fases y en el conjunto del proyecto.

Esto se constituye como una Pila de Producto viva, que está soportando continuadamente un proceso de “jardinería”, desde un punto de vista de negocio, la cual alimenta a las diferentes fases de desarrollo y operaciones; y que aborda los cambios y evoluciones según un proceso de mejora continua basado en un feedback temprano y continuado.

Para ello utilizare las “liturgias” de Scrum, como son las reuniones de Planificación de la iteración y la Revisión de la iteración; pero sin, por ello, dejar de tener una comunicación e implicación constante entre negocio y el equipo técnico. Siendo imprescindible que Negocio y Gestión se formen en las herramientas y métricas diseñadas para que tengan una visibilidad veraz y suficiente del desarrollo del proyecto.

Desarrollo, construyendo código

Mr Burns Monkeys Typewriters1

Esta fase es en donde se construye. Sea picando código, diseñando infraestructura, automatizando procesos, definiendo las pruebas o implantando la seguridad.

Es en donde, en la actualidad, se está realizando el esfuerzo más importante en la automatización de las acciones repetitivas o complejas; y que debiera ser uno de los primeros peldaños que escalar para implantar DevOps en una organización.

Si tuviera que resumir en una sola palabra el concepto más importante de esta fase, esta sería “pruebas.

Ya sea en una aplicación de gestión, operaciones con datos o el despliegue de infraestructura virtual; siempre voy a trabajar en código – ya sea con un lenguaje de programación o de scripting; el cual debe ser almacenado en un gestor de código que me permita operaciones básicas como históricos, ramas, versionado, etc.

Pero con esto no es suficiente y cada pieza construida debe incluir (obligatoriamente) sus propias pruebas automatizadas. Es decir, los mecanismos con los que el propio sistema pueda asegurarse de que lo que hemos realizado es correcto, no falla, no hace fallar a otras partes, cumple los criterios de aceptación, y señala de forma temprana los errores que surgen en todo desarrollo.

De hecho, este es un camino imperativo para adoptar Devops, desde sus más incipientes estadios.

Primero almaceno el código/script en un gestor para poder tener versionado y poder hacer rollback; luego empezar a incluir las pruebas automatizadas, lo cual va a producir una transformación profunda en las técnicas de codificación (desacoplamiento, segregación, modularización, etc); por último, se llega a la orientación de lo construido hacía las fases siguientes, incluyendo la transformación del propio flujo de trabajo.

Integración continua, o cómo dormir tranquilo

Sleeping Baby 1

Aunque en esta fase y la anterior la mayoría de los autores nos centramos en un punto de vista de desarrollo, realmente la llegada de DevOps y los conceptos de Infraestructura como código, hacen que IT también sea pleno participante de esta fase.

La integración continua es automatizar el mecanismo de revisión, validación, prueba y alertas del valor construido en las iteraciones, desde un punto de vista global.

Es decir, mi singular funcionalidad o característica, que he construido en mi entorno de desarrollo, junto con las pruebas automáticas que aseguran su correcto funcionamiento, son publicadas en un servicio que la integra con el resto de la aplicación.

Así, lanzando todas las pruebas que incluye cada funcionalidad, más las pruebas de integración de toda la aplicación, más las pruebas funcionales, más las pruebas de aceptación, más los análisis de calidad del código, más las pruebas de regresión, podré estar seguro de que mi aplicación sigue funcionando correctamente.

Y si algo falla, saltará la alerta temprana indicando en qué pieza y en qué línea está rompiendo mi sistema.

Así que, cuanto más me acerque al momento de iniciar el camino crítico del despliegue, más tranquilo estaré porque más pruebas incluyen mi trabajo.

Despliegue automatizado

Gns60gr

Desplegar, en las organizaciones clásicas, siempre ha sido un dolor. Dos roles (Dev e IT) con objetivos e intereses divergentes se encuentran en una batalla de incomunicación y recelo mutuo para publicar la aplicación en los diferentes entornos de trabajo: desarrollo, integración, calidad/test, preproducción, producción, etc.

Como en toda cadena, es fácil romper por el eslabón más débil, y cuantos más pasos existan en los procesos de despliegue, más posibilidades de fallo humano se suman.

Así, DevOps promueve la automatización de los despliegues por medio de herramientas y scripts, con el objetivo último de que todo el proceso se resuelva con un botón de aprobación o, idealmente, la activación de una característica.

Entre cada entorno de despliegue, hay que tener muy en cuenta la administración del contexto (crear, configurar y destruir entornos); realizar y superar las pruebas específicas de cada uno (como pueden ser pruebas de rendimiento, resiliencia, funcionales, de seguridad o de UX); y administrar la gestión de la configuración (CMDB) de acuerdo con las complejas necesidades de los diferentes contextos de despliegue.

Lo más crítico y dificultoso en esta fase, más que conocida y adoptada en el entorno IT, es la llegada del concepto Cloud con sus capacidades de Infraestructura como código, que fuerza un cambio en el paradigma de la gestión de la infraestructura. Que pasa de una gestión de recursos finitos a una gestión basada en una optimización permanente de costes.

Operaciones, velando por el buen funcionamiento

Istock 000026445143small 0

Es una minoría las aplicaciones que son puestas en producción y no requieren de un trabajo constante en su optimización, evolución, o soporte. Pero, además, debo tener en cuenta todas las operaciones relacionadas con su funcionamiento que deben realizarse de forma continuada durante toda la vida del software.

Así tendré, el ajuste de los recursos de acuerdo con la demanda o las características de crecimiento de las aplicaciones; la modificación dinámica de la infraestructura por causas de seguridad, rendimiento, disponibilidad, etc.; o la optimización de procesos y procedimientos que requieren cambios en el contexto de ejecución y explotación.

En esta fase, aplicará como anillo al dedo la adopción del concepto de Nube – sea pública, privada o hibrida- en dónde las operaciones puedan explotar las capacidades de escalabilidad, persistencia, disponibilidad, transformación, resiliencia y seguridad que ofrecen este tipo de plataformas.

Debiendo trabajar en la automatización de la optimización de los escenarios de operaciones, de forma que vuelvo a mitigar los fallos a causa de error humano.

Monitorización, o el arte de medir

Measurement

Esta última fase de un proceso DevOps, es una fase permanente y que se aplica a todo el ciclo completo.

Es dónde voy a definir las medidas que estaré monitorizando para controlar el estado de salud de las aplicaciones y su infraestructura, siendo esto el histórico de las mediciones durante un periodo de tiempo, que me muestran la evolución del sistema.

Tiene una vertiente reactiva, en donde de acuerdo con los resultados iré ajustando o modificando la plataforma; y otra proactiva en la cual un proceso de aprendizaje continuo me va a permitir adelantarme a las necesidades y riesgos.

Lo que no se define no se puede medir. Lo que no se mide, no se puede mejorar. Lo que no se mejora, se degrada siempre. William Thomson.

Pero no todo es tecnología, y en esta fase se va a consolidar el feedback continuo de todos los ámbitos y niveles del ciclo Devops para poder incluirlos en la siguiente iteración durante la fase de Plan, o de forma inmediata con correcciones puntuales.

Monitorizaré, analizaré y mediré todo aquello que me pueda aportar una visión general del estado actual del proyecto (en su definición más amplia), incluyendo todas las dependencias que tuviera; pero con capacidades de bajar hasta la singularidad para observar con detenimiento el funcionamiento de una pieza en particular.

Y por medio de la realización de retrospectivas, completaré el proceso de Kaizen (mejora continua) del proyecto, incluyendo todos los orígenes relacionados con el desarrollo positivo de los trabajos.

Sobre las fases del ciclo DevOps

Continuous Delivery Infographic 1x

He mostrado una visión generalizada e idílica de un ciclo DevOps completo, siguiendo una estructura lógica basada en la experiencia y en la profusa literatura que hay publicada.

La realidad es bastante más compleja tanto en la implantación como en la ejecución; pero sin duda el mayor escollo son los problemas de comunicación entre los equipos con objetivos e intereses diferentes, y la desconfianza de salir de mi zona de confort siguiendo una “moda”.

Sin embargo, los beneficios son muy importantes. Y no solo en el ámbito de la productividad, del Time to Market, o de la flexibilidad de la empresa frente a las demandas del negocio y los clientes; si no también en los factores humanos, de mejora de la calidad de vida, que hay que valorar en su justa y positiva medida.

También te recomendamos

Trabajar con microservicios: evitando la frustración de las (enormes) aplicaciones monolíticas

Así serán las smart cities en 2025 de acuerdo a tres estudios, dos directivos y un profesor

Dime cuál es la organización de tu equipo de desarrollo y te diré cómo es la arquitectura de tu software

-
La noticia El ciclo de DevOps, una guía para iniciarse en las fases que lo componen fue publicada originalmente en Genbeta Dev por Juan Quijano .

Aprendizaje no Supervisado y Detección de Anomalías: Reglas de Asociación

21/03/2018
Artículo original

Este articulo forma parte de una serie de artículos sobre clustering, detección de anomalías y reglas de asociación. Originalmente forman parte de un trabajo para el Máster Universitario Oficial en Ciencia de Datos e Ingeniería de Computadores de la Universidad de Granada en la asignatura Aprendizaje no supervisado y detección de anomalías. El resto de artículos son:

Las reglas de asociación se usan para aportar conocimiento que ayude a la toma de decisiones. Ejemplos en los que este tipo de métodos resulta útil es para conocer las tendencias de compra de los clientes. Otra aplicación es en tareas de predicción, como deducir los estudios de una persona en función de su salario. Minería de textos para asociar la presencia de términos en documentos etc.

Este tipo de modelos se usa cuando prima la interpretabilidad del modelo, y son modelos predictivos. Es habitual usarlo conjuntos difusos. A diferencia de los árboles, que parten el espacio, las reglas cubren parte del espacio, disponiendo de un grado de cubrimiento y un acierto. Disponer de un grado de cubrimiento significa que las regiones de decisión pueden solaparse o dejar zonas sin cubrir, de ahí que sean muy usadas en problemas difusos.

Definición

Las reglas de asociación son una de las técnicas más usadas para extraer conocimiento a partir de bases de datos grandes. Identifican relaciones existentes entre los datos, llamados items. Se trata de una técnica de aprendizaje no supervisado. Una regla se define como \(X \rightarrow Y\), donde \(X\) e \(Y\) son conjuntos de items disjuntos \(X\mathcal{\cap} Y = \emptyset\). Un ejemplo: \(\text{Pan} \rightarrow \text{Mantequilla}\) Cuando se compra pan, se compra mantequilla.

En sus inicios, las reglas de asociación se aplicaron a datos de supermercados, ya que a estos les interesa saber qué productos suelen comprar los clientes, para ponerlos unos junto a otros y así reducir el tiempo de compra del cliente. En el caso de un supermercado, los artículos son los items y el conjunto de cestas de la compra son las transacciones. Cada transacción es un subconjunto de items, llamado itemset. Por ejemplo Leche y pan \(\rightarrow\) mantequilla.

Los pasos a seguir antes de aplicar reglas de asociación es determinar qué datos de la base da datos son los items y cuales las transacciones. Los items son los elementos a asociar, pan, mantequilla, aceite… mientras que las transacciones son particularidades de la relación entre items (la lista de la compra concreta).

Los items pueden ser de varios tipos. Cuando cada registro es un listado de elementos, como en el caso de productos de la compra, no existen variables, un item se corresponde con un producto. Cuando existen variables con rangos, el item es un par (atributo, valor), por ejemplo una variable puesto, con valores estudiante, jefe, trabajador tendría como items (Puesto, estudiante), (Puesto, jefe) y (puesto, trabajador). Ejemplos de reglas usando items de este tipo son: (Salario, alto) \(\rightarrow\) (Estudios, Superiores). De la regla anterior se pueden deducir dos cosas: Todo el que tiene un salario alto tiene estudios superiores, o un salario alto implica estudios superiores.

Medidas Clásicas: Soporte y Confianza

El soporte de un itemset mide la frecuencia del item o itemset en la base de datos, es decir, la probabilidad de que el itemset X esté en el conjunto de transacciones (\(p(X)\)). El soporte de una regla de asociación (X \(\rightarrow\) Y ) es la frecuencia con la que ocurre el itemset \(X \cup Y\). Es decir, la probabilidad de que el itemset \(X \cup Y\) esté en el conjunto de transacciones (\(p(X\wedge Y)\)). La confianza define cómo de fiable es la regla, es decir, cómo de seguro está el modelo de que cuando se da \(X\) va a ocurrir \(Y\). Es útil comprobar la confianza en ambos sentidos de la regla, es decir, dado X \(\rightarrow\) Y comprobar tanto \(Conf(X, Y)\), como \(Conf(Y, X)\). Como regla general, una confianza superior al 80% es buena, aunque esto es subjetivo y depende del problema y el experto.

Definidas las medidas clásicas, la extracción de las reglas se lleva a cabo a partir de un conjunto de transacciones T. Dado ese conjunto se desea encontrar todas las reglas que cumplan:

  • minSup: Definido como Soporte \(\geq\) soporte mínimo.
  • minConf: Definida como Confianza \(\geq\) confianza mínima.

Ambos valores los debe definir el experto del problema.

Lo más sencillo es resolver este problema mediante fuerza bruta (Generar todas la reglas posibles, calcular para cada una de ellas el soporte y confianza y descartar las que no superen los umbrales anteriores). Sin embargo es inviable para problemas grandes. El enfoque basado en dos pasos genera primero todos los itemset frecuentes (aquellos con un soporte mayor o igual al umbral minSup), posteriormente genera las reglas con una confianza alta basándose en los itemset anteriores. El problema de esta aproximación es que el número de combinaciones posibles es de \(2^d\), siendo \(d\) el número de items, y por tanto la generación de los itemset es costosa.

Dado a la inviabilidad de resolver el problema mediante fuerza bruta, es necesario reducir el número de candidatos posibles (de los \(2^d\) usar técnicas de poda para reducir el espacio), el número de transacciones y el número de comparaciones.

Métodos Clásicos de extracción de reglas

Algoritmo Apriori

Definición

El primer método clásico se llama Apriori, es el que peor funciona de todos, pero del que más versiones existen. Se basa en la propiedad de anti monotonía del soporte, es decir, si un itemset es frecuente, entonces todos sus subconjuntos deben serlo también:

$$X\subseteq Y \Rightarrow sop(X) \geq sop(Y)$$

Algoritmo

El algoritmo funciona del siguiente modo: En memoria mantiene dos tablas, \(L_k\) guarda el conjunto de k-itemsets frecuentes, \(C_k\) almacena el conjunto de k-itemsets candidatos a ser frecuentes. El algoritmo (Suponiendo k=1 ):

  1. Generar \(L_1\) (itemsets frecuentes de longitud 1)
  2. Repetir hasta que no se encuentren más itemsets nuevos:
    1. Generar el conjunto C(k+1) de itemsets candidatos a partir de \(L_k\), combinando solo aquellos que se diferencien en el último item.
    2. Calcular el soporte de cada candidato.
    3. Eliminar los candidatos infrecuentes.
    4. Incrementar k en 1.

La figura 1 muestra un ejemplo.

Ejemplo algoritmo Apriori. *Créd. Rafa Alcalá, Profesor Reglas de Asociación*
Ejemplo algoritmo Apriori. *Créd. Rafa Alcalá, Profesor Reglas de Asociación*

Eficiencia

La elección del umbral para el soporte mínimo debe ser adecuada, umbrales demasiado bajos dan lugar a muchos itemsets e incrementará la complejidad. El número de items en la base da datos es un factor importante y afecta al rendimiento del algoritmo. De igual manera, el tamaño de la base de datos puede hacer incrementar considerablemente el tiempo de ejecución, ya que apriori realiza múltiples pasadas a toda la base de datos. Por último, la longitud de las transacciones puede aumentar la longitud de los itemsets frecuentes, requiriendo de más espacio para almacenarlos.

Algoritmo Eclat

Este algoritmo es igual que Apriori pero mejora el cálculo del soporte obteniendo el mismo resultado. Para cada item almacena en una lista en qué transacción aparece dicho item, de esta forma se reduce el tiempo de cómputo sacrificando más memoria.

Algoritmo FP-Growth

Definición

Este algoritmo genera una representación comprimida de la base da datos mediante árboles. Mantiene una tabla cabecera donde para cada item hay una lista enlazando a todos los nodos del grafo en el cual aparece dicho item. Además, el grafo de transacciones resume las transacciones en la base de datos junto con el soporte del itemset que se forma siguiendo el camino desde la raíz del grafo hasta el nodo en cuestión. Como requisito, los items deben estar ordenados. De todos los métodos vistos, FP-Growth es el más eficiente.

Extracción de itemsets frecuentes

En este algoritmo se realiza en dos fases. Primero se calcula el soporte de los items que aparecen en la tabla cabecera, recorriendo la lista almacenada en la tabla. Posteriormente, para cada item superando el umbral de soporte, se extraen las ramas del árbol donde aparece el item y se reajusta el soporte de todos los items que aparecen en las ramas. Se genera un nuevo árbol considerando las ramas extraidas y se extraen los itemsets que superen el umbral de soporte mínimo.

Conjuntos maximales y cerrados

Los itemsets Maximales son aquellos itemsets frecuentes para los que ninguno de sus superconjuntos inmediatos son frecuentes. La Figura 2 muestra un ejemplo. Las ventajas de usar conjuntos maximales es la reducción del espacio, ya que a partir de los itemsets frecuentes maximales se pueden deducir los itemsets frecuentes. Como desventaja no se conoce el soporte de los itemsets frecuentes, hay que volver a calcularlo.

En azul: *itemsets* frecuentes, en amarillo: *Itemsets Maximales*. *Créd: [hypertextbookshop](http://www.hypertextbookshop.com/dataminingbook/public_version/contents/chapters/chapter002/section004/blue/page001.html)
En azul: *itemsets* frecuentes, en amarillo: *Itemsets Maximales*. *Créd: hypertextbookshop

Los itemsets cerrados son los itemsets frecuentes para los que ninguno de sus superconjuntos inmediatos tienen soporte igual al de ellos. Cabe destacar que todo itemset maximal es también cerrado. La figura 3 muestra un ejemplo. La ventaja de los itemsets cerrados es que no es necesario volver a calcular el soporte, mientras que como desventaja necesitan más espacio, al haber más cerrados que maximales.

En azul: *itemsets cerrados*, en amarillo: *Itemsets maximales*. *Créd: [hypertextbookshop](http://www.hypertextbookshop.com/dataminingbook/public_version/contents/chapters/chapter002/section004/blue/page001.html)
En azul: *itemsets cerrados*, en amarillo: *Itemsets maximales*. *Créd: hypertextbookshop

Para terminar, estos dos conjuntos están relacionados, como muestra la Figura 4, los maximales son un subconjunto de los cerrados.

En azul: *itemsets cerrados*, en amarillo: *Itemsets maximales*. *Créd: [hypertextbookshop](http://www.hypertextbookshop.com/dataminingbook/public_version/contents/chapters/chapter002/section004/blue/page001.html)
En azul: *itemsets cerrados*, en amarillo: *Itemsets maximales*. *Créd: hypertextbookshop

Generación de reglas

A partir de los itemsets frecuentes se generan todas las reglas posibles y solo se quedan las que superen los umbrales de confianza mínimo. Por lo general es preferible general reglas con un solo elemento en el consecuente (ABC \(\rightarrow\) D), pero nada impide que exista más de un objeto en el consecuente, sin embargo, de este modo se generarán bastantes más reglas posibles. Como beneficio a generar reglas con un solo elemento en el consecuente se obtienen reglas más interpretables, ya que AB \(\rightarrow\) CD \(\equiv\) AB \(\rightarrow\) C y AB \(\rightarrow\) D.

Problemas abiertos

Todo el contenido anterior es para reglas de asociación binarias, es decir, valores categóricos. Pero la mayoría de problemas reales contienen variables numéricas y las reglas no serán buenas. Para ello hay que dividir el domino de los atributos en intervalos, como se describió anteriormente (Puesto, Estudiante) etc y usar conjuntos difusos.

En cuanto a las medidas de calidad para evaluar reglas de asociación se debe tener cuidado. Por lo general se deben usar varias medidas de calidad que se complementen a la hora de evaluar la calidad de una regla, estas medidas, entre otras son lift, factor de certeza…

Consejos

  • Si al generar reglas hay items con soporte demasiado altos es mejor no tener en cuanta dichos items. Por ejemplo, si un producto se compra el 100% de las veces, no merece la pena añadirlo a los itemsets, ya que no va a aportar información útil.
  • Antes de comenzar un problema de reglas de asociación, lo más importante es tener claro qué queremos encontrar en los datos y conocer el problema presente.

Bibliografía

Sesgos Cognitivos en Programación

21/03/2018
Artículo original

Este artículo es una traducción del original de Yash Ranadive en Hackernoon.

Como desarrolladores, estamos familiarizados con los diversos problemas que interfieren con nuestra productividad. Pero a menudo los árboles no nos dejan ver el bosque, perdiendo perspectiva. Algunos pueden ser sutiles, otros enormes, por algunos se puede hacer algo, y hay otros por los que, simplemente, nada se puede hacer. Muchas veces se combinan para formar una especie de bucle que se retroalimenta a sí mismo y que suele llevar a la pérdida de horas de productividad, errores de programación, y a la frustración generalizada.

Si pudiésemos minimizar el impacto de tan solo uno o dos de estos sesgos podríamos romper el ciclo y neutralizar a los demás. A continuación tienes una lista de 5 sesgos cognitivos que debes tener en cuenta mientras estás programando:

Imagen ornamental

El descuento hiperbólico

Ir a por una recompensa inmediata en lugar de demorar una mucho mayor

¿Alguna vez has retrasado hacer una prueba unitaria? ¿Alguna vez te has encontrado usando las teclas de flechas en Vim? Felicidades, has exhibido comportamiento de descuento hiperbólico. La recompensa inmediata de usar las teclas de flechas supera de largo el sufrimiento de tener que encontrar la sintaxis correcta para navegar a la línea que queremos. Sin embargo, una vez que aprendes a navegar más rápido, la satisfacción futura es mucho mayor. Terminas ahorrando muchísimo tiempo.

El efecto IKEA

Sobrevalorar tus propias soluciones a un problema, y en consecuencia infravalorar otras soluciones

El efecto IKEA es un sesgo cognitivo mediante el cual los consumidores atribuyen desproporcionadamente un alto valor a un producto que han elaborado parcialmente. Tendemos a sobrevalorar nuestras propias soluciones a un problema, y en consecuencia infravalorar otras posibles soluciones. Si alguna vez has trabajado en alguna empresa que ha usado una mala herramienta interna en vez de una mejor solución "paquetizada" lista-para-usarse , ya sabes de lo que estoy hablando.

Optimización prematura

Optimizar antes de saber lo que necesitas

No necesita explicación. Añadirle un alerón aerodinámico a un viejo vehículo antes de arreglarle el motor no hará que vaya más rápido. Un gran ejemplo de esto es escribir un código super tuneado y de gran rendimiento cuando lo que tienes entre manos es un simple experimento.

La falacia de la planificación

Infravalorar de manera optimista el tiempo que llevará completar una tarea

La falacia de planificación es una con la que muchos de nosotros nos podemos identificar. Ya sea nuestra culpa, o la de los jefes de proyectos, o la de nuestros usuarios/clientes, todos tendemos a ser optimistas a la hora de determinar cuándo vamos a terminar una tarea. Esto se demuestra claramente con el viejo aforismo:

"El primer 90% del código equivale al primer 90% del tiempo de desarrollo. El restante 10% del código equivale al otro 90% del tiempo de desarrollo."

El sesgo de lo reciente

Darle más valor a los sucesos recientes que a aquellos que ocurrieron más atrás en el tiempo

El sesgo de lo reciente a menudo nos ocurre cuando necesitamos una solución para un problema, y oye, hace poco solucionamos un problema similar así que usemos esa solución porque nos ha funcionado, ¡y nos acordamos!

¿Te encuentras usando los mismos patrones de diseño una y otra vez? Si es tu caso, probablemente estás enfocando problemas distintos con la misma lente. Al que tiene un martillo, todo le parecen clavos.


Es imposible eliminar nuestros sesgos del todo, pero si somos conscientes de cómo nos están afectando, podemos de alguna manera limitar y mitigar los problemas que nos causan.

Las tendencias en proyectos open source para 2018 según GitHub

19/03/2018
Artículo original

GitHub es usado por más de 24 millones de personas de 200 países diferentes que han participado en proyectos a través de más de 25 millones de repositorios. Estas cifras astronómicas convierten a GitHub en el mayor repositorio de proyectos open source del mundo, así como en testigo único de lo que “se cuece” en programación.

El personal de GitHub analizó los datos correspondientes al pasado año, y según ellos las tendencias para 2018 en proyectos open source son:

Nota: Imagen de GitHub

Desarrollo web y multiplataforma

En el sector de desarrollo web y multiplataforma, los repositorios Angular / angular-cli registraron el mayor crecimiento con 2,2 veces más usuarios en 2017 que en 2016. Otros proyectos relacionados con Angular, React y Electron de Facebook, también tuvieron mucho éxito.

Deep Learning

Los desarrolladores acuden a GitHub para ver proyectos de deep learning a medida que la inteligencia artificial continúa creciendo. Dos repositorios TensorFlow crecieron: TensorFlow /models experimentó 5.5 veces más tráfico y TensorFlow / TensorFlow tuvo 2.2 veces más tráfico en 2017 que en 2016.

El deep learning ha crecido en popularidad dentro de las empresas siendo usado en reconocimiento de imágenes y voz. Compañías como Google, Facebook, Microsoft y Amazon están invirtiendo en ello.

Desarrollo profesional

Los repositorios diseñados para enseñar nuevas habilidades, especialmente nuevas habilidades de programación, también han tenido mucho éxito. Los proyectos educativos más populares enseñaban lenguajes como JavaScript y Python, otros te orientaban sobre cómo pasar las entrevistas o sobre gestión de proyectos. Mientras que los proyectos open source pueden considerarse como educativos por naturaleza, los repositorios creados específicamente para enseñar a otros pueden ser especialmente útiles para aprender o revisar habilidades.

Contenedores

También se aprecia un importante crecimiento en la edición de código, el diseño, la containerization y el desarrollo.

En lo que a contenedores se refieren destacan Docker y Kubernetes. Docker se encontraba entre los diez mejores de todos los proyectos en GitHub, mientras que Kubernetes estaba entre los diez primeros en la categoría de "proyectos más revisados", y también fue, de hecho, el proyecto más comentado en GitHub ese año.

Si deseas tener datos detallados sobre cuáles han sido los proyectos más revisados, los más populares o con más ramificaciones, puedes echar un vistazo a Universe.

Cómo reducir (mucho) el tamaño de tu instalación de Windows y Windows Server

17/03/2018
Artículo original

Afrontémoslo: Windows es un sistema operativo que "se come" muchísimo espacio en disco. Ocupa muchísimo nada más instalarlo, pero es que a medida que pasa el tiempo todavía va ocupando más y más espacio. Los motivos son variados: cachés que se hacen de todo tipo de recursos, archivos temporales, configuraciones que se guardan en el perfil de los usuarios y, sobre todo, actualizaciones del propio sistema operativo.

Si dispones de un disco duro generoso normalmente esto no es una gran molestia. Pero si tienes restricciones de espacio (por ejemplo en un tablet) o cada GB extra ocupado te cuesta dinero (en la nube), esto puede llegar a ser un problema grave.

Lo primero que todos intentamos es borrar cosas innecesarias utilizando la utilidad que viene integrada en Windows:

La cual (sobre todo ejecutándola en modo administrador) es capaz de borrar archivos temporales, cachés y algunos archivos del sistema que ya no se necesitan.

Sin embargo los ahorros son más bien exiguos. Así que si necesitamos liberar más espacio lo siguiente suele ser utilizar algún programa para analizar el espacio en disco, y así identificar qué carpetas son las responsables de consumir más espacio.

Por supuesto, la carpeta más glotona es casi siempre "C:\Windows", y más en concreto, dentro de ésta, "C:\Windows\WinSxS". Esta carpeta siempre ocupa unos cuantos GB, y además va aumentando con el tiempo. No es raro que ocupe 10, 12 o 15GB de tu precioso espacio que podría ser utilizado para otras cosas. 

Esta carpeta (Windows Side by Side, de ahí su nombre) contiene la caché nativa de ensamblados. Este pomposo nombre viene de los tiempos de Mari Castaña Windows Millenium (Windows Me: si no te suena, mejor para ti), y se suponía que iba a ser la solución del famoso "Infierno de las DLL" que infestaba a los sistemas operativos de por aquel entonces. En la actualidad sigue estando presente en todas las versiones de Windows, incluso las más recientes, y almacena todo tipo de basura electrónica al más puro síndrome de diógenes digital. De hecho, desde Windows Vista, almacena también los componentes del propio sistema operativo, por lo que, cuando una biblioteca o un componente del sistema operativo se actualiza, la versión vieja se archiva aquí, al igual que la nueva, que ahora apunta (mediante un hardlink) a la biblioteca real a la que está sustituyendo. De esta forma, si hay necesidad de utilizar dos versiones diferentes de lo mismo, las tienes aquí, o si hay que echar atrás alguna actualización, también podrías hacerlo.

Lo que ocurre es que lo más habitual es que esta carpeta permanezca llena de cosas obsoletas durante muchísimo tiempo, ocupando mucho espacio en disco.

OJO: si vas a mirar el espacio ocupado en disco por "C:\Windows" con el explorador de archivos, el tamaño que te dará es mayor que el real. El motivo es precisamente lo que comentamos de los Hardlinks. Un hardlink permite que un mismo archivo esté en más de un sitio al mismo tiempo, pero que realmente solo esté guardado en disco una única vez. Peor el explorador de archivos no los gestiona bien y los cuenta todas las veces. Como muchos de los archivos que hay, por ejemplo, en "C:\Windows\System32" en realidad son hardlinks a archivos de WinSxS, la carpeta del sistema parece ocupar mucho más de lo que en realidad ocupa. Si usas un programa que tenga en cuenta esto verás que el espacio ocupado no es en realidad tanto como parece. Eso sí, WinSxS está lleno de cosas inservibles a priori que sería bueno eliminar si andamos justos de espacio.

¿Podemos eliminar el contenido de WinSxS?

La respuesta es no. No directamente. Nos podríamos cargar partes importantes del sistema y dejarlo inutilizado, pero es que además tampoco podríamos debido a los permisos necesarios, ya que es una carpeta especialmente protegida por el sistema.

Entonces ¿qué podemos hacer?

Por suerte todas las versiones modernas de Windows ofrecen una herramienta de línea de comandos que sirve precisamente para lidiar con esta situación. Se trata de la Herramienta Deployment Image Servicing and Management, o dicho más breve, DISM. Esta herramienta apareció con Windows Vista SP1 y Windows Server 2008, por lo que la tienes en cualquier sistema operativo anterior.

Para sacarle partido solo tenemos que abrir una línea de comandos como administradores y ejecutar un par de instrucciones.

Lo primero es averiguar cuánto espacio tenemos ocupado por WinSxS y cuánto realmente se puede liberar. Esto se consigue con esta instrucción:

Dism.exe /Online /Cleanup-Image /AnalyzeComponentStore

Por ejemplo, esta captura proviene de aplicar el comando en una máquina virtual con Windows Server 2016 recién instalado en un conocido proveedor Cloud:

Fíjate en cómo nos indica que el explorador de Windows nos diría que la carpeta ocupa casi 23GB!, aunque en realidad ocupa 19,03GB (que sigue siendo una barbaridad). Dado que la máquina virtual viene con unos exiguos 40GB de disco duro, todo lo que podamos liberar va a ser una gran ventaja para nosotros.

Nos indica que hay 5,79GB compartidos con Windows. Esos no los podemos eliminar, pero los otros más de 13GB que hay entre backups, características deshabilitadas del sistema y cachés y datos temporales, sí que podremos recuperarlos, así que en un caso así es un beneficio enorme. En esta máquina virtual en concreto, supone ¡ahorrar más de un 32% de espacio en disco!.

Para lograrlo en la misma línea de comandos escribe:

Dism.exe /online /Cleanup-Image /StartComponentCleanup /ResetBase

Esto le indica a DISM que libere todo el espacio que pueday que deje solo las últimas versiones de los componentes del sistema. Con esto conseguiremos el máximo ahorro, pero no podremos volver atrás si necesitamos deshacer una actualización (algo que raramente haremos de todos modos). Si llevas bastante tiempo con el sistema actualizado y sin problemas no deberías tener problema alguno por hacerlo.

El proceso tarda bastante rato, y podemos ver el resultado final en la pantalla así:

No nos indica gran cosa, pero podemos ver el log en la ruta indicada y si comprobamos el espacio libre en disco desde el explorador de archivos, veremos que hemos ganado un montón de GBs para ser utilizados para otras cosas más útiles.

Windows 10 y Windows Server 2016 se supone que ejecutan este proceso automáticamente de vez en cuando, pero probablemente no de modo exhaustivo como hemos hecho nosotros, pues esta carpeta no de deja de crecer. Tampoco hay que obsesionarse con hacer esto cada pocos días, pero seguramente hacerlo una vez al año (o cuando veamos que la carpeta de "desmadra") nos vendrá muy bien.

¡Espero que te sea útil!

¿Qué pruebas debemos hacerle a nuestro software y para qué?

15/03/2018
Artículo original

Testing

“Los test no son opcionales”. Esto que parece a muchos una verdad de perogrullo, sigue siendo uno de los temas pendientes en el mundo del desarrollo de aplicaciones de software actual.

Sí, increíblemente aún hay muchos compañeros “del metal” que no son conscientes que programar sin pruebas no solo es como hacer acrobacias en el trapecio sin red de seguridad, sino además una fuente de errores, malas prácticas y ansiedad.

Y por ello quiero repasar los fundamentos básicos de las pruebas que debiéramos aplicar, cada uno en su necesidad, a nuestros desarrollos.

¿Por qué hacer pruebas?

Para que lo entienda hasta el más novel de los lectores, hacer pruebas es la forma de asegurarse que lo que queremos que haga nuestro programa, lo haga, y lo haga sin errores.

La construcción de software implica conocimiento, experiencia, talento, capacidad intelectual y un punto de arte. Es decir, es una labor muy difícil, y falta aún mucho para que eso cambie a mejor. De hecho, la complejidad está tendiendo al crecimiento de una forma, como en todo lo relacionado con el Front-End en Javascript, al absurdo.

Habiendo superado, hace ya décadas, la capacidad humana de aprensión y memorización; lo que implica necesariamente que los fallos y errores son inevitables si los intentamos evitar con solo nuestras capacidades humanas.

Las pruebas no son opcionales. Un software sin pruebas es una bomba a punto de estallar

¿A quien no le ha pasado que ha dejado su código medio año en un cajón, y a la vuelta de ponerse a toquetearlo tener la sensación de que lo ha escrito otra persona? No reconocemos a nuestra propia criatura.Y no hablemos cuando estamos integrados en un equipo, o recibimos el “regalito” de soportar o evolucionar un código heredado.

Por ello las pruebas son imprescindibles, ya que nos permiten garantizar que las aplicaciones cumplen las funcionalidades que se esperan de ellas y las expectativas de calidad (no solo de código); ayudando a encontrar esos errores o defectos que aún no se han descubierto; reduciendo el costo del desarrollo, el de propiedad para los usuarios; y desarrollar confianza en los clientes al evitar los molestos errores de regresión.

Eso sin hablar de la sensación de seguridad incremental que se obtiene cuanto más cerca estamos de un despliegue, ya que a más código que tenemos, más pruebas nos aseguran (en forma de una tupida malla) que todo funciona correctamente.

DevOps y la herencia de la automatización

Devops

La llegada de las metodologías Agiles, desde los años 90 del siglo pasado, fue un revulsivo en la organización y ejecución de pruebas dentro de procesos Waterfall.

En estos últimos, se podría generalizar, las pruebas principalmente eran manuales; definidas meticulosamente en voluminosos documentos de planes de pruebas; y que se realizaban solamente una vez acabada la codificación del software.

Xtreme Programming, en cambio, hizo mucho hincapié en la automatización y en el concepto de pruebas orientadas a la prevención de los finales de los años 80; marcando de esta forma, la futura filosofía Agile. Por ello, actualmente utilizamos frameworks de pruebas que permiten realizar automáticamente la mayoría de los test en todos los ámbitos de la aplicación.

Las pruebas manuales y automatizadas son complementarias

Y más cuando se pretende adoptar el concepto de Integración Continua, como parte imprescindible de DevOps, donde la propia construcción y validación de la Build por medio de todo tipo de pruebas automáticas es parte inherente del proceso.

Siendo esto aún más crítico en niveles altos de madurez en donde llegaríamos a aplicar despliegue automatizado o, incluso, continuo.

La importancia que han ido ganando las pruebas ha sido tal que la propia forma de codificar el software también ha sufrido cambios profundos. El nacimiento de TDD (desarrollo orientado a las pruebas) y su forma de supeditar el código a los test, implica que hacer software testeable es un requisito imprescindible en el código de calidad.

Y, aunque no lleguemos a utilizar esta avanzada técnica de desarrollo (que no es nada fácil), el objetivo de poder probar de forma automática nuestro código, ha reforzado prácticas tan importantes en la programación orientada a objetos como es SOLID.

Pruebas automatizadas vs manuales

Tortoise And Hare

Tenemos una primera gran división en el mundo de las pruebas entre las automatizadas y las manuales.

Como indica su nombre, las primeras dependen de una herramienta de pruebas que implica, en casi todos los casos, un lenguaje o subconjunto del lenguaje propio. Es decir, si las hago en nUnit va a ser muy complicado pasarlas a MS Test.

Las pruebas manuales requieren de interacción humana. El probador se pone en la piel del rol de usuario que se tenga que validar, y realiza todas aquellas operaciones que tenga definidas en un plan de pruebas, o le busca “las cosquillas” al sistema para llegar allí donde ningún “luser” ha llegado anteriormente...

Como ves, ambos tipos de ejecución de pruebas son complementarios e importantes para garantizar un software de calidad.

La automatización es rápida y puede probar muchas variaciones sutiles en los datos; también puede repetir fácilmente las pruebas a medida que el software evoluciona; y debido a que es ejecutado por el sistema, se evita la fatiga y los errores que a veces acompañan a las tareas repetitivas.

En cambio, aunque las pruebas manuales generalmente tardan más en ejecutarse (ya que las realiza una persona), a menudo requieren mucho menos tiempo de configuración. Es una buena opción para las pruebas que solo deben ejecutarse ocasionalmente, o en los casos en que el costo/tiempo de la configuración de automatización supere los beneficios.

Un universo de tipos de pruebas

Siguiendo los pasos de la complejidad inherente de nuestra industria, las pruebas también sufren de una miríada inacabable de tipos, versiones, evoluciones y clases. Pero centrémonos en las más importantes e imprescindibles, según cada caso y contexto.

Prueba unitaria: las pruebas unitarias son pruebas automatizadas que verifican la funcionalidad en el componente, clase, método o nivel de propiedad.

Tddmantra

El objetivo principal de las pruebas unitarias es tomar la pieza más pequeña de software comprobable en la aplicación, aislarla del resto del código y determinar si se comporta exactamente como esperamos. Cada unidad se prueba por separado antes de integrarlas en los componentes para probar las interfaces entre las unidades.

Las pruebas unitarias deben escribirse antes (o muy poco después) de escribir un método; siendo los desarrolladores que crean la clase o el método, quienes diseñan la prueba.

Así, conseguimos mantener el foco en lo que debe hacer el código, y se convierte en una poderosa herramienta para aplicar KISS, JIT, y mantener el foco en lo que tiene que hacer en vez de en el cómo, evitando introducir complejidad sin valor.

Pruebas de integración: desde una perspectiva de prueba, las unidades individuales se integran juntas para formar componentes más grandes. En su forma más simple, dos unidades que ya han sido probadas se combinan en un componente integrado y se prueba la interfaz entre ellas.

Las pruebas de integración – o de componentes - identifican problemas que ocurren cuando las unidades se combinan. Los nuevos errores que surgen probablemente estén relacionados con la interfaz entre las unidades en lugar de dentro de las propias unidades; simplificando la tarea de encontrar y corregir los defectos.

Pruebas de regresión: cada vez que se realizan cambios en un proyecto, es posible que el código existente ya no funcione correctamente o que se presenten errores no descubiertos previamente. Este tipo de error se llama regresión.

Para detectar estos defectos, todo el proyecto debe someterse a una regresión: una nueva prueba completa de un programa modificado, en lugar de una prueba de solo las unidades modificadas, para garantizar que no se hayan introducido errores con las modificaciones.

Como se puede deducir, este tipo de pruebas debe ser automatizado porque puede estar compuesto por decenas o miles de pruebas unitarias, de integración o más.

Una versión menos costosa, podría ser construir pruebas que repliquen las acciones que provocaron la regresión, y comprueben que han sido corregidos al no volver a sucederse los errores; además de añadir los test unitarios que aseguren que el código que ha corregido la regresión funciona correctamente.

Pruebas de funcionalidad: pruebas automatizadas o manuales que prueban las funcionalidades de la aplicación o módulo construidos desde el punto de vista del usuario final, con sus diferentes roles, para validar que el software hace lo que debe y, sobre todo, lo que se ha especificado.

En su versión automática son pruebas que se automatizan para "ahorrar tiempo de pruebas". A partir de los casos de prueba de las pruebas manuales, se automatizan los casos de prueba para que se repitan en las ejecuciones. Esos casos suelen ser los más importantes (happy flow) de los módulos o procesos de negocio "vitales" de la aplicación. Es decir, los procesos que siempre tienen que funcionar y que bajo ningún concepto pueden fallar. El objetivo de las pruebas funcionales automáticas es comprobar que no haya regresiones.

Las pruebas obligan a hacer un código desacoplado y promueven la calidad

En el caso de las manuales, las ejecuta un tester como si fuese un usuario, pero siguiendo una serie de pasos establecidos en el plan de pruebas, diseñado en el análisis de los requisitos para garantizar que hace lo que debe (casos positivos), que no falla (casos negativos) y que es lo que se ha solicitado.

El tester realizará las acciones indicadas en cada paso del caso de prueba comprobando que se cumple el resultado esperado. Si el resultado es distinto, se reportará un defecto con todo detalle: descripción, datos utilizados, capturas de pantalla, etc., para facilitar la solución.

El mayor problema con el que se enfrentan las pruebas funcionales para ser automatizadas es su fragilidad. Cada prueba testea miles de líneas de código, centenares de integraciones en todos los tiers, y una interfaz de usuario cambiante. Llegando a no ser sostenible el conjunto de pruebas en relación con su definición, coste y mantenimiento.

Llevando las aplicaciones a su límite

Test De Carga

Ya tenemos probada y desplegada nuestra aplicación. Ahora viene la parte de operaciones y también se debe probar de forma automática las capacidades y debilidades del software y de la plataforma sobre la que corre (infraestructura y dependencias), llevándola al límite, para comprobar su disponibilidad, estabilidad y resiliencia.

Pruebas de estrés: las pruebas a pequeña escala, como un usuario único que ejecuta una aplicación web o una base de datos con solo un puñado de registros, pueden no revelar problemas que suceden cuando la aplicación se usa en condiciones "reales".

La prueba de estrés empuja los límites funcionales de un sistema. Se realiza sometiendo el sistema a condiciones extremas, como volúmenes de datos máximos o una gran cantidad de usuarios simultáneos.

También se utilizan para, llevado el sistema al colapso o degradación, comprobar su funcionamiento continuado por encima de su límite y, una vez liberado de la carga, evaluar su capacidad de resiliencia volviendo a su estado óptimo de funcionamiento.

Lleva la aplicación al límite, busca que rompa, y luego observa como se reconstruye

Y en la actualidad cada vez más se utilizan las capacidades de la Cloud tanto para crear un gran número de usuarios, distribuir las peticiones en todo el mundo, como para obtener los recursos de procesamiento, memoria y almacenamiento necesarios en operaciones de este calibre.

Prueba de rendimiento: determinan la capacidad de respuesta, el rendimiento, la confiabilidad y/o la escalabilidad de un sistema bajo una carga de trabajo determinada.

En aplicaciones web, las pruebas de rendimiento a menudo están estrechamente relacionadas con las pruebas de estrés, la medición del retraso y la capacidad de respuesta bajo una carga pesada.

En otras aplicaciones (escritorio y aplicaciones móviles, por ejemplo), las pruebas de rendimiento miden la velocidad y la utilización de recursos, como el espacio en disco y la memoria.

Si almacenamos todos los resultados de las pruebas de rendimiento durante un plazo de tiempo, podemos conocer el estado de salud de la aplicación, pudiendo obtener tendencias y previsiones de funcionamiento; y optimizando cada despliegue según el rendimiento necesario en cada caso.

Pruebas de seguridad: validan los servicios de seguridad de una aplicación e identifican posibles fallos y debilidades.

Muchos proyectos utilizan un enfoque de caja negra para las pruebas de seguridad, lo que permite a los expertos, sin conocimiento del software, probar la aplicación en busca de agujeros, fallos, exploit y debilidades.

Y esto es solo el principio

Funcionales, Usabilidad, Exploratorios, Aceptación, Infraestructura, etc. El universo de las pruebas es inmenso, siendo una de las ramas de la mal llamada informática, que requiere de una especialización especifica.

Y más cuando la llegada de la Infraestructura como Código, automatiza y mejora procesos conocidos como el Estado de Configuración Deseada, añadiendo capacidades de lógica de negocio en la construcción, mantenimiento y pruebas a nivel de plataforma.

No lo olvides nunca: las pruebas no son opcionales.

También te recomendamos

12 herramientas imprescindibles para asegurar la calidad del software (y sus alternativas)

DevOps. ¿Moda, mito o evolución?

Cómo ver nuestras historias archivadas en Instagram

-
La noticia ¿Qué pruebas debemos hacerle a nuestro software y para qué? fue publicada originalmente en Genbeta Dev por Juan Quijano .

Cómo empezar a desarrollar utilizando Docker

14/03/2018
Artículo original

 Logotipo de Docker

Nota: el artículo original es de Jakub Skalecki, traducido con su permiso expreso. Puedes seguir a Jakub en Twitter y en LinkedIn.

En esta ocasión vamos a hablar de una gran herramienta que se usa mucho en el día a día trabajando como desarrollador. Se llama Docker. Antes de nada, aclarar que este post va dirigido a principiantes.

Sí, he oído hablar de Docker, ¿pero qué es en realidad?

Docker es una herramienta para crear y ejecutar "máquinas virtuales ligeras". Se distribuyen en paquetes que por regla general contienen:

  • Una pequeña distribución de Linux (aunque también trabaja con Windows),
  • todas las dependencias necesarias para que tu aplicación se ejecute,
  • y el código de tu aplicación.

Se llaman "imágenes Docker" y puedes pensar en ellas como "cajas negras ejecutables". Estas imágenes se pueden utilizar para crear un número arbitrario de "contenedores", procesos aislados con acceso a todas las dependencias preparadas. Una cosa importante es que cada contenedor es una copia exacta de una imagen, incluso si se inicia en un sistema operativo diferente. No importa qué tecnología o lenguaje se requiera para ejecutar tu aplicación, si tienes instalada la imagen y Docker, podrás ejecutarla.

Voy a procurar que este artículo sea breve y conciso, así que pasemos a las ventajas de usar Docker. Si quieres saber más, puedes consultar la este artículo + vídeo.

¿Por qué debería darle una oportunidad a Docker?

Recordemos, no tienes por qué entrar "de lleno".

Te aconsejo que vayas incorporando soporte con Docker en tu aplicación de manera progresiva. Empieza a usarlo en desarrollo. Comenta con los demás en tu equipo de desarrollo que pueden usar Docker, muéstrales cómo usarlo. Espera a ver qué pasa, acostumbraos a utilizarlo y familiarizaos con él. Cuando alguien pregunte "oye, ¿por qué diablos no hemos empezado a trabajar con esto antes?", ya quizás sea el momento de empezar a pensar cómo integrarlo en la fase de producción... Pero centrémonos en la fase de desarrollo por hoy.

En desarrollo, Docker te permite conservar toda la infraestructura en forma de código y compartirlo con todos los miembros de tu equipo. ¿Te suenan conversaciones de este estilo?:

(Tú): -"Oye Pedro, mi aplicación en desarrollo no arranca... ¿Has tocado algo?"-

Pedro: -"Ah, sí, se me olvidó comentarte. Tenemos un nuevo motor de base de datos. Además hay que instalarle el redis y los drivers. Es muy sencillo, échale un ojo a la documentación y lo haces en un minuto."-

Claro, siempre lleva más tiempo que ese "minuto". Si trabajas en un equipo muy grande, estas cosas pasan mucho más a menudo y se complica mucho identificar el origen de los problemas. Con Docker, para sincronizar los cambios solo hay que ejecutar docker-compose up --build, y en breves instantes la nueva versión de la pila de desarrollo estará en funcionamiento, independientemente de lo que haya cambiado. Además, el hecho de incorporar un nuevo programador en el equipo de desarrollo no supondrá trauma alguno, ya que todo será igual... Imagina cuánto tiempo se puede llegar a ahorrar.

Personalmente, trabajo con muchas tecnologías diferentes en paralelo, usando diferentes versiones de dependencias comunes (por ejemplo, bases de datos). Docker me permite aislarlas. También, independientemente de la tecnología, puedo trabajar siempre de la misma manera- docker-compose up- y para adelante...

Hay un lugar llamado Docker Hub. Es una tienda oficial con un montón de imágenes listas para ser utilizadas, que puedes emplear en tu "stack" de desarrollo. ¿Necesitas redis? ¿Postgres? ¿MySQL, Apache, PHP, nGinx, Python, Ruby, NodeJS? ¡Todo disponible en un clic!

Bien, la cosa promete. ¿Cómo empezar?

Primero: instala docker y docker-compose.

Puedes acceder a las instrucciones oficiales aquí y aquí.

Segundo: añade un Dockerfile propio a tu aplicación

Dockerfile contiene una lista de instrucciones que se tienen que ejecutar para preparar el entorno, para luego poder ejecutar tu aplicación. Por ejemplo, aquí copias tus archivos de proyecto, instalas todas las dependencias del sistema y la aplicación, haces los ajustes de configuración, etc... Por ejemplo, veamos un Dockerfile que se utiliza para un proyecto en Python:

FROM python:3.6

ENV PROJECT_ROOT=/srv
WORKDIR $PROJECT_ROOT

COPY requirements.txt .
RUN pip install -r requirements.txt

COPY . .

CMD ["python", "manage.py", "runserver"]

Por lo general no se necesita nada más sofisticado. Para encontrar instrucciones sobre cómo crear un Dockerfile para tu lenguaje de programación solo tienes que buscarlo en Google, hay muchísimos recursos sobre esto en particular.

Si quieres aprender sobre buenas prácticas, este artículo ya ha ayudado a muchas personas. También te puedes dirigir a la página oficial.

Tercero: crea un archivo docker-compose.yml.

Docker-compose es una herramienta genial que nos permite gestionar simultáneamente varias pilas de contenedores sin traumas. Este archivo especial le dice a docker-compose qué contenedores tienen que iniciarse.

Este es un ejemplo de docker-compose.yml que utilizo:

version: '2'
services:
redis:
  image: redis

database:
  image: postgres

app:
  build: .
  environment:
    DEBUG: 1
  ports:
    - 8000:8000
  volumes:
    - .:/srv
  command: python manage.py runserver

Este archivo indica que queremos que Redis y Postgres se creen usando imágenes oficiales, y que nuestra aplicación se cree desde Dockerfile en local, disponible desde la red de Docker externa a través del puerto 8000, con todos los archivos locales montados dentro del contenedor para facilitar el desarrollo. Se pueden encontrar todas las opciones aquí. En este ejemplo se usa la versión 2 porque la versión soporta Docker Swarm que no se necesita en desarrollo.

Ahora, cuando introduzcamos docker-compose up, esto es lo que va a suceder:

  1. Docker intentará descargar / crear todas las imágenes requeridas. Si usamos la opción image, se descargará de Internet, por defecto desde DockerHub. La opción build dará instrucciones a Docker de crear la imagen usando el Dockerfile ubicado en un directorio concreto, en nuestro caso . (dir actual). Si la imagen ya existe, no se volverá a comprobar automáticamente (para hacerlo, debemos añadir la bandera --build)
  2. Cuando las imágenes están disponibles, docker-compose comprobará si la configuración ha cambiado desde la última ejecución. Si no, se inician contenedores usados con anterioridad, y en caso contrario, se crean nuevos contenedores. La configuración de cosas como puertos, volúmenes, variables, redes, etc... se toman desde docker-compose.yml.
  3. Si no se indica lo contrario, se crea una red especial, abarcando todos los contenedores creados. Les permite referenciarse entre ellos usando nombres en vez de direcciones IP. Como muestra, en el ejemplo, la base de datos de la aplicación estará disponible en postgres:5432.
  4. Todos los contenedores se inician a la vez, y vemos logs de todos ellos.

Y eso es todo. Ahora toda la pila arranca automáticamente. Evidentemente deberás hacer cosas como crear automáticamente una base de datos si no existe, o volver a cargar el código de la aplicación tras un cambio para hacer que la experiencia de desarrollo sea más agradable. Lo importante aquí es que solo tienes que preparar esto una vez y todo el equipo de programación se beneficiará de ello inmediatamente.

Aviso: a la hora de programar, probablemente debas usar siempre la opción volumes en tu archivo docker-compose.yml, montando los archivos locales en el contenedor. Sin esta opción, tendrás que rehacer el contenedor cada vez que haya algún cambio.

Uso típico

Estos son algunos de los comandos más utilizados en el día a día.

  • Empezando a trabajar: docker-compose up o docker-compose up --rebuild si sabes que algunas dependencias han cambiado.

  • Ejecutando comandos una sola vez: depende de si necesitamos disponibles otros contenedores, como la base de datos, o no. Si es así, arranca la pila con un comando anterior, y en otro ventana de terminal ejecuta docker-compose exec $SERVICE_NAME $COMMAND. Si no, solo usa docker-compose run --rm $SERVICE_NAME $COMMAND (yo recomiendo el "flag" --rm para eliminarlo después del comando)

  • Eliminar todo lo creado por docker-compose: docker-compose down. Eliminará todos los contenedores, imágenes y redes.

  • Eliminar un contenedor con todos los datos asociados: docker-compose rm -v $SERVICE_NAME (muy útil si quieres restablecer completamente una base de datos).

¡Esto es todo por ahora!

Espero que este artículo haya sido muy útil para empezar con Docker. Si te gusta esta post, no dudes en compartirlo.

Aprendizaje no Supervisado y Detección de Anomalías: ¿Qué es una Anomalía?

12/03/2018
Artículo original

Este articulo forma parte de una serie de artículos sobre clustering, detección de anomalías y reglas de asociación. Originalmente forman parte de un trabajo para el Máster Universitario Oficial en Ciencia de Datos e Ingeniería de Computadores de la Universidad de Granada en la asignatura Aprendizaje no supervisado y detección de anomalías. El resto de artículos son:

  • Clustering
  • Reglas de Asociación (Próximamente)
  • Reglas de Asociación Avanzadas (Próximamente)

Antes de comenzar es necesario definir qué es una anomalía: Una anomalía es un dato muy distinto del resto. Esto puede deberse a fallos en mediciones, o a la propia naturaleza del dato. Por ejemplo, una intrusión a un sistema informático puede considerarse una anomalía, ya que por norma general el resto de actividades en dicho sistema serán legítimas. Por lo general, un dato se considera anómalo si escapa a los rangos de normalidad del resto de los datos.

El tratamiento de los datos anómalos debe hacerse con cuidado, ya que en ocasiones se podrá descartar (cuando son errores de medición) y en otras será importante (Introsiones/ataques a un sistema).

Ciertas técnicas de aprendizaje son más robustas frente a datos anómalos que otras. Un ejemplo de ello es la regresión lineal, la presencia de un dato anómalo afectará en gran medida al resultado del modelo, ya que este dato anómalo “tirará” de la línea de regresión hacia él. Como muestra la Figura 1

Cómo afecta un dato anómalo a una regresión
Cómo afecta un dato anómalo a una regresión

También ocurre en clustering, ya que los datos anómalos desplazan los centroides hacia ellos (Figura 2).

Cómo afecta un dato anómalo al *clustering*
Cómo afecta un dato anómalo al *clustering*

Una buena analogía en este campo es encontrar una aguja en un pajar. Esa sería la forma fácil de encontrar una anomalía, ya que al menos se sabe que hay que encontrar una aguja. Pero en muchas ocasiones no se sabe qué es lo que se debe encontrar.

Aplicaciones

Algunas aplicaciones son los Sistemas de detección de intrusiones en red (Network Intrusion Detection Systems [NIDS] ). Cuando se conoce el tipo de anomalía los NIDS son basados en firmas, pero también existen sin conocer previamente el tipo de anomalía a detectar. Este documento se centrará en la última, NIDS basados en detección de anomalías. Ejemplos de este tipo de sistemas son:

  • Detectar intrusiones de red.
  • Fraude en tarjetas de crédito.
  • Detectar brotes de epidemias.
  • Análisis de regiones sospechosas en imágenes (Como radiografías).
  • Video vigilancia.

Métodos supervisados

Cuando se conoce la existencia de anomalías en los datos, y se sabe cuales son, las técnicas usadas son de clasifiación supervisada. En este tipo de problemas se tienen dos conjuntos de datos, uno de entrenamiento y otro de test. Como se dispone de toda la información, los datos están etiquetados en función de si son anomalía o no. Con estos datos se construye un modelo que aprenda a distinguir ente un dato anómalo y uno legítimo.

Una situación muy común en este tipo de datos es que están desbalanceados. Existen muchos más datos legítimos que anómalos, lo cual sesga el resultado del modelo. Este tipo de problemas se conoce como calsificación desbalanceada. Principalmente existen dos métodos para lidiar con este problema. Métodos basados en Instancias y basados en algoritmos. El primero consiste en modificar los datos antes de pasarlos al algoritmo, mientras que el segundo usa los datos originales sobre un algoritmo modificado.

Basados en Instancias

La forma de modificar los datos antes de pasarlos al algoritmo consiste en eliminar instancias de la clase mayoritaria (undersampling) o crear instancias artificiales de la clase minoritaria (oversampling). Algunos métodos de underasmpling son Tomek-links, CNN y NCL, de oversampling SMOTE, aunque este último realiza un undersampling a la clase mayoritaria a la vez de un oversampling de la clase minoritaria.

Basados en Algoritmos

En este caso no se alteran los datos, pero asignan distintos pesos a cada instancia mediante una función de coste, bagging oo boosting. Los métodos que usan la función de coste asignan costes muy altos a las clases minoritarias. Bagging incluye más instancias de la clase minoritaria en cada paso del algoritmos de bagging. Por contra, Boosting asigna más peso a las instancias de la clase minoritaria en cada paso. También existen alternativas híbridas, como SmoteBoosting, SmoteBagging etc.

Métricas de evaluación

En este tipo de problemas la precisión del modelo no es importante, ya que un modelo sencillo que etiquete todas las instancias como legítimas podría tener un 99.9% de precisión en los casos en los que la anomalía esté presente el 0.1% del tiempo, y aún con este porcentaje de precisión no se estaría detectando ninguna anomalía. Esto es debido al desbalanceo entre las clases. Debido a ello es necesario usar otro tipo de métricas, como Recall, Precisión, F-Measure, ROC etc.

Métodos semi-supervisados

Se conoce la existencia de anomalías, pero no se encuentran en el conjunto de datos. Con este conjunto de datos se define “*la normalidad*” del entorno. Por ejemplo, en datos de red, lo normal es que todo el tráfico sea legítimo, y sin saturaciones. El problema en esta situación es saber cómo modelar un “*comportamiento normal*”. Para ello hay varias técnicas, basadas en clasificación, en reglas de asociación, en máquinas de soporte vectorial.

Los modelos de clasificación en el caso de conjuntos de datos correctamente balanceados sufre de cometer demasiados falsos positivos. Cuando un nuevo dato llega al modelo de clasificación, y éste lo clasifica incorrectamente, el dato se considera como una anomalía, lo cual no tiene por qué ser cierto. Para mejorar este modelo, se suelen usar clasificadores basados en reglas. Los clasificadores basados en reglas proporcionan más información cuando un dato se clasifica incorrectamente, informan en qué grado se considera al dato anómalo, por ejemplo, en un 80%. Otra forma de abordar el problema es mediante la generación de máquinas de estados finitos, cuando llega un nuevo dato se comprueba contra esa máquina de estados finitos para determinar la legitimidad o no legitimidad. Un ejemplo de este tipo de modelos se encuentra en la Figura 3

Máquina de estados finitos para modelar tráfico FTP
Máquina de estados finitos para modelar tráfico FTP

Los métodos basados en reglas buscan patrones frecuentes y reglas de asociación. Uno de estos métodos es LERAD. LERAD aprende reglas que encuentran eventos extraños en una serie temporal.

Los métodos basados en kernel como Máquinas de Soporte Vectoriales asumen la existencia de una única clase definida como comportamiento normal. Este comportamiento normal se construye estableciendo una región en el espacio. Todo punto que caiga en ese espacio será considerado normal. Por contra, cuando un punto cae fuera de la región es considerado anómalo. Un ejemplo de la definición de este espacio se muestra en la Figura 4. Gracias a la potencia de los kernels es posible definir distintos tipos de regiones en el espacio para realizar la detección.

SVMs para detección de Anomalías
SVMs para detección de Anomalías

Es posible construir modelos basándose en los datos históricos. En este tipo de métodos se asume como anomalía cualquier evento que no se haya producido en el pasado. Para ello se lleva un recuento de los eventos ocurridos y se comparan con los datos históricos para intentar detectar anomalías.

Métodos no supervisados

Se dispone de anomalías en el conjunto, pero no están etiquetadas, no se conoce a priori si un dato es una anomalía o no, es decir, tanto anomalías como comportamientos legítimos están mezclados. En este campo existen también varias alternativas, las cuales se pasan a describir a continuación.

Aproximaciones gráficas

Como su nombre indica consiste en inspeccionar visualmente los datos para determinar cuales son los datos anómalos. Su principal desventaja es la cantidad de tiempo a invertir, y que es subjetivo. Para poder usar esta aproximación es necesario reducir/resumir la información a una dimensión que pueda ser visualizada (1D, 2D o 3D), y por tanto se está perdiendo información que puede resultar relevante. Una de las aproximaciones visuales más útiles es el biplot, que muestra una proyección a dos dimensiones de la varianza que aporta cada atributo. La figura 5 muestra un biplot, la longitud de los vectores para cada atributo muestra la dirección más fuerte de los datos. Si dos atributos son ortogonales significa que no están correlados, lo cual implica que ambos pueden usarse en la construcción del modelo para obtener mejores resultados. Por contra, si dos atributos van en la misma dirección y tienen similares longitudes, están correlados, o negativamente correlados si van en direcciones opuestas.

Biplot. **Var1** y **Var6** están muy poco correlacionadas, mientras que **Var1** y **Var10** sí lo están    *Créd. <https://sukhbinder.wordpress.com/2016/03/02/biplot-in-python-revisited/>*
Biplot. **Var1** y **Var6** están muy poco correlacionadas, mientras que **Var1** y **Var10** sí lo están *Créd. sukhbinder

Aproximaciones paramétricas

Estas aproximaciones asumen un modelo paramétrico describiendo la distribución de los datos y usan tests estadísticos para determinar si un punto es un outlier con un nivel de significancia. Dichos tests dependen de la distribución inherente, sus parámetros y número de outliers esperados. Entre los tests que consideran una sola variable se encuentran el test de Grubb, que considera un solo outlier, este test sufre de enmascaramiento (la media puede enmascarar outliers) , los tests de Tietjen y Moore consideran k outliers y sufren de swamping (de forma similar, la media oculta outliers). Cuando hay varias dimensiones (p dimensiones) se considera la distancia de Mahalanobis. En p dimensiones, un punto que sea considerado outlier en uno de sus atributos seguirá siéndolo aunque en cualquiera de sus atributos restantes no sea considerado outlier, o cuando sea outlier en varios de sus atributos.

El problema de los tests del párrafo anterior es que necesitan de una medida de distancia multivariante. Además, para poder calcular una matriz de covarianza de forma correcta es necesario eliminar los outliers, de lo contrario la matriz no será correcta y proporcionará información falsa.

Aproximaciones basadas en vecinos cercanos

Las aproximaciones anteriores asumen una distribución normal de los datos, pero en muchos casos la distribución no es normal, e incluso se desconoce. Si se añade el hecho de dimensiones muy altas, los datos no suelen seguir una distribución multivariante específica. Aquí hay dos formas de obtener los vecinos, mediante una función de distancia que mide la cercanía entre dos puntos o asignando una puntuación de anomalía a un punto en función de su distancia frente al resto de puntos vecinos.

Aproximaciones basadas en clustering

En esta aproximación primero se construyen los cluster mediante cualquier técnica de clustering, posteriormente se mide la distancia de un punto a su centroide para determinar si se trata de una anomalía. Se debe elegir con cuidado la medida de distancia. La distancia Euclídea no tiene en cuenta la densidad, por tanto es aconsejable usar la distancia relativa (La distancia relativa es la relación entre la distancia del punto del centroide a la distancia mediana de todos los puntos del cluster desde el centroide).

Evaluación

En detección de anomalías no basta obtener simplemente el porcentaje de acierto, es necesaria una matriz de confusión en la que se pueda observar la tasa de falsos positivos y falsos negativos. Dado que lo importante en este tipo de problema es detectar la anomalía es necesario observar el comportamiento de la precisión para detectar la anomalía. Para ello se usa la fórmula \(\frac{TP}{TP + FP}\), que indica qué porcentaje en la predicción de anomalías es correcto, siendo TP un acierto verdadero y FP un falso positivo, a más cercana de 1 esta medida mejor. Es interesante fijarse en el Recall (\(\frac{TP}{TP + FN}\)) que mide el porcentaje de anomalías detectadas, ya sean bien clasificadas o no. La proporción de falsos positivos \(\frac{FP}{FP + TN}\) mide el porcentaje de clases normales que fueron clasificadas como anomalías. Por último, la especifidad (\(\frac{TN}{TN + FP}\)) indica el porcentaje de clases normales detectadas. No es posible mejorar todas las medidas anteriores simultáneamente (Cuando aumente la precisión, el Recall va a decaer, ya que son inversos). Para atajar este problema se usa la medida \(F_1\) -Score, la cual intenta encontar un equilibrio entre Recall y precisión. Para terminar de aclarar estos conceptos, obtener una fiabilidad del \(99\%\) en una enfermedad que ocurren en una de cada \(10000\) no es fiable, ya que se equivocará una vez de cada \(1000\). Cuando se habla de anomalías que aparecen muy poco el modelo va a cometer muchos falsos positivos, la solución a este problema es usar información adicional como la probabilidad a priori de la anomalía, porcentaje de acierto y tasa de falsos positivos.

Bibliografía

Entity Framework: Code First, Database First y Model First ¿En qué consiste cada uno?

12/03/2018
Artículo original

Logo no oficial de Entity Framework Core

Entity Framework es el ORM (Object-Relational Mapper) de Microsoft, con versiones tanto para la plataforma .NET "tradicional" como para .NET Core.

Como vimos en el artículo del enlace anterior, en el que se explicaba con detalle qué es un ORM, este tipo de software puede funcionar de varias maneras diferentes a la hora de "mapear" las clases de nuestro programa orientado a objetos y las tablas en la base de datos.

Entity Framework no es una excepción, y nos ofrece diversas maneras de trabajar con los datos desde nuestros programas. Cada una tiene un enfoque diferente y es interesante para ciertos casos concretos, además de tener sus beneficios y problemas.

Vamos a dar un repaso rápido a los 3 modos de trabajo principales de Entity Framework para ver en qué consisten y sus ventajas e inconvenientes.

Nota: debes tener muy claras las diferencias entre EF6 y EF Core antes de seguir. También las diferencias y similitudes entre la plataforma .NET "tradicional" y .NET Core.

Es importante tener en cuenta que las capacidades de Entity Framework en .NET "tradicional" (EF6) y en .NET Core (EF Core) son completamente diferentes. Así, los tres modos de trabajo descritos a continuación están completamente soportados en EF6, pero EF Core solamente soporta "Code First" y muy poquito de "Database First". "Model First" en .NET Core ni está ni se le espera. A continuación lo detallaremos más.

Database First

En este modo se parte de una base de datos pre-existente con la que queremos trabajar. Es decir, tenemos la base de datos ya diseñada y probablemente con datos y lo que queremos es que EF se encargue de generar las clases necesarias y toda la "fontanería" interna para trabajar con ella.

Se suele utilizar si aprovechamos una base de datos existente y queremos crear una nueva aplicación sobre ésta. Por ejemplo, vamos a modernizar una aplicación antigua y queremos aprovechar todo lo que hay en la capa de datos, o si le añadimos una nueva API por encima a una aplicación que usa otra tecnología para el acceso a datos.

En este caso Entity Framework creará las entidades orientadas a objetos (las clases) de manera automática, y las actualizará en caso de que haya cambios en la base de datos subyacente. Para generar las entidades utiliza plantillas T4 (que son una mezcla de texto y lógica que permiten generar nuevos archivos). Si queremos una personalización especial para alguna entidad generada deberemos tocar las plantillas T4 o bien usar clases parciales.

Ventajas o beneficios de Database First

  • El trabajo en Visual Studio es muy visual. El diseñador visual muy cuidado
  • Son muy sencillas de implementar, pues casi todo va en automático y parten de la base de datos
  • Si tienes costumbre de trabajar con bases de datos, llevando a cabo primero el diseño E-R, y te sientes menos cómodo con código C#, entonces estarás como en casa.
  • Se lleva bien con proyectos de datos grandes, con muchas tablas, convenientemente repartidas en varios modelos.
  • Es muy complicado que pierdas datos al hacer modificaciones en el modelo, ya que las harás en la base de datos, no en el código de la aplicación.

Problemas o inconvenientes de Database First

  • El código resultante para los modelos tiene infinidad de código auto-generado sobre el que tenemos poco control y que puede acabar "pesando" mucho. Si hay algún problema te costará más ver de dónde te viene.
  • Si necesitas personalizar las clases o su comportamiento debes extenderlas con clases parciales o bien tocando las plantillas T4. Dependiendo de lo que quieras hacer puedes acabar escribiendo bastante código, que probablemente es lo que querías evitar usando este modelo.
  • Cada vez que haces cambios en la base de datos se debe regenerar el archivo EDMX que la representa, lo cual puede llevar bastante tiempo dependiendo de lo grande que sea. Si estás haciendo y probando muchos pequeños cambios puede llegar a desesperarte.

Database First solamente está soportado completamente en la plataforma .NET (EF6). En Entity Framework Core podemos generar las entidades y los contextos de datos utilizando una herramienta de línea de comandos, pero no disponemos de ningún diseñador ni nada que nos permita hacerlo de manea interactiva. Tampoco existen plantillas T4 para editar, ni archivos EDMX. La actual herramienta solo permite hacer la generación desde una base de datos inicial, pero si luego hay cambios sobre ésta no podremos incorporarlos al modelo. En la próxima versión 2.1 se supone que incorporarán esta posibilidad.

Model First

Este nombre puede despistarte, sobre todo si vienes del mundo MVC, en el que el "Modelo" de la "M" en su nombre, es código que escribes para modelar tus datos. En este caso se refiere a crear tu modelo de datos visualmente, usando el Diseñador de Modelos de Visual Studio. No tienes que escribir código alguno.

Modelo de la base de datos Northwind generado automáticamente

Describes visualmente el modelo de objetos que quieres crear, con las entidades, sus propiedades, relaciones entre ellas (que generan propiedades de navegación entre las entidades), etc... y luego Entity Framework se encarga de generar la base de datos subyacente o modificarla y también las entidades POCO (Plain Old C# Object, o sea, clases normales y corrientes de C#) que representan dicho modelo, usando plantillas T4.

Ventajas o beneficios de Model First

  • El diseñador visual facilita enormemente el diseño del modelo de datos.
  • Es un sistema interesante porque te evita tanto escribir código como definir la base de datos (aunque puedes generar el modelo inicial de una base de datos preexistente si quieres). Si no eres de las personas que disfrutan escribiendo código y mucho menos definiendo bases de datos, te ahorrará muchos desvelos.
  • Es muy productivo en proyectos pequeños, pues te olvidas de definir clases y de tocar bases de datos. Es lo más parecido a la "magia" que te ofrece EF.

Problemas o inconvenientes de Model First

  • Pierdes el control tanto de la base de datos como de las clases generadas. Se encarga de todo EF, lo cual es estupendo si no necesitas nada "especial", pero te quita control en otros casos.
  • Si quieres extender las clases, como antes, debes tocar las plantillas T4 o definir clases parciales.
  • Por defecto los cambios que hagas en el modelo no generan scripts SQL incrementales, sino completos. Esto quiere decir que si haces un cambio y regeneras la base de datos, se elimina la actual y se crea de nuevo. Esto puede significar que pierdas los datos que ya tuvieses en la misma, así que mucho cuidado.

Este modo de funcionamiento sólo está disponible en EF6, es decir, en la plataforma .NET "tradicional", pero no en .NET Core. Existen algunas herramientas de terceros que permiten gestionar el modelo de forma visual, tanto para EF6 como con EFCore (y otros ORM), pero no debemos confundir esto con Model First: se trata tan solo de una capa de gestión visual que por debajo trabaja con Code First (que veremos a continuación).

Code First

Si en Database First empezábamos por la base de datos generando EF todo lo demás, y en Model First estábamos en el "medio" definiendo el modelo para que EF generase tanto las clases como la base de datos... en Code First nos situamos en el otro extremo del espectro: definimos nuestras clases mediante código, y EF se encarga de generar la base de datos y todo lo necesario para encajar las clases en ellas.

Se trata de un enfoque muy orientado al programador. Es para gente a la que le gusta escribir código y tener control total sobre cómo se comportan sus clases. En este caso EF no genera código, ni necesita complejos y pesados archivos EDMX para mapear objetos a la base de datos, por lo que todo es más ágil.

El programador define su modelo usando clases normales (POCO). Relaciona unas con otras simplemente haciendo referencia entre ellas en propiedades. A mayores puede decorar algunas propiedades de estas clases de forma especial (las llamadas "Annotations", "Anotaciones" en inglés) si quiere indicar cosas concretas, como por ejemplo el nombre que quiere darle al campo correspondiente en la base de datos, y cosas así. Y puede implementar algunos métodos de la clase dbContext para indicar cómo mapear ciertas cosas con la base de datos.

Por lo demás solo es necesario usar una herramienta de "Migraciones" desde el gestor de paquetes de Visual Studio para generar la base de datos, que se ve como un mero sistema de almacenamiento sin ninguna lógica, la cual se implementa en el código de las clases que hemos creado.

Ventajas o beneficios de Code First

  • Máximo control sobre el código de tu modelo de datos en C#, ya que son clases que construyes desde cero.
  • Te ofrece control sobre las colecciones de objetos que quieres que se carguen de modo "perezoso" (es decir, a medida que se vayan necesitando).
  • No tocas una base de datos ni con un palo. El código es el que manda y el "tooling" se encarga de generar la base de datos en función de tu código.
  • La estructura de la base de datos es muy fácil de mantener bajo control de código (con Git o similar) ya que no se guarda en absoluto: se guarda el código de nuestras clases del modelo, y se genera la base de datos bajo demanda.

Problemas o inconvenientes de Code First

  • Debes dominar bastante más EF que con los enfoques anteriores.
  • Cualquier cosa que necesites persistir u obtener de tu base de datos la tienes que implementar en código C# y LINQ. La base de datos que se genera por detrás no la puedes tocar.
  • Si tu base de datos es muy grande y con muchas tablas, la gestión de la base de datos se puede convertir en un pequeño dolor de muelas.

Este es el único modo verdaderamente soportado por EF Core. Por ello es el más utilizado y en el que más hincapié se debe hacer a la hora de aprender, ya que nos servirá tanto para EF6 como para la plataforma más moderna de Microsoft.

¿Cuál escoger?

Ahora que hemos repasado las opciones, conociendo en qué consisten y sus ventajas e inconvenientes... ¿Cuál sería la mejor opción?

Bueno, si lo tuyo es .NET Core te quedas sin opciones: deberás usar Code First, sí o sí.

En el caso de EF6 y .NET "tradicional", tienes acceso a todo, por lo que para elegir, como todo en la vida, dependerá de muchos factores.

Los más puristas prefieren el enfoque de Code First frente a los demás. Les da el máximo rendimiento y control y además desde el punto de vista de un programador "puro", la base de datos es solo un mal necesario y lo importante es nuestro código. Además podrás aplicar casi todo a EF Core.

Los que dominan y valoran las bondades de las bases de datos, por el contrario, suelen preferir alguno de los anteriores, especialmente el Database First.

Si tu proyecto es pequeño y no va a tener muchas tablas/entidades que manejar, Code First puede ser muy cómodo y ágil, con control total por tu parte. Si por el contrario hay muchas tablas y el proyecto de datos es grande, Database First puede ser una gran opción aunque algún "purista" se rasgue las vestiduras.

En caso de que no te gusten demasiado las bases de datos ni tampoco tener que escribir todo el código de "fontanería" a mano, el enfoque Model First es una buena opción para los más vagos (dicho sea desde el cariño), ya que te permite diseñar visualmente las entidades/datos que quieres manejar y se encarga automáticamente de todo lo demás: generar las clases del modelo y las tablas en la base de datos, mapeándolos entre sí de manera transparente.

¡Espero que te resulte de ayuda!

FRIKADAS: Mujer con diabetes construye su propio páncreas artificial y lo hace Open Source

09/03/2018
Artículo original

Esta es una de esas historias que verdaderamente nos gusta contar, y que refleja muy bien el poder individual para crear que nos otorga la tecnología en la actualidad. Todo es cuestión de imaginación, tiempo y perseverancia. Y hablando además de mujeres en tecnología...

Dana Lewis es una universitaria de 28 años de Alabama (EEUU) que tiene diabetes de tipo 1 desde hace más de 14 años. Utilizando sus conocimientos de programación, comprando piezas por Internet, con la ayuda de su marido y con cierta asistencia desde las redes sociales, ha conseguido crear su propio "páncreas artificial" para combatir de manera automática la enfermedad. Y lo mejor: ha hecho Open Source el dispositivo y toda la información relacionada. Por este proyecto, a finales del año pasado, la revista Fast Company nombró a Dana una de las 100 personas más creativas.

El dispositivo ha sido un éxito y ya hay cientos de personas usándolo (bajo su propia responsabilidad), aparte de la propia Dana, claro.

La diabetes se produce cuando el páncreas no es capaz de producir insulina, la hormona encargada de convertir en energía la glucosa del azúcar y de los carbohidratos. Sin insulina el azúcar se aglomera en la sangre. Con demasiada insulina el azúcar puede caer a niveles peligrosos. Lo complicado para los diabéticos es permanecer en el deseado término medio. Un diabético debe tomar decisiones constantemente durante el día sobre cuestiones que impactan sobre sus niveles de azúcar (qué comer o no y cuándo, hacer más o menos ejercicio, pincharse la insulina o no, cuándo y cuánta, dormir demasiado y que pueda caer el nivel de insulina...). Esto implica ir siempre encima con una bomba de insulina y un monitor de glucosa. Medir, inyectar, corregir... Esto suena como un buen trabajo para que lo haga una máquina. Un dispositivo que pueda leer a menudo estos datos y tomar decisiones por ti o asistido por ti.

Dana empezó con un proyecto pequeño hace algo más de 4 años. Vio en las redes sociales a alguien que había encontrado la manera de extraer la información del lector de glucosa. Le escribió para pedirle si le pasaba esa información y le dijo que sí. Con esto construyó un dispositivo que leía la información de su monitor de glucosa cada 5 minutos, la enviaba  la nube y en caso de necesidad le avisaba en el móvil con una alarma. También podía avisar a algún familiar o amigo (en este caso su novio) en caso de que no se enterara (por ejemplo, le ocurrió un par de veces al estar durmiendo).

Posteriormente quisieron ir más allá. Lo siguiente fue analizar todos esos datos y tratar de predecir lo que iba a pasar. De este modo pudieron ir más allá y no solo recibir avisos cuando los niveles eran preocupantes, sino adelantarse a ello y tomar ciertas decisiones, como pulsar el botón de la insulina para inyectarse.

El siguiente paso natural sería que pulsar el botón de la bomba fuese automático si se determinaba que podría haber problemas en el futuro inmediato. Una vez más las redes sociales le ayudaron. Alguien había pensado en la manera de conectarse con la bomba de insulina y compartió con ella el procedimiento.

Con esto cerró el bucle. Ahora tenía un monitor continuo de su nivel de glucosa, un sistema que analiza los datos recibidos, saca conclusiones, envía alarmas, y que también es capaz de enviar instrucciones a una bomba de glucosa.

Los primeros prototipos los hicieron con Raspberry Pi (foto de la izquierda), pero el actual diseño, mucho más pequeño (derecha), está hecho con un chip Intel Edison. Así que el dispositivo "páncreas artificial" es cómo llevar un pequeño paquete de chicles en el bolsillo. En la foto se ve el interior (con una goma alrededor) y el exterior

El dispositivo final estuvo listo en diciembre de 2014. Una pequeña empresa y mucho menos una persona, no pueden fabricar y distribuir un dispositivo médico como este. Demasiadas regulaciones (lógicamente) y demasiado coste. Pero lanzarlo como proyecto Open Source en Internet no está sujeto a regulaciones. Así que es lo que Dana hizo en su página OpenAPS, con instrucciones, código y describiendo las herramientas necesarias para construirlo. Dana también divulga sobre diabetes, derechos de los pacientes, etc... en su otra Web, DIYPS.org que inició antes de la anterior, con los primeros pasos de su dispositivo. Es interesante echarle un vistazo. Y puedes verla explicando el proyecto en sus propias palabras en O'Reilly.

Página Anterior Página Siguiente