Quantcast
Channel: Planeta Código
Viewing all 2725 articles
Browse latest View live

Variable not found: Enlaces interesantes 386

$
0
0
Enlaces interesantes Ahí van un buen puñado de enlaces recopilados durante las semanas anteriores. Como siempre, espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

ASP.NET Core / ASP.NET

Azure / Cloud

Conceptos / Patrones / Buenas prácticas

Data

Machine learning / IA / Bots

Web / HTML / CSS / Javascript

Visual Studio / Complementos / Herramientas

Xamarin

Otros

Publicado en Variable not found.

Fixed Buffer: Azure App Configuration: Configuración centralizada de aplicaciones

$
0
0
Tiempo de lectura:8minutos
La imagen muestra el icono de Azure App Configuration

Vuelta al trabajo y vuelta al blog tras un merecido descanso navideño. Después de unas semanas de parón hoy vengo a hablaros de un servicio muy interesante para centralizar la configuración de aplicaciones. Este servicio es Azure App Configuration.

Es hora ya de dejar .Net Core 3, sus interfaces, expresiones switch y demás novedades y volver a meternos de lleno con diferentes herramientas que utilizar en nuestro día a día.

Situación

La idea de escribir sobre este servicio viene de que no hace mucho en el trabajo estuvimos comentando cual podría ser una buena manera de mantener de manera centralizada las diferentes configuraciones que tienes nuestros contenedores en kubernetes, ya que el hecho de utilizar variables de entorno obliga a reiniciar el contenedor para actualizar las variables.

Existen múltiples opciones para resolver ese problema utilizando volúmenes de persistencia para almacenar esas configuraciones, pero eso requiere de tener un volumen, lo que no siempre es posible o aceptable…

Hace cosa de un año Microsoft puso en preview el servicio Azure App Configuration que promete resolver todos los problemas de centralizar la configuración de un plumazo. La parte mala es que después de un año, sigue en preview… Por esta razón no lo estamos implementando aún. Pero no quita que sea un servicio muy interesante y por eso vamos a verlo en profundidad en esta entrada.

¿Qué es Azure App Configuration?

En primer lugar, conviene tener claro de que estamos hablando. Azure App Configuration es un servicio que nos permite tener de manera unificada y centralizada las diferentes configuraciones que tienen una o varias aplicaciones. Este servicio funciona no solo con C# y .Net, sino también con Java, Python y JavaScript.

Con esto vamos a poder resolver de manera muy sencilla situaciones donde, por ejemplo, estamos haciendo una escalabilidad horizontal. La escalabilidad horizontal consiste en tener varias instancias de nuestro servicio corriendo a la vez de modo que aumentemos la capacidad de respuesta que tiene. Un ejemplo de esto puede ser una web corriendo en varias máquinas a la vez de modo que se pueda responder a muchas más peticiones que si solo estuviese en una.

Este es un escenario tipo donde compartir la configuración es vital, ya que si tenemos el mismo servicio en paralelo, pero hay que configurarlo en cada instancia que está corriendo, podemos tener problemas porque una instancia no esté configurada igual que las demás.

Aquí es donde entra en juego Azure App Configuration. Gracias a este servicio vamos a tener concentradas en un almacén las configuraciones de modo que, al cambiarlas en ese punto, todas las instancias se enteren y actualicen sus datos. Un punto interesante es que mientras siga en preview es gratuito, por lo que te recomiendo que lo pruebes ya que es gratis y puede ser una solución a algún problema.

Crear el almacén

Para poder utilizar un almacén de Azure App Configuration vamos a tener que crear el servicio en el portal de Azure. Para esto basta con que pulsemos crear un recurso y escribamos ‘App Configuration’:

La imagen muestra el portal de Azure creando un Azure App Configuration

Tras esto le damos a crear y solo es necesario rellenar 4 campos para crear el almacén:

La imagen muestra los 4 datos que solicita para crear el almacen. Nombre del recurso, Suscripción, Grupo de recursos y localización

Con esto se inicia el proceso de creación del almacén que estará disponible en unos segundos. Una vez que esté disponible, ya podemos empezar a usarlo como almacén de configuraciones.

Lo primero será registrar las diferentes configuraciones que van a estar disponibles para las aplicaciones. Para eso dentro del servicio vamos a ir a ‘Explorador de configuración’ y después a ‘Crear’:

La imagen muestra el panel principal de Azure App Services indicados los botones `Explorador de configuración` y `Crear`

Seleccionamos clave valor (algunas traducciones de Azure son…) y ya podemos registrar la clave:

La imagen muestra la ventana de creación de claves

De este modo tan sencillo vamos a poder ir creando diferentes claves en Azure App Configuration con sus valores que van a poder ser consumidos por las diferentes aplicaciones. Para esta entrada yo he creado dos claves que luego se consumirán desde una aplicación ASP NET Core:

La imagen muestra dos claves: asp:welcomesettings:author=FixedBuffer y asp:welcomesettings:message=Hola a todos!

En caso de que tengas ficheros de configuración ya creados, es posible importarlos desde varios formatos gracias a la opción Importar/Exportar. De igual modo es posible exportarlos a varios formatos.

Obteniendo acceso de aplicaciones para Azure App Configuration

Ahora que ya está creado el almacén y tiene algunas claves creadas, es necesario tener unos datos de acceso de modo que las aplicaciones se puedan conectar con el este para leer la configuración.

Esto lo vamos a conseguir desde el menú ‘Claves de Acceso’ donde vamos a poder elegir si queremos de lectura y escritura o solo de lectura:

La imagen señala los botones 'Claves de acceso', 'Claves de lectura' y 'Copiar cadena de conexión'

Elijamos de lectura y escritura o solo lectura, lo que nos interesa es la cadena de conexión ya que es lo que vamos a necesitar en las aplicaciones para poder acceder al almacén.

Utilizando Azure App Configuration en una aplicación .Net Core

Para poder utilizar el almacén de Azure App Configuration dentro de una aplicación .Net, es preciso añadir el paquete NuGet ‘Microsoft.Extensions.Configuration.AzureAppConfiguration‘. Además, para poder buscarlo dentro de Visual Studio es necesario tener activado el check de mostrar paquetes en preview.

Una vez que esta el paquete instalado simplemente es necesario obtener el ‘IConfiguration’ de donde vamos a recuperar las configuraciones:

private static IConfiguration _configuration = null;
//...
var builder = new ConfigurationBuilder();
builder.AddAzureAppConfiguration(options =>
{
    options.Connect(connectionString)
           .ConfigureRefresh(refresh => //registramos el refresco
           {
               refresh.Register("asp:welcomesettings:author")
                      .Register("asp:welcomesettings:message")
                      .SetCacheExpiration(TimeSpan.FromSeconds(10));
           });
});
_configuration = builder.Build();
//Escribimos un mensaje accediendo a la configuración
Console.WriteLine(_configuration["asp:welcomesettings:message"]);

Con el código anterior estamos recuperando las configuraciones que haya registradas en Azure App Configuration y además le estamos indicando que queremos que ‘asp:welcomesetting:author’ y ‘asp:welcomesetting:message’ se actualicen. También estamos invalidando el tiempo de actualización por defecto que es 30 segundos para hacer que se actualice cada 10.

Con esto, simplemente sería necesario añadir el IConfiguration al inyector de dependencias si lo hubiese o mantenerlo con un acceso global para poder acceder a la configuración siempre que nos haga falta. Además, el único dato de configuración que necesita la propia aplicación es la cadena de conexión al almacén.

Utilizando Azure App Configuration en una aplicación web ASP NET Core

Aunque con lo que acabamos de ver para aplicaciones puede ser suficiente, hay otro paquete que nos permite directamente utilizar este almacén como uno de los propios de la web de modo que automáticamente podamos inyectar las configuraciones como una dependencia. Este paquete es ‘Microsoft.Azure.AppConfiguration.AspNetCore‘.

Para el ejemplo se está utilizando una aplicación ASP NET Core 3.1 MVC

Una vez instalado vamos a añadir la configuración directamente sobre el HostBuilder (en Program.cs):

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
      .ConfigureAppConfiguration((hostingContext, config) =>
      {
          config.AddAzureAppConfiguration(options =>
          {
              options.Connect(connectionString)
                   .ConfigureRefresh(refresh =>
                   {
                       refresh.Register("asp:welcomesettings:message")
                            .Register("asp:welcomesettings:author")
                            .SetCacheExpiration(TimeSpan.FromSeconds(10));
                   });
           });
       })
       .ConfigureWebHostDefaults(webBuilder =>
       {
           webBuilder.UseStartup<Startup>();
       });

Como puedes comprobar, hasta aquí es exactamente igual que hacíamos en una aplicación. La diferencia radica en que ahora vamos a crear una clase para esos settings:

public class WelcomeSettings
{
    public string Message { get; set; }
    public string Author { get; set; }
}

Y en ‘ConfigureServices’ de la clase ‘Startup’ vamos a añadir la línea para convertir la configuración en la clase:

services.Configure<WelcomeSettings>(Configuration.GetSection("asp:welcomesettings"));

Por último, dentro del método ‘Configure’ de esta misma clase vamos a añadir el middleware de Azure App Copnfiguration:

app.UseAzureAppConfiguration();

Ahora todo está listo y configurado para poder utilizar Azure App Configuration como un almacén de configuración dentro de nuestra aplicación web. Vamos a probarlo inyectando la configuración como un snapshot a HomeController y pasándoselo a una vista donde lo visualicemos:

public class HomeController : Controller
{
    private readonly WelcomeSettings _welcomeOptions;

    public HomeController( IOptionsSnapshot<WelcomeSettings> welcomeOptions)
    {
        _welcomeOptions = welcomeOptions.Value;
    }

    public IActionResult Index()
    {
        return View(_welcomeOptions);
    }
}
@model WelcomeSettings

<div class="text-center">
    <h1 class="display-4">@Model.Message</h1>
    <h2 class="display-4">By: @Model.Author</h2>
</div>'

Una vez que esta esto listo, solo nos queda probarlo. Si arrancamos la aplicación nos encontramos con algo como esto:

La imagen muestra la web con los mensajes obtenidos desde Azure App Configuration

Sin detener la aplicación vamos a editar el valor de la configuración ‘asp:welcomesettings:author’ desde el servicio haciendo click en los 3 puntos y pulsando editar:

La imagen muestra con flechas como se llega a los 3 puntos de la derecha y al botón editar

Una vez que hemos editado su valor, simplemente vamos a recargar la página de nuestra web y vamos a comprobar cómo ha cambiado el valor.

Recuerda que le hemos dado 10 segundos de tiempo de vida a la cache de la configuración, por lo que puede tardar hasta 10 segundos en actualizarse el valor que vemos.

La imagen muestra la misma web ASP NET Core que hemos creado con los valores del Azure App Configuration actualizados

Conclusión

Aunque ahora mismo el servicio de Azure App Configuration está en preview y lleva así desde hace mucho tiempo, es un servicio que funciona bien. Personalmente me gusta y lo utilizo en mis proyectos personales ya que me permite centralizar la configuración de todos mis proyectos en un único sitio de manera muy cómoda.

De igual manera me permite que cuando los contenedores que tengo desplegados sobre un AKS escalan (AKS es el servicio de Kubernetes de Azure, del que hablaremos en algún momento 🙂 ), automáticamente adopten la configuración y apliquen los cambios. Sí, sé que esto lo puedo conseguir perfectamente con volúmenes donde se persistan las configuraciones, pero gracias Azure App Configuration tengo las que pertenecen a contenedores y las que no en el mismo sitio.

No es recomendable utilizar elementos en preview si vamos a llevar algo a producción y no seré yo el que recomiende hacerlo, si alguien quiere hacerlo es bajo su cuenta y riesgo. No obstante, durante la fase de desarrollo donde las configuraciones cambian frecuentemente, sobre todo en entornos de desarrollo, es una opción a tener muy encuenta.

¿Qué opinas tú? ¿Conocías Azure App Configuration como almacén de configuraciones?

Para que puedas probar tú mismo Azure App Configuration en ambos escenarios, he subido el código a GitHub en dos ramas, application para la aplicación de consola y web para la aplicación MVC. En ambos casos tendrás que añadir las configuraciones en el servicio y reemplazar la cadena de conexión.

**La entrada Azure App Configuration: Configuración centralizada de aplicaciones se publicó primero en Fixed Buffer.**

Picando Código: [Libro] The Psycopath Test por Jon Ronson

$
0
0
Jon Ronson - The Psychopath Test

Jon Ronson – The Psychopath Test

Éste es un libro que tenía en la mira desde que leí Them: Adventures with Extremists por Jon Ronson el año pasado. El autor tiene una forma de escribir bastante entretenida, investigación periodística mezclada con ficción y humor. Además quería ver si leyendo este libro confirmaba mi teoría de que la mayoría de CEO’s y políticos del mundo son psicópatas…

Them era más “documental” y cómico, éste es más un libro de psicología donde explora ese mundo mediante la narrativa, pasando por el psicoanálisis, la industria farmacéutica y la psicopatía. Pero no deja de tener un componente periodístico. La descripción del libro hace un buen trabajo en resumirlo así que para qué reinventar la rueda:

¿Y si la sociedad no fuera fundamentalmente racional, pero estuviera motivada por la locura? Este pensamiento lleva a Jon Ronson a una aventura completamente convincente al mundo de la locura.

En el camino, Jon conoce psicópatas, aquellos cuyas vidas han sido tocadas por la locura y aquellos cuyo trabajo es diagnosticarla, incluyendo al influencial psicólogo que desarrolló el Test de la psicopatía, de quien Jon aprende el arte de la observación de psicópatas. Una habilidad que aparentemente revela que la locura podría de hecho estar en el corazón de todo…

Combinando el humor marca registrada de Jon, encanto incisión de investigación, The Psycopath Test es entretenido y honesto, desenterrando verdades peligrosas y haciendo preguntas serias sobre cómo definimos la normalidad en un mundo donde somos cada vez más juzgados por nuestros bordes más locos.

Es bastante entretenido pero obviamente no ahonda tanto en el tema desde un punto de vista científico, sino más bien opiniones y experiencias, manteniendo su estilo para entretener al lector y no ser un libro para estudiantes de psicología. Me resultó muy fácil de leer, y lo terminé en dos sesiones de lectura.

Es de esos libros que siento -al igual que me pasó con Them- me dan algunas herramientas más para entender un poco más el mundo en el que vivo. El test del que habla no es la verdad absoluta, pero es lo que se usa para diagnosticar el desorden. Entonces al aprenderlo uno se siente un poco como el autor en que puede empezar a detectar potenciales psicópatas donde antes no los veía. Y también está interesante el ejercicio de pensar en cuánto de lo que pasa en el mundo es por culpa de (o gracias a) algún psicópata.

La sociedad actual está mayormente controlada por CEO’s y políticos. ¿Todos los CEO’s son psicópatas? No, pero una buena cantidad seguro que sí. ¿Los políticos también? ¡Seguro! Por lo menos cuentan con los 3 puntos de “grandioso sentido de autoestima”, “ser mentirosos patológicos”, “ser manipuladores”, “falta de empatía”, “estilo de vida parasitario” y lo dejo ahí porque ya son 15 puntos y falta nada para calificar como psicópatas… Esto explicaría mucho, pero como podrán concluir si leen el libro, no es tan blanco y negro.

Me resultó un buen catalizador para despertar el interés en el tema y buscar más información. Particularmente me interesó y agregué a mi lista de libros por conseguir Snakes in Suits, que ahonda más en el tema pero está escrito por verdaderos psicólogos. De todas formas recomiendo The Psycopath Test por Jon Ronson, al igual que Them. Son muy entretenidos y te hacen pensar y evaluar distintas ideas, los mejores tipos de libros.

Llevo una buena racha de lectura en los últimos meses. Las vacaciones de fin de año me permitieron leer 3 libros, y desde entonces vengo tratando de mantener la costumbre. Así que con suerte en breve termino lo que estoy leyendo ahora y publico otra reseña, así mantengo en ejercicio la escritura.

Variable not found: Incluir recursos estáticos en una Biblioteca de Clases Razor (RCL)

$
0
0
ASP.NET CoreLas Razor Class Libraries (RCL) constituyen una interesante fórmula para crear componentes redistribuibles de interfaz de usuario para aplicaciones basadas en ASP.NET Core MVC o Razor Pages. En las bibliotecas de clases de este tipo podemos incluir controladores, view components, tag helpers o vistas y páginas Razor, elementos que estarán disponibles en las aplicaciones que las referencien, bien directamente o bien a través del paquete NuGet en el que las distribuyamos.

Sin embargo, es menos conocido el hecho de que estas bibliotecas pueden incluir también recursos estáticos como imágenes, hojas de estilo o scripts, lo que resulta bastante interesante a la hora de crear componentes totalmente autosuficientes y muy reutilizables.

En este post vamos a ver cómo crear una RCL redistribuible que definirá el tag helper<mario>, cuya inclusión en una página hará que ésta muestre el conocido personaje correteando por la pantalla, como se muestra en la siguiente captura:

Mario corriendo por la pantalla

1. Lo básico: creación y consumo de la Razor Class Library

Como sabemos, podemos crear RCLs utilizando Visual Studio o bien desde la línea de comandos:
dotnet new razorclasslib --support-pages-and-views
Importante: en ambos casos es fundamental añadir el soporte para páginas y vistas a la hora de crear el proyecto.
También podemos crear una biblioteca de clases tradicional, y modificar su archivo .csproj para dejarlo como el mostrado a continuación:
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
</Project>
Una vez creado el proyecto, ya podemos introducir en él los componentes que queramos distribuir en la biblioteca. En nuestro caso, iremos preparando el esqueleto del tag helper<mario>, que podría ser algo así:
public class MarioTagHelper: TagHelper
{
public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
output.SuppressOutput();
output.Content.SetHtmlContent("<p align=center>Mario will be here!</p>");
return base.ProcessAsync(context, output);
}
}
Para utilizar este componente desde una aplicación ASP.NET Core MVC, sólo tenemos que referenciar el proyecto RCL (o el paquete NuGet, si hubiéramos decidido distribuir así nuestra biblioteca) y, dado que se trata de un tag helper, registrarlo en el archivo _ViewImports.cshtml. Suponiendo que la biblioteca Razor se denomina MarioRcl, sería algo como:
...
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, MarioRcl
De esta forma, ya podríamos utilizar en nuestras páginas la etiqueta que hemos definido, por ejemplo en la vista Index.cshtml creada por defecto en proyectos MVC:
...
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web
apps with ASP.NET Core</a>.</p>
</div>
<mario></mario>
El resultado en ejecución sería el siguiente:

Tag Helper mario -solo texto- en ejecución

2. Incluir recursos estáticos

Por simplificar, en el código anterior solo hemos mostrado un texto en el lugar donde se introdujo la etiqueta <mario>, aunque en realidad lo que nos interesará es insertar un código scripts que vaya superponiendo distintas imágenes para crear la ilusión de animación.


Mario corriendo, frame 1    Mario corriendo, frame 2    Mario corriendo, frame 3

Dado que vamos a utilizar estas tres imágenes, debemos añadirlas a la carpeta wwwroot del proyecto RCL, que sabemos que es donde se almacenan por convención los recursos estáticos; un buen lugar para hacerlo, sin duda, sería en una subcarpeta llamada images en su interior.

Carpeta wwwroot del proyecto RCLPor defecto, todos los recursos presentes en la carpeta wwwroot de la RCL serán distribuidos junto con la biblioteca de clases Razor. De hecho, si probáis a publicar el proyecto ASP.NET Core MVC que referencia a la RCL, podréis observar que los recursos estáticos se encuentran en la carpeta de salida, en un directorio llamado por convención wwwroot\_content\[Ensamblado RCL].

Por ejemplo, si nuestro proyecto RCL se denomina MarioRcl, los recursos estáticos introducidos en la carpeta wwwroot de la Razor Class Library se introducirán automáticamente en la carpeta de salida wwwroot\_content\MarioRcl del proyecto web que lo utilice, como se muestra en la siguiente captura de pantalla del explorador de archivos de Windows:

Recursos estáticos de la RCL
Si hay recursos estáticos que no queremos incluir al empaquetar la RCL, podemos excluirlos explícitamente utilizando el elemento <DefaultItemExcludes> del archivo .csproj.
Y con esto, podríamos decir que la magia está hecha. El único requisito adicional a tener en cuenta es que el proyecto web deberá incluir el middleware Static Files en el pipeline, pues es la forma de asegurar el proceso de peticiones a archivos estáticos.

En este momento, si modificamos el tag helper de la siguiente forma, ya deberíamos poder ver a Mario, aún quietecito, en las páginas que utilicen el tag <mario>.
public class MarioTagHelper : TagHelper
{
private static readonly string Root =
$"/_content/{typeof(MarioTagHelper).Assembly.GetName().Name}";

public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
output.SuppressOutput();
output.Content.SetHtmlContent(GetHtml());
return base.ProcessAsync(context, output);
}

private string GetHtml() =>
$"<p align=center><img src='{Root}/images/1.png'>";
}
Tag Helper Mario en ejecución mostrando una imagen

Sólo un detalle adicional: esto os funcionará sin problema cuando publiquéis el proyecto o si lo ejecutáis desde la carpeta de salida o el IDE en el entorno Development, pero no si modificáis el entorno a Production. En este caso tendréis que añadir una configuración extra al Program.cs:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStaticWebAssets(); <-- ¡Añadir esta línea!
webBuilder.UseStartup<Startup>();
});

Punto extra: démosle vida al muñeco

Ya sabemos todo lo necesario para incluir recursos estáticos en una RCL y distribuirlos con ella, así que podríamos considerar que este último punto sobra en el post. Pero como habíamos establecido al principio, el objetivo era ver corretear a Mario por pantalla, así que démosle un último empujón.

Para conseguirlo, sólo tendremos que introducir algo de Javascript en el tag helper para que mueva el sprite y vaya alternando sus frames al mismo tiempo. Una posible implementación podría ser la siguiente:
public class MarioTagHelper : TagHelper
{
private static readonly string Root =
$"/_content/{typeof(MarioTagHelper).Assembly.GetName().Name}";

public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
output.SuppressOutput();
var id = context.UniqueId; // ID único del tag <mario> en proceso,
// generado por Razor

output.Content.SetHtmlContent(GetHtml(id));
return base.ProcessAsync(context, output);
}

private string GetHtml(string id) =>
$@"<div style='width=100%;' id='parent-{id}'>
<img id='mario-{id}' style='position: absolute; left: 0;'>
</div>
<script>
(function () {{
let frame = 0;
let parent = document.getElementById('parent-{id}');
let element = document.getElementById('mario-{id}');
let left = parseInt(element.style.left);
setInterval(function() {{
element.src = '{Root}/images/' + frame + '.png';
element.style.left = left+'px';
left=(left+10)%(parent.offsetWidth-element.offsetWidth);
frame = (frame+1) % 3;
}}, 80);
}})();
</script>";

}

¡Y eso es todo! Con esto ya tendremos a Mario correteando por la pantalla. Pero lo importante no es eso, sino que por el camino hemos aprendido a crear una RCL reutilizable con contenidos estáticos :)

Publicado en Variable not found.

Una sinfonía en C#: ¿Qué es un Webhook? o ¿Cómo lograr ser informado de eventos sin hacer pooling?

$
0
0

En ocasiones necesitamos enterarnos de cambios en otros sistema, por ejemplo, tenemos un repositorio Git en Github y queremos saber cuándo se ha hecho un cambio para hacer algo en consecuencia (como iniciar un proceso de compilación).

Haciendo pooling

La primera forma de hacerlo sería de algún modo verificar si hay cambios ( cada 1 minuto digamos), es decir, enviar una petición cada 1 minuto.

image

Esta técnica se suela llamar pooling y de hecho se utiliza en casos que aplica, pero tiene ciertos problemas:

  • App1 (y todas las aplicaciones que desean saber si hay cambios) tiene que implementar el pooling, un timer, el request, etc.)
  • Cada App lo hará a su manera, y el intervalo de verificación puede ser diferente.
  • Cada App debería implementar un modo de saber que efectivamente hay cambios (imaginemos que en lugar de Git es una API que nos dice si hay un producto disponible por ejemplo) y esto podría tener un costo alto.
  • Todas las App cliente hacen pooling al mismo server y podría generar un costo a éste e incluso “tirarlo” si se hacen muchos request por segundo.

Webhooks al rescate

Hay dos formas prinicipales para solucionar problemas en software: la primera es agregra una capa más y la segunda es invertir el flujo y éste es el caso de los Webhooks.

Un Webhook es un endpoint que ofrece el cliente (por ejemplo App1) es decir una URL que acepta peticiones, y que es llamada por la API que queremos consumir, en este caso Github

image

 

Entonces en un primer momento App1 le dice a GitHub cuál es la URL de su Webhook (y eventualmente de qué eventos quiere ser informado) y luego se queda esperando.

Github (o la API que fuera) guarda la URL del Webhook de App1 (y a la todos los clientes que quieran ser notificados) y cuando detecta cambios le informa haciendo un POST a cada URL de los clientes, adicionalmente envía información sobre el evento ocurrido.

A partir de esto App1 hace un pull de los cambios (o lo que sea).

Es decir, en lugar de nosotros como cliente que consume una API preguntar cada x tiempo si hay cambios, le decimos a la API que nos avise cuando hay cambios a través de una URL dada, cuando esto ocurre hacemos algo en consecuencia.

Probando  un Webhook con Github.

Una cosa que no está definida en un Webhook son los datos que la API (Github en este caso) nos va a enviar en el payload del POST a nuestro Webhook (la información sobre los cambios, el evento, etc.) esto es libre, cada API/Aplicación/etc. incluye la información que cree necesaria, cosa que parece lógica para dar flexibilidad y porque cada aplicación puede querer informar cosas diferentes.

Entonces, ¿cómo sabemos qué datos nos llegan a nuestro Webhook?

Evidentemante nuestro Webhook ( el endpoint que ofrecemos para ser informados de eventos en Github en este ejemplo) tiene que ser accesible desde internet (para que Github puede invocarlo, claro) y estoy puede ser un problema a la hora de desarrollarlo.

Hay herramientas que voy a recomendar para verificar esto, es un sitio web que nos permite generar una URL aleatoria (nuestro Webhook temporal) y ver todas los requests que recibe y su respectivo payload. Entonces vamos a https://webhook.site

Webhook Site

Este sitio apenas ingresamos nos genera una URL aleatoria que será nuestro Webhook, es decir, la URL por la cual, mediante un POST las API (o apps que querramos que nos informen) nos informarán.

image

Para probar cómo funciona vamos a utilizar Postman y hace un simple request.

 

image

 

Simplemente un POST a la URL que generó webhook.site y ponemos algo en el body, apretamos Send

 

image

 

Y magia! vemos nuestro request, bien, funciona,ahora vamos a hacerlo con Github, crear un Webhook sobre un repositorio.

Configurar GitHub

Para esto vamos a un repositorio, a la pestaña de setting y ahí a Webhooks (se pueden configurar a nivel usuario también)

image

image

En este caso se seleccionó la opción “send me everything” para recibir todos los eventos (es una prueba, claro)

Lo primero que va a ocurrir es que Github envían un ping a nuestro Webhook para verificar que funciona, y podemos verlo en webhook.site

 

image

Esto es buena señal (quiere decir que la configuración es correcta), entonces ahora hacemos un cambio en cualquier archivo en nuestro repositorio y recibimos el evento con la información

image

Y recibimos un nuevo POST con la información que envía Github, como dije, esta información varía con cada evento y en cada sitio, de modo que tenemos que leer la documentación o probar qué nos envía para poder leer esto dentro de nuestro Webhook.

Conclusiones:

Los Webhook son una forma excelente de recibir notificaciones de sitios web (o APIs, Repositrios, etc.) que queremos monitorizar para realizar tareas en consecuencia, además hoy por hoy casi todo el mundo los soporta.

Falta ver el soporte de autenticación y algunos detalles más pero la idea básica es ésta, espero sera de utilidad, nos leemos.

Picando Código: Nuevo diseño en MontevideoBicis.com 🚲

$
0
0

Lo que empezó con una corrección mínima de un enlace en Montevideo Bicis me llevó a hacer algunos cambios bastante grandes:

  • Migré de Bootstrap a Bulma.io, mi nuevo framework CSS preferido
    Lo que también elimina la dependencia del JavaScript completo de Bootsrap. Cambió bastante el diseño, dándole una apariencia un poco más moderna (en mi muy humilde opinión). También me restula más fácil de mantener. Como vengo usando Bulma en varios proyectos, lo tengo más fresco en la memoria para cambiar cosas.
  • Eliminé la dependencia jQuery 🙌
    En su momento fu un sitio hecho lo más rápido posible para publicarse enseguida. Y la dependencia con jQuery vino con la facilidad de desarrollo. Pero en verdad hay tan poco JavaScript en el sitio que no valía la pena incluirlo. Y hoy en día no es muy necesario, menos para sitios tan pequeños como éste.
  • Quité la imagen de fondo
    No quedaba demasiado bien de todas formas, y es un request menos en el navegador.

Todavía puede quedar alguna cosa por corregir, pero en principio creo que se ve un poco mejor, y sin duda quedó más liviano al no cargar tanto JavaScript y CSS innecesarios.

Cómo se veía antes:

Montevideo Bicis Antes

Cómo se ve ahora: MontevideoBicis.com
Si llegan a encontrar algún error o detalle, pueden dar de alta un issue en GitHub o contactarme por acá o por Twitter.

Coding Potions: Vue JS ≫ Cómo crear y emitir eventos entre componentes

$
0
0

Introducción

Anteriormente vimos qué son los props en Vue y para qué sirven. Vimos que los props sirven para pasar información desde el componente padre al componente hijo. Si no recuerdas o quieres aprender el funcionamiento de los props te dejo el enlace al artículo: Cómo crear y usar props en Vue

En el artículo de hoy vamos a ver cómo crear eventos y para qué sirven ya que son esenciales para la creación de componentes web reutilizables.

Qué son los eventos en Vue

Los eventos o events son la contraparte de los props, es decir, sirven para pasar información desde el componete hijo al padre. El ejemplo típico de uso es de cuando queremos notificar de un suceso en el componente hijo.

Por ejemplo podemos crear un componente que simplemente renderice un botón. Si queremos que este botón sea reutilizable en toda la página web lo que necesitamos es notificar al componente que usa el botón si el usuario hace clic en el enlace.

Lo bueno de los eventos es que a parte de servir para notificar, se pueden pasar datos e información desde el hijo al padre en caso de que la necesitemos.

Los props se pasan desde el componente padre al componente hijo y los eventos del hijo al padre

Cómo crear y emitir eventos

Aunque no lo creas, si has usado Vue seguramente ya hayas usado sin saberlo los eventos ya que el @submit y el @click no son más que eventos que ya vienen por defecto en Vue.

Como supondrás, la forma de recibir eventos es poniendo el @ antes del nombre del evento, pero vamos a ver cómo crear tus propios eventos desde el componente hijo.

Volvamos al ejemplo del Botón ya que es un ejemplo claro para usar eventos. La estrategia a seguir es reaccionar con el evento click de Vue para ejecutar una función que sera la encargada de enviar el evento al componente padre.

<template>
  <button @click="handleClick">{{text}}</button>
</template>
<script>
export default {
  props: {
    text: String
  },
  methods: {
    handleClick() {
      this.$emit("click");
    }
  }
}
</script>

Con la función this.$emit() emites el evento. Dentro de la función tienes que poner el nombre que le quieres dar al evento, es decir, si por ejemplo pones this.$emit("hover"); luego para usarlo tienes que llamar al evento @hover. En este ejmplo le he puesto el nombre de click para que podamos estar a la escucha del click en el botón como si se tratase del evento click que viene en Vue por defecto.

Hay otra forma de crear eventos, se trata de crearlos directamente desde la vista, sin tener que poner el this:

<template>
  <button @click="$emit('click')">{{text}}</button>
</template>

De esta forma ya no necesitas crear un método desde el que enviar el evento. Con ambas formas obtienes el mismo resultado.

Cómo estar a la escucha de eventos

Para usar el botón que acabamos de crear:

<my-button text="Botón de ejemplo" @click="handleClick"></my-button>

Recuerda importarlo dentro del componente para poder usarlo. Si hubieras llamado al evento hover por ejemplo, entonces sería:

<my-button text="Botón de ejemplo" @hover="handleClick"></my-button>

Cómo enviar datos en los eventos

Una cosa muy interesante de Vue es que permite enviar información dentro de los eventos. Puedes enviar cualquier cosa: variables, computadas, resultados de métodos, etc.

Para enviar datos tan solo tienes que añadir un parámetro más al evento:

<template>
  <button @click="handleClick">{{text}}</button>
</template>

<script>
export default {
  props: {
    text: String
  },
  data: () => ({
    example: "Hello world"
  }),
  methods: {
    handleClick() {
      this.$emit("click", this.example);
    }
  }
}
</script>

Para recoger en el componente padre la información que viene del hijo lo tienes que hacer en el método que declaras cuando declaras el evento que estás escuchando:

<template>
  <my-button text="Botón de ejemplo" @click="handleClick"></my-button>
</template>

<script>
import MyButton from "@/components/MyButton.vue";

export default {
  components: {
    MyButton
  },
  methods: {
    handleClick(info) {
      console.log("Click event on the button of the children with: " + info)
    }
  }
}
</script>

Si te fijas, en la vista HTML solo necesitas llamar al nombre del método, en otras palabras NO tienes que hacer esto:

<my-button text="Botón de ejemplo" @click="handleClick(info)"></my-button>

Conclusiones

Este artículo es muy corto porque los eventos no dan para más. Es algo muy simple de implementar y encima muy útil para la creación de los componentes si lo combinas con los props.

La única desventaja de los props y los eventos es que si por ejemplo tienes herencias más completas (hijos con más componentes hijos), tienes que pasar los props y los eventos hacia arriba y hacia abajo en la herencia, aunque ya veremos como solucionar esto con el store de Vue.

Blog Bitix: Los permisos del sistema de archivos de GNU/Linux

$
0
0

El sistema de permisos de GNU/Linux por defecto es menos capaz que el de Windows basado en listas de control o ACLs pero es más sencillo y suficiente para muchos casos y usuarios. Cada archivo o directorio tiene unos bits de control que determinan los permisos de lectura, escritura y ejecución para el propietario, grupo y el resto de usuarios. Los comandos ls, chmod y chown permiten listar los permisos de los archivos y cambiarlos.

GNU

Linux

En un sistema multiprogramado como son cualquiera de los actuales modernos que son utilizados por varios usuarios y programas es necesario que tengan algún mecanismo de seguridad y permisos para proteger los recursos. En el caso del sistema de archivos GNU/Linux usa un sistema simple pero suficiente para una buena parte de casos de uso.

En GNU/Linux los permisos de cada archivo se dividen en lectura, escritura y ejecución, identificados por las letras rwx respectivamente, para el propietario del archivo, el grupo de usuarios al que pertenece y para el resto de usuarios, identificados estos grupos con las letras ugo respectivamente. Para saber si se posee el permiso de lectura, escritura y ejecución se utiliza un bit para cada uno de ellos. Para el conjunto de usuario, grupo y resto de usuarios en total se utilizan 9 bits. Estos 9 bits forman la cadena rwxrwxrwx que para escribirlos de forma numérica y más simple se pueden utilizar base octal, por ejemplo 744 se traduce a binario en 111100100 significando que el usuario tiene permisos para leer, escribir y ejecutar el archivo, dados los tres primeros bits, y el grupo de usuario y resto de usuarios solo tienen el permiso de lectura.

Con el comando para listar el contenido de un directorio ls -lha se muestra el listado en formato largo con la opción -l que incluye los permisos, las unidades de tamaño en formato legible para humanos con la opción -h, con la opción -a incluye los archivos ocultos que son los que empiezan por . y con la opción --group-directories-first los directorios primero.

En los listados del comando ls el primer caracter indica si el archivo es un archivo regular o un directorio que se identifican por la letra d como el directorio Descargas, si fuese una l indicaría que es un enlace como el enlace .steampath. El propietario de los archivos es mi usuario picodotdev, salvo en el caso del directorio superior referenciado con .. que es el superusuario root.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$ ls -lha --group-directories-first
total 376K
drwx------ 39 picodotdev picodotdev 4,0K ene 15 22:27 .
drwxr-xr-x  3 root       root       4,0K nov 28  2018 ..
drwx------ 48 picodotdev picodotdev 4,0K ene 13 19:22 .cache
drwx------ 45 picodotdev picodotdev 4,0K ene 13 23:49 .config
drwxr-xr-x  2 picodotdev picodotdev 4,0K ene  6 01:57 Descargas
drwxr-xr-x  3 picodotdev picodotdev 4,0K sep 25 23:00 Documentos
drwxr-xr-x  2 picodotdev picodotdev 4,0K dic 19  2018 Escritorio
drwxr-xr-x  2 picodotdev picodotdev 4,0K mar 18  2019 Grabaciones
drwxr-xr-x  8 picodotdev picodotdev 4,0K abr 18  2019 .gradle
drwxr-xr-x  2 picodotdev picodotdev 4,0K dic 29  2018 Imágenes
drwxr-xr-x  4 picodotdev picodotdev 4,0K nov 29  2018 .java
drwx------  3 picodotdev picodotdev 4,0K nov 28  2018 .local
drwxr-xr-x  4 picodotdev picodotdev 4,0K feb 22  2019 .m2
drwx------  5 picodotdev picodotdev 4,0K nov 28  2018 .mozilla
drwxr-xr-x  2 picodotdev picodotdev 4,0K dic 20  2018 Música
drwxr-xr-x  2 picodotdev picodotdev 4,0K nov 28  2018 Plantillas
drwxr-xr-x  2 picodotdev picodotdev 4,0K nov 28  2018 Público
drwxr-xr-x  5 picodotdev picodotdev 4,0K ene 11 00:58 Software
drwx------  2 picodotdev picodotdev 4,0K may  3  2019 .ssh
drwxr-xr-x  2 picodotdev picodotdev 4,0K sep 24 23:20 .steam
drwxr-xr-x  2 picodotdev picodotdev 4,0K nov 30  2018 Vídeos
drwxr-xr-x  2 picodotdev picodotdev 4,0K feb  1  2019 .vim
-rw-------  1 picodotdev picodotdev 8,9K ene 15 22:27 .bash_history
-rw-r--r--  1 picodotdev picodotdev   21 jun  4  2018 .bash_logout
-rw-r--r--  1 picodotdev picodotdev   57 jun  4  2018 .bash_profile
-rw-r--r--  1 picodotdev picodotdev  541 nov 28 22:14 .bashrc
-rw-r--r--  1 picodotdev picodotdev   73 dic  1  2018 .gitconfig
-rw-r--r--  1 picodotdev picodotdev  16K dic  1  2018 .git-prompt.sh
lrwxrwxrwx  1 picodotdev picodotdev   35 sep 24 23:19 .steampath -> /home/picodotdev/.steam/sdk32/steam
lrwxrwxrwx  1 picodotdev picodotdev   33 sep 24 23:19 .steampid -> /home/picodotdev/.steam/steam.pid
ls.sh

Para cambiar los permisos de un archivo se utiliza el comando chmod pudiendo utilizarse de varias formas. El primer caso establece todos los bits dando permisos de lectura, escritura y ejecución al usuario propietario de archivo, y de lectura para los usuarios del grupo y para el resto de usuarios. El segundo caso da permisos de lectura al usuario en el archivo indicado. El tercer caso quita los permisos de escritura al resto de usuarios. El cuarto caso da permisos de ejecución a todos, al propietario del archivo, a los usuarios de su grupo y al resto de usuarios.

1
2
3
4
$ chmod 644 README.md
$ chmod r+u README.md
$ chmod r-o README.md
$ chmod x-a README.md
chmod.sh

El comando chown permite cambiar el propietario del archivo. En este caso se establece como propietario del archivo el usuario root.

1
2
$ chmod root README.md
$ chmod root:root README.md
chown.sh

En el caso de los directorios tener el permiso de lectura significa poder listar el contenido del directorio (ls), el permiso de escritura poder crear archivos, renombrar y eliminar archivos (por ejemplo con touch, mkdir) y el de ejecución en un directorio otorga acceso al contenido de los archivos (se concede dependiendo de los propios permisos del archivo).

En el permiso de ejecución en vez de una x puede aparecer una s en en los permisos de grupos de usuario y grupo y significa que al ejecutar el archivo en vez de tomar como usuario de ejecución el del usuario o grupo del usuario que lo ejecuta se toma el usuario y grupo del archivo, estos son los setuid y setgid. Si en en el bit de ejecución del grupo otros aparece una t indica que el directorio es sticky y solo el dueño del directorio o el usuario root pueden renombrar o eliminar archivos.

  • r: lectura.
  • w: escritura.
  • x: ejecución.
  • u: usuario.
  • g: grupo.
  • o: otros.
  • a: todos (usuario, grupo y otros).
  • +: añadir permisos.
  • -: quitar permisos.
  • d: directorio.
  • l: enlace simbólico.
  • s: setuid y setgid.
  • t: sticky.

Estos son algunos ejemplos de permisos en directorios.

El usuario archie tiene acceso al directorio Documents. Puede listar, crear archivos, renombrar y eliminar cualquier archivo en Documents independientemente de los permisos de esos archivos. Su posibilidad de acceder al contenido de los archivos dependen de los permisos del archivo.

1
drwx------ 6 archie users  4096 Jul  5 17:37 Documents
permissions-1.sh

En este caso sin el permiso de lectura en el directorio archie tiene acceso completo pero no puede crear, renombrar ni eliminar archivos. Puede listar los archivos y acceder al contenido de los archivos si los permisos de ese archivo lo permiten.

1
dr-x------ 6 archie users  4096 Jul  5 17:37 Documents
permissions-2.sh

archie no puede listar los archivos del directorio pero si conocer el nombre de un archivo existente puede listarlo, renombrarlo, eliminarlo y acceder a su contenido (si los permisos del archivo lo permiten). También puede creer nuevos archivos.

1
d-wx------ 6 archie users  4096 Jul  5 17:37 Documents
permissions-3.sh

archie solo es capaz de acceder a los archivos que conoce (si los permisos de ese archivo lo permiten). No puede listar archivos existentes ni crear, renombrar o eliminar ninguno de ellos.

1
d--x------ 6 archie users  4096 Jul  5 17:37 Documents
permissions-4.sh

Debe tenerse en cuenta que los anteriores son permisos sobre directorios y son independientes de los permisos de los archivos individuales. Cuando se crea un nuevo archivo es el directorio el que cambia, este es el por qué se necesitan permisos en el directorio.

Otro ejemplo, en este caso para un archivo, no un directorio. La primera letra no es una d sino un -, con lo que foobar es un archivo, no un directorio. Los permisos del propietario son rw- de modo que el propietario (archie) tiene la capacidad de leer y escribir pero no de ejecutarlo. El permiso de ejecución no es necesario si los archivos son de texto o datos. Los permisos de grupo son r--, de modo que el grupo tiene la habilidad de leer el archivo pero no de escribir en él de ninguna forma, esencialmente es un archivo de solo lectura para el grupo. Los permisos para el grupo de otros es el mismo.

1
-rw-r--r-- 1 archie users  5120 Jun 27 08:28 foobar
permissions-5.sh

Otro esquema más flexible pero más complejo son las listas de control de acceso o ACL. Las ACL permiten dar permisos a cualquier usuario o grupo para cualquier archivo.

En la wiki de Arch Linux sobre permisos de archivo y atributos se explica detalladamente y con ejemplos el sistema de permisos en GNU/Linux.


Navegapolis: La empresa consciente

$
0
0

la empresa consciente icoAlgunas perlas del libro La empresa consciente de Fredy Kofman.

 

"Yo utilizo siete cualidades para distinguir a los empleados conscientes de los inconscientes.

Las primeras tres son atributos de la personalidad: responsabilidad incondicional, integridad esencial y humildad ontológica. Las tres siguientes son habilidades interpersonales: comunicación auténtica, negociación constructiva y coordinación impecable. La séptima cualidad es la condición que hace posibles a las seis anteriores: maestría emocional.

Comprender en qué consisten estas cualidades es algo sencillo, pero es difícil ponerlas en práctica. Parecen naturales, pero desafían supuestos profundamente arraigados acerca de nosotros mismos, de otras personas y del mundo. Por este motivo, aun cuando generalmente las conocemos, no sabemos cómo implementarlas. Son cuestión de sentido común, pero no de práctica común.

Los empleados conscientes asumen responsablemente su vida. No comprometen valores humanos para lograr el éxito material. Dicen su verdad y escuchan las verdades de los demás con honestidad y respeto. Buscan soluciones creativas a los desacuerdos y honran de manera impecable sus responsabilidades. Se conectan con sus emociones y las expresan productivamente.

Los empleados inconscientes hacen lo opuesto. Culpan a otros por sus problemas, buscan gratificación inmediata olvidando la ética, y proclaman tener siempre la razón."

 

Variable not found: Enlaces interesantes 387

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

Por si te lo perdiste...

.NET Core / .NET

ASP.NET Core / ASP.NET

Azure / Cloud

Conceptos / Patrones / Buenas prácticas

Data

Machine learning / IA / Bots

Web / HTML / CSS / Javascript

Visual Studio / Complementos / Herramientas

Xamarin / Mobile

Mobile Blazor Bindings architecture

Otros

Publicado en Variable not found.

Variable not found: ¿Qué es Blazor, eso de lo que todo el mundo habla?

$
0
0
Blazor Recuerdo que la primera vez que, en una de mis visitas a Redmond, vi a Steve Sanderson haciendo una demo de Blazor "en vivo" me pareció casi magia: una aplicación web cuya lógica de presentación y UI se implementaba exclusivamente en C#, eliminando por completo de la ecuación a Javascript. ¡Uau!

En aquellos tiempos era aún poco más que un prototipo y no se podía saber si aquella línea de investigación llevaría a alguna parte, pero era tan prometedor que, algún tiempo después, a primeros de 2018, Blazor pasó a ser un proyecto experimental del equipo ASP.NET de Microsoft.

A partir de ese momento se fueron despejando las incógnitas que quedaban en cuanto a la viabilidad real de convertir aquello en un producto y se continuaron implementando funcionalidades, hasta que, en abril de 2019, Daniel Roth anunció que daban por concluida la fase experimental y Blazor entraba oficialmente a formar parte del stack de tecnologías para la web.

A día de hoy, Blazor es un framework completo para el desarrollo de aplicaciones web SPA, como lo pueden ser Angular, React o Vue. Dispone de sistema de bindings, routing, componentes, ciclo de vida, validaciones, plantillas, gestión de errores, inyección de dependencias, etc. Todo lo que podemos necesitar para crear aplicaciones web de calidad.

La primera versión de Blazor se lanzó acompañando a .NET Core 3.0 en Septiembre de 2019, aunque sólo en uno de sus modelos de hospedado: el denominado server-side o Blazor Server.

Pero no era ese el único plan...

Los "sabores" de Blazor: client-side, server-side... y otros

Inicialmente, la idea de Blazor era conseguir ejecutar el código C# en el browser llevando a éste una versión deducida del runtime de .NET. Este enfoque suele conocerse como Blazor WebAssembly o client-side, pues se basa en llevar físicamente al browser la ejecución de la parte cliente de la aplicación web.

WebAssemblyLa clave del funcionamiento de Blazor client-side es un runtime de .NET que corre sobre WebAssembly (WASM), una especificación abierta que define un "lenguaje ensamblador" común a todas las máquinas virtuales presentes en los navegadores modernos (y pollyfillable para los anteriores). Sobre ese runtime, ya en el lado cliente, es donde corren nuestras aplicaciones Blazor cuando elegimos este modelo de hospedaje.

Así, la primera vez que un usuario accede a una aplicación Blazor WebAssembly, su navegador descarga tanto el runtime de .NET como los ensamblados propios de la aplicación (compilados desde C# en tiempo de desarrollo) y sus dependencias. Ya tras esta descarga inicial, que gracias al caché de los navegadores se realizaría sólo una vez, los ensamblados de la aplicación serían ejecutados por el runtime directamente desde el navegador.

Un detalle importante a tener en cuenta es que el hecho de que el código cliente de nuestras aplicaciones lo desarrollemos usando .NET no significa que estemos llevando al cliente todo el potencial de esta plataforma. Dado que este código se ejecuta en cliente, al igual que cuando programamos con Javascript, estamos limitados por el sandbox proporcionado por el navegador para la ejecución segura de aplicaciones. Es decir, no podremos acceder a dispositivos o recursos locales más allá de los permitidos por las APIs estándar de los navegadores.

Por otra parte, como la ejecución se realiza puramente en cliente, no sería estrictamente necesario disponer de un servidor ASP.NET, IIS ni nada parecido. Tanto el runtime como los ensamblados resultantes de la compilación podrían ser distribuidos en un CDN, y es lo único que se necesitaría para poner en marcha la aplicación (bueno, a no ser que ésta necesite de un backend, claro.)

¿Y qué ventajas tiene esto? Pues bueno, ya el simple hecho de sustituir Javascript por C# para implementar el lado cliente puede aportarnos ventajas interesantes. Aparte de que C# es un lenguaje muy superior, también será posible utilizar o reutilizar bibliotecas .NET existentes, compartir código entre cliente y servidor, o utilizar entornos tan potentes como Visual Studio durante la fase de desarrollo.

Pero como siempre ocurre, no es la panacea; también provocará que la carga inicial de la aplicación sea más lenta (aunque, como decíamos, la caché podrá ayudarnos con esto), o requerirá que los clientes sean compatibles con WASM (aunque esto ya no es un problema en la mayoría de los casos).
Y bueno, de alguna forma nos alejaremos del ecosistema Javascript, que ya sabemos que es enorme, aunque también es cierto que desde Blazor es posible interoperar con bibliotecas JS existentes.
En la actualidad, Blazor WebAssembly sólo está disponible en preview, y está previsto lanzar la primera versión oficial en mayo de 2020 (aunque ésta aún no será LTS).
Como comentaba algo más arriba, el enfoque client-side de Blazor fue el origen del proyecto y sigue siendo el objetivo principal del mismo. Sin embargo, durante la fase de desarrollo aparecieron otros escenarios de uso de Blazor que podrían resultar interesantes y entraron a formar parte del Roadmap del producto, modificando los planes iniciales:

Blazor Roadmap

En la ilustración anterior podemos observar que el Roadmap posicionó Blazor Server como el primer hito del conjunto de tecnologías Blazor. De hecho, es el único framework del que tenemos a día de hoy una versión estable, production ready y con soporte a largo plazo.

Blazor Server parte del mismo objetivo que Blazor WebAssembly respecto a utilizar C# para la implementación de la lógica de presentación, aunque el enfoque que sigue es bastante diferente. En este caso no se trata de llevar todo al cliente sino al contrario: hacer que todo se ejecute en el servidor, comunicándose con el browser mediante una conexión persistente de SignalR:

Blazor WebAssembly vs Blazor Server

Para conseguirlo, el servidor mantiene en memoria una representación del estado de la página, que es modificada por mensajes SignalR que son enviados cuando se producen cambios o interacciones en la interfaz de usuario.

Por ejemplo, si un usuario pulsa un botón en la página, el evento "click" no es procesado en cliente sino enviado a través de la conexión SignalR al servidor, que ejecutará el handler oportuno (escrito en C#). Los cambios realizados en el UI desde dicho handler son enviados de vuelta al cliente, que actualizará el DOM de forma automática.
Pues sí, en cierto modo es muy similar a lo que utilizábamos en Web Forms años atrás, pero eliminando la pesadez del postback, la carga de página completa y el mantenimiento del estado mediante el célebre viewstate. De hecho, Blazor Server es la tecnología propuesta por Microsoft para sustituir a Web Forms, al promover un tipo de desarrollo conceptualmente muy parecido.
Como siempre ocurre, la idea tiene sus ventajas e inconvenientes. Como parte positiva respecto al modelo client-side, en este caso la carga inicial sería más rápida porque no hay nada que descargar desde el cliente. También, dado que el código se ejecutaría en el servidor, podríamos utilizar todo tipo de bibliotecas y componentes para .NET, así como las herramientas habituales de desarrollo y depuración. Y para casos de necesidad, este enfoque conseguiría casi el soporte universal por parte de los browsers, pues no requiere ninguna característica especial en el lado cliente.

Pero ah, amigos, todo esto no es gratis. El hecho de que cada interacción o evento en el UI deba ser enviado y procesado en el servidor añade una latencia que no todas las aplicaciones podrán soportar sin destrozar su usabilidad. Además, las conexiones concurrentes y el mantenimiento del estado en memoria podrían limitar las opciones de escalabilidad de los sistemas.

La buena noticia es que el modelo de componentes, y por tanto la forma de desarrollar, es la misma. De esta forma, podríamos iniciar un proyecto utilizando Blazor Server y migrar a Blazor WebAssembly más adelante con relativamente poco esfuerzo. Bueno, o al menos en teoría ;)

Pero aparte de Blazor Server y Blazor WebAssemby, y como veíamos en el Roadmap algo más arriba, el resto de tecnologías Blazor van acercándose consecutivamente a la ejecución nativa de aplicaciones, tanto desde dispositivos móviles como de escritorio:
  • Blazor PWA, para la construcción de Progressive Web Applications (PWA), webs que proporcionan una experiencia más cercana a las aplicaciones nativas al ser capaces de trabajar offline, recibir notificaciones push, o ser instaladas en los equipos de los usuarios. Sin embargo, la ejecución se realizará siempre sobre el sandbox proporcionado por el browser, por lo que tendremos las mismas limitaciones que si utilizáramos JS.
     
  • Blazor Hybrid, aplicaciones que correrán sobre Electron y renderizarán su UI utilizando tecnologías web sobre WebViews o motores de renderizado de webs. Dado que serán aplicaciones .NET puras, en este caso sí se podrá acceder a todos los recursos del equipo donde se instalen.
     
  • Blazor Native, que permitirá en el futuro utilizar el mismo modelo de programación para crear aplicaciones nativas puras, capaces de renderizarse utilizando componentes nativos de la plataforma de ejecución, fuera del mundo web. En la práctica, quiere decir que podríamos utilizar esta tecnología en lugar de Xamarin o React Native para implementar nuestras aplicaciones nativas.
Aunque muy sujeto a cambios, pero está previsto lanzar previews de PWA e Hybrid a finales de 2020, acompañando a .NET 5. La última referencia que he encontrado de Blazor Native es que está en fase experimental y, por tanto, no existen aún previsiones de disponibilidad.

Solución usando Mobile Blazor BindingsAparte, hace apenas un par de días han anunciado otro giro de tuerca: Mobile Blazor Binding. Este proyecto, aún en fase experimental, permite utilizar el modelo de programación de Blazor y la sintaxis Razor para la construcción de aplicaciones nativas Android e iOS, en la práctica algo así como un híbrido entre Blazor y Xamarin. El objetivo es acercar al mundo de las apps nativas a esa gran masa de desarrolladores web acostumbrados a Razor, y la verdad es que tiene bastante buena pinta.

Esto promete, ¿eh? 😉

¿Cómo se desarrolla con Blazor?

Por si no os lo habéis preguntado, el nombre Blazor procede de la unión de "Browser" y "Razor" (la "L" no sé de dónde sale, supongo que dará más musicalidad al resultado :-P), así que ya podéis intuir por dónde van los tiros: Razor que se ejecuta en el navegador.

De hecho, los componentes y páginas Blazor se implementan utilizando sintaxis Razor, que muchos ya conocéis de otras películas como ASP.NET Core MVC o Razor Pages, aunque con algunos cambios. Por ejemplo, en Blazor las páginas o componentes se implementan en archivos .razor, a diferencia de los clásicos .cshtml de MVC o Razor Pages.

Pero como las cosas se suelen entender mejor con código, mejor que echéis primero un vistazo al siguiente archivo Sum.razor:
@page "/sum"

<h1>Calculator</h1>
<div>
<input type="number" @bind-value="@A" />
+
<input type="number" @bind-value="@B" />
<button @onclick="Calculate">Calculate</button>
</div>
@if (Result != null)
{
<div>
The sum of @A and @B is @Result
</div>
}

@code {
public int? A { get; set; }
public int? B { get; set; }
public int? Result { get; set; }

void Calculate()
{
Result = A + B;
}
}
Calculadora BlazorEchando un vistazo puede entenderse que se trata de una simple calculadora para realizar sumas que incluye un par de tags <input> para solicitar los sumandos y un botón para realizar el cálculo. Al pulsarlo, se muestra el resultado de la suma en un <div> que inicialmente no está visible.

Este bloque de código es suficiente para entender la magia de Blazor:
  • En el bloque @code, implementado por completo en C#, definimos todas las propiedades y métodos que necesitemos para implementar la lógica de nuestra página. En este caso, tenemos un par de propiedades para los sumandos, otra para el resultado, y un método que realiza el cálculo.
    @code {
    public int? A { get; set; }
    public int? B { get; set; }
    public int? Result { get; set; }

    void Calculate()
    {
    Result = A + B;
    }
    }
  • Utilizamos bindings sobre los controles HTML, muy al estilo de otros frameworks basados en MVVM, como Angular o React. En el ejemplo podemos ver que bindeamos el valor de los <input> a las propiedades definidas en el bloque @code, de la misma forma que establecemos el manejador del evento click al método Calculate().
    <input type="number" @bind-value="@A" />
    +
    <input type="number" @bind-value="@B" />
    <button @onclick="Calculate">Calculate</button>
  • Dado que usamos sintaxis Razor, es posible utilizar los habituales bloques de control de flujo como @if, @foreach, etc. En el caso anterior, usamos un condicional para añadir a la página el <div> con el resultado, pero sólo cuando hemos calculado la suma.
    @if (Result != null)
    {
    <div>
    The sum of @A and @B is @Result
    </div>
    }
Fijaos que hemos eliminado de un plumazo a Javascript, y la página funcionará sin cambiar de página, muy al estilo SPA:
  • Si hemos optado por utilizar el host Blazor Server, todos los eventos e interacciones sobre el UI (cambios de valores en controles bindeados, clicks, etc.) serán enviados al servidor a través de la conexión SignalR establecida automáticamente. El servidor ejecutará el código y enviará de vuelta al cliente, usando la misma conexión, las modificaciones a realizar en el DOM para actualizar la interfaz de usuario.

  • En cambio, si hemos optado por utilizar Blazor WebAssembly, la página será compilada y el ensamblado resultante será enviado al cliente, quien lo ejecutará sobre el runtime basado en WebAssembly. Por tanto, la ejecución de la página se realizará totalmente en cliente, como si la hubiéramos implementado totalmente Javascript, sin necesidad de interactuar con el servidor en ningún momento.
Y lo interesante es que en ambos casos nuestro código será el mismo. Es decir, la página Sum.razor será la misma para cualquiera de los modelos de ejecución de Blazor, por lo que podríamos crear nuestras aplicaciones e ir evolucionando posteriormente de un modelo a otro. Por ejemplo, a día de hoy sólo podríamos poner aplicaciones Blazor en producción usando Blazor Server, pero en unos meses podríamos pasar al modelo WebAssembly cuando esté disponible, realizando pocos cambios.

Pero no sólo eso, la idea también aplica para el resto de "sabores" de Blazor, como PWA, Hybrid o Native: lo único que cambiará es el "empaquetado" y, en algunos casos, el proceso interno de renderizado, pero nuestro código seguirá siendo principalmente el mismo... o al menos, estas son las intenciones iniciales; conforme avancen estos proyectos iremos viendo hasta qué punto es así.

En definitiva, Blazor es un framework del que seguro vamos a oír hablar bastante durante los próximos meses, y no sin razón. Aunque aún está empezando a rodar y quedan bastantes cosas por pulir, es conveniente no perderlo de vista porque realmente las expectativas están muy altas :)

Publicado en Variable not found.

Blog Bitix: Conferencia BilboStack 2020

$
0
0

BilboStack 2020

Se cumple la 9º edición de la conferencia del ámbito de proyectos de tecnología que una vez más ha sido hospeda en el palacio Euskalduna. Como anteriores ediciones en un formato de dos tracks simultáneos y cuatro presentaciones en cada uno, en una única mañana pero que se alarga durante la tarde con el networking y los pintxos, y da a tiempo a visitar la ciudad si se viene de viaje.

Las entradas fueron lanzadas en varias oleadas que en las primeras se agotaron en pocos minutos, incluso literalmente en unos segundos. Adquirir una entrada en la oleada final ya fue más sencillo. Al igual que el año anterior el precio ha sido muy reducido de 13,5€.

Si otros años destacaba el desarrollo web, este año ha habido alguna presentación sobre la materia, este año ha habido algunas sobre varios de los temas que son tendencia en el desarrollo, devops junto con sus asuntos relacionados de monitorización y microservicios. Estas fueron principalmente a las que asistí como resumo más adelante.

Palacio EuskaldunaPalacio EuskaldunaPalacio Euskalduna

Palacio Euskalduna

Distribuidos por el recinto había varios photocalls en los que hacerse una foto.

PhotocallsPhotocallsPhotocalls

Photocalls

Este año la acreditación ha sido un detalle que esté hecha de algodón reciclado que incluye semillas, se puede plantar, regar y ver que es lo que surge pasado unas semanas. También ha habido una zona amplia para los patrocinadores en los que ubicar sus stands, una oportunidad para conocerlos como posibles futuras oportunidades laborales, recoger varios obsequios que ofrecían y participar en algún sorteo en el tiempo de descanso entre las os primeras conferencias y las dos siguientes últimas.

AcreditaciónAcreditaciónAcreditación

Acreditación

Dado que los tracks son simultáneos y las charlas no se graban hay que elegir a que presentaciones nos resultan más atractivas, no siempre es fácil elegir y descartar la opción a la que no asistir.

BilboStack hashtag

BilboStack hashtag
HoraSala OE
09:00-09:20Presentación
09:30-10:20DevOps: el camino de la entrega de valor en software por Luis Fraile Hernández
10:30-11:20Monitorización con Prometheus por Laura Morillo-Velarde Rodríguez y Beatriz Martínez
11:30-12:00Networking + Café
12:00-12:50¿Cómo de real puede llegar a ser la inteligencia artificial? por Eduardo Matallanas
13:00-13:50Otra charla sobre microservicios por Isabel Garrido Cardenas y Sergi González
> 14:00Networking + pintxos y poteo
HoraSala OD
09:00-09:20Presentación
09:30-10:20Unos estáticos muy dinámicos por Joan León
10:30-11:20El poder de las restricciones por Silvia Calvet
11:30-12:00Networking + Café
12:00-12:50Implementing corporate Design Systems in React por Ignacio Velázquez
13:00-13:50Compassionate Hiring por Berta Devant Pintado
> 14:00Networking + pintxos y poteo

Cartel

Cartel

De las presentaciones a las que asistí recojo las ideas principales que he apuntado, es muy posible que haya alguna omisión importante y no les hagan justicia al nivel de las presentaciones pero hago mi esfuerzo para una año más cumplir con el resumen de este año y que de esta forma quede recogido en el artículo sobre lo que versó estas presentaciones.

Presentación

La jornada al igual que el año anterior ha empezado con una presentación sobre la conferencia y los agradecimientos a los patrocinadores por su apoyo asi como unos comentarios de un miembro de Lan Ekintza, agencia el sector público del Ayuntamiento de Bilbao para el desarrollo local, sobre sus motivos de la importancia para la ciudad de eventos como este que ya tienen muchos años de constancia y el interés para empresas importantes que cotizan en bolsa ya existentes con sede en Bilbao y para otras que en un futuro se establezcan en el nuevo Zorrozaurre como nuevo polo empresarial, en estos momentos está en una fase de construcción con algunas obras importantes ya realizadas con la apertura del canal y otras obras que ya se están acometiendo.

BilboStack 2020BilboStack 2020

BilboStack 2020

DevOps: el camino de la entrega de valor en software por Luis Fraile Hernández

La cultura o método de devops incluye personas, procesos y productos con el objetivo de habilitar la entrega de valor al negocio y a sus usuarios, rápida y constante resolviendo problemas y no creando otros. Incluye ámbitos como el desarrollo, despliegue, monitorización y operación, requiere planificación. No basta con entregar de cualquier forma, ha de funcionar y tener calidad, en pequeños entregables los defectos se pueden descubrir y validar hipótesis antes y más rápido.

Hay varias estrategias de despliegue:

  • blue-green: se despliegan en un entorno nuevo sin eliminar el antiguo.
  • rolling updates: se despliega de forma progresiva entre todas las instancias de servicio.
  • feature togles: la nueva funcionalidad se activa o desactiva mediante una condición.
  • Es posible emplear varias de las anteriores a la vez ya que no son exclusivas.

Estos despliegues progresivos son aplicables al código, requieren también despliegues progresivos en las base de datos empleando los pasos Expand, Migrate, Contract. Un caso es crear una nueva columna, copiar los datos a ella, mantener la versión antigua y nueva y finalmente completada la migración eliminar la columna antigua. Las migraciónes pogresivas también son aplicables a las APIs.

La monitorización permite conocer si una funcionalidad se está utilizando y obtener información del funcionamiento interno de la aplicación. La infraestructura se puede convertir en inmutable con tecnologías como contenedores como Docker y Kubernetes y tratar como código con tecnologías como Terraform. La gestión del código puede ser usando git flow o trunk based y con un único repositorio que incluya todo para tratarlo como el entregable.

DevOps: el camino de la entrega de valor en software _por Luis Fraile Hernández_

DevOps: el camino de la entrega de valor en software por Luis Fraile Hernández

Monitorización con Prometheus por Laura Morillo-Velarde Rodríguez y Beatriz Martínez

La herramienta de monitorización Prometheus se está convirtiendo en un estándar, muchas herramientas incluyen exportan métricas en formato prometheus, unas de forma nativa y otras mediante adaptadores. OpenMetrics trata de crear un estándar para la transmisión de métricas en representación en formato de texto y con Protocol Buffers.

La monitorización de caja negra analiza elementos externos del servicio como tiempo de respuesta, carga de CPU, memoria. La monitorización de caja blanca expone métricas propias de la aplicación. Al analizar las métricas hay que definir unos valores umbrales considerados como el funcionamiento correcto, de las métricas se extraen tendencias conociendo si es incremental o decremental, también se extraen correlaciones un fallo B puede estar causando por un fallo A. En el caso de una API para evaluar el estado de una API se pueden definir umbrales para las métricas de request rate, error rate y duration response time.

Las métricas de aplicación requieren instrumentalizar la aplicación para exponer los valores de los cuales es posible extraer información con valor para negocio. Hay cuatro tipos de métricas:

  • Counter: valor que se incrementa o reinicializa pero no se decrementa.
  • Gauge: va tomando valores mayores o menores que el anterior.
  • Histogram: son agrupaciones de los valores que se recogen.
  • Summary: trabajan con percentiles y medias.

En base a las métricas un sistema de alertas envía notificaciones cuando se detectan situaciones anómalas. Para un sistema de alertas efectivo hay que tener varias consideraciones. Una de ellas es que cuando lleguen alertas no sean ignoradas, solo han de llegar a las personas interesadas y que cuando les lleguen sea para que sean atendidas con alguna intervención. Si llegan alertas en las que hay que determinar si requieren atención corren el riesgo de que sean ignoradas. Para mayor efectividad las alertas se pueden deduplicar, agrupar, enrutar, inhibir y silenciar, funcionalidades que ofrece Alertmanager.

Los sistemas actuales requieren no solo saber el estado de funcionamiento de cada elemento de la infraestructura, también cuando no funcionan por qué. También permiten reaccionar de forma proactiva para evitar errores antes de que ocurran.

Monitorización con Prometheus por Laura Morillo-Velarde Rodríguez y Beatriz Martínez

Monitorización con Prometheus por Laura Morillo-Velarde Rodríguez y Beatriz Martínez

Descanso

Momento de tomar un café y pasar por los stands de los patrocinadores.

Stands patrocinadoresStands patrocinadoresStands patrocinadores

Stands patrocinadoresStands patrocinadoresStands patrocinadores

Stands patrocinadoresStands patrocinadores

Stands patrocinadores

Implementing corporate Design Systems in React por Ignacio Velázquez

Un sistema de diseño o design system es importante para tener consistencia de la imagen de marca en todos los canales de comunicación desde la web a una aplicación móvil, un correo electrónico o un folleto impreso. Incluye colores, tipografía, espaciado. Algunos design systems son:

Al desarrollar un design system en una organización es importante ofrecer documentación, dar visibilidad al proyecto e involucrar a toda la empresa de forma que se use en todos los departamentos, ha de mantenerse como cualquier otro desarrollo. En la jerga de los design system se incluyen átomos, moléculas, organismos, plantillas y páginas.

Varias herramientas son útiles para las pruebas y el desarrollo de un design system:

  • Jest: para hacer pruebas de con JavaScript.
  • Storybook: para desarrollar componentes React, Vue o Angular de forma aislada.
  • Chromatic: para probar los cambios visuales.
  • BrowserStack: para probar en varios dispositivos.

Implementing corporate Design Systems in React por Ignacio Velázquez

Implementing corporate Design Systems in React por Ignacio Velázquez

Otra charla sobre microservicios por Isabel Garrido Cardenas y Sergi González

Se empieza a desarrollar una aplicación en forma de monolito, a medida que es más grande la aplicación y la organización en número de personas se divide en áreas funcionales. El siguiente paso es crear crear APIs con contratos y microservicios que se comunican unos entre otros, quizá sigan compartiendo la base de datos y tienen dependencias. El resultado es un monolito distribuido que genera sus propios problemas de escalabilidad y pruebas.

Para conseguir desacoplar los microservicios y si la consistencia eventual es posible en vez de utilizar una comunicación síncrona y acoplada por API REST o gRPC hay que utilizar la comunicación desacoplada mediante eventos e implementar código reactivo a esos eventos.

El bus de eventos se convierte en un único punto de fallo con problemas que hay preveer:

  • Eventos duplicados
  • Eventos perdidos
  • Eventos desordenados
  • Implementar operaciones idempotentes en eventos

Otra charla sobre microservicios por Isabel Garrido Cardenas y Sergi González

Otra charla sobre microservicios por Isabel Garrido Cardenas y Sergi González

Acabando

Dicen que en este evento el evento en realidad es el postevento, lo que ocurre a partir de las 14:00 en el networking, pintxo y poteo. No lo conozco por experiencia propia porque no he estado en ninguno, no se me da bien y ya tengo suficiente con dedicar una mañana a la asistencia. En cualquier caso el evento es el momento ideal para saludar a algunos excompañeros de trabajo para saber como les va o como nos va.

En las presentaciones se han mencionado algunas herramientas pero en estas que he estado este año han sido todas bastante teóricas, a los que ya conocen algo del tema que se trata poco les será nuevo y a los que no conocemos el tema hay que indagar acabado el evento para darle algo de sentido a lo expuesto. He recogido algunas ideas que con tiempo será interesante profundizar como el caso de los design systems.

Variable not found: Enlaces interesantes 388

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

Por si te lo perdiste...

.NET Core / .NET

ASP.NET Core / ASP.NET

Azure / Cloud

Conceptos / Patrones / Buenas prácticas

Data

Machine learning / IA / Bots

Web / HTML / CSS / Javascript

Visual Studio / Complementos / Herramientas

Xamarin

Otros

Publicado en Variable not found.

Blog Bitix: Desempaquetado olla a presión rápida Kuhn Rikon Duromatic Supreme de 3,5 litros

$
0
0

Las ollas rápidas permiten cocina además de en poco tiempo fácilmente. Son fáciles de usar y una buena con sus recambios dura muchos años. Al igual que con otros productos que voy comprando para mi uso en este artículo hago un resumen de las opciones que he evaluado, que he tenido en cuenta desde la capacidad hasta los recambios y finalmente el desempaquetado de la Kuhn Rikon modelo Duromatic Supreme que he adquirido.

Kuhn Rikon

De las cosas básicas en una cocina una es la olla rápida a presión, permite cocinar en muy poco tiempo y ahorrar dinero en energía que sin utilizarlas, son sencillas de utilizar y de limpiar. Hay multitud de modelos con diferentes características, precios y capacidades.

Necesitaba comprar una y he evaluado varios modelos, finalmente eligiendo una olla de la que se considera la gama alta, al menos por precio. Lo primero que he tenido que decidir ha sido la capacidad adecuada para mi caso, también la facilidad de encontrar repuestos, facilidad de limpieza y durabilidad. Una olla buena dura perfectamente varios lustros y alguna década tratándola con un poco de cuidado.

Elegir la capacidad según número de platos o personas

Lo primero que hay que decidir al comprar una olla es la capacidad más adecuada para el uso que se va a dar. Los modelos más pequeños están entre 2,5 litros, 3,5 litros y 4 litros, suficientes para 1 persona hasta 4 personas. Los modelos grandes alcanzan los 6, 8 y 10 litros para una familia grande. También hay conjuntos de ollas que tienen dos cuerpos de olla de diferentes capacidades en las que la misma tapa sirve para las dos utilizando la de capacidad más adecuada según la ocasión.

Una olla pequeña permite alcanzar presión más rápidamente y cocinar gastando menos energía lo que también ahorra a lo largo del tiempo algo de dinero en la factura de luz o gas. Hay que tener en cuenta que las ollas por seguridad solo permite cocinar hasta su límite máximo, que normalmente es 2/3 de la capacidad indicada. Por lo que si de forma ocasional se necesita es mejor adquirir una olla un poco más grande con una capacidad suficiente para ese límite de uso. Una olla de mayor capacidad permite cocinar para menos personas de su capacidad máxima pero una olla pequeña no permite cocinar para más personas de su límite indicado, aún así tampoco tiene sentido utilizar una olla de 6 litros para una persona.

Mi forma de calcular la capacidad ha sido tener en cuenta el número de platos que normalmente voy a cocinar, la capacidad de un plato hondo tiene una capacidad que es de entre 650 ml y 800 ml y que una olla solo se debe llenar hasta 2/3 de su capacidad total. Según lo anterior he intentado estimar los platos que puedo hacer según la capacidad de la olla, es probalbe que no sea muy exacto ya que la medida de los platos que he tomado no es muy exacta. Si he medido que cuatro platos ondos llenados casi hasta el borde exterior al máximo de agua y vertida en la olla llegan al límite de 2/3 así que el límite máximo pueden ser 4 platos.

  • Capacidad 2,5 litros: 2500 ml / 3 * 2 / 650 ml/plato = 2,5 platos máximo
  • Capacidad 2,5 litros: 2500 ml / 3 * 2 / 800 ml/plato = 2 platos máximo
  • Capacidad 3,5 litros: 3500 ml / 3 * 2 / 650 ml/plato = 3,5 platos máximo
  • Capacidad 3,5 litros: 3500 ml / 3 * 2 / 800 ml/plato = 3 platos máximo

Mi uso habitual es poner la olla un día haciendo comida para entre dos o tres platos como máximo, con lo que la capacidad adecuada para mi sería una de 2,5 litros pero estaría en el límite de lo que necesito y las veces que he hecho comida en una olla de esta capacidad siempre la he llenado al máximo, con lo que al final he adquirido una de 3,5 litros que quizá me quede algo grande en su límite superior pero me permite cocinar para más platos si necesitase en algún momento que guardaré en varios tuppers para otros días. También hay algunos modelos de 3 litros que probablemente hubiese elegido si me hubiesen parecido la mejor opción.

Para hacerme una idea aproximada de las dimensiones de la olla he hecho con unos folios el cuerpo de la olla, doblándolos y pegándolos con celo ajustando a un diámetro de 20 centímetros y una altura aproximada de 18 centímetros que es la que se indicaba en el paquete de la olla, aunque finalmente tiene menos altura de la que se indicaba para el paquete en la descripción del producto.

Opciones que he evaluado

Modelos hay muchos, de diferentes capacidades y de precios. Los modelos de entrada están entre 50€ y los modelos de la gama que se considera la superior está entre 130€ o hasta 200€ según capacidad. Pero el precio no lo he considerado algo determinante sabiendo que una olla perfectamente puede durar toda la vida si sale buena. Los modelos de entrada son perfectamente válidos pero en algunos detalles como los materiales se nota la diferencia con los modelos de gama alta.

Un punto importante que he considerado ha sido el poder encontrar repuestos y el precio de los mismos. A lo largo de la vida útil de una olla un elemento que hay que cambiar cada dos años aproximadamente es la goma que permite que coja presión, es importante que esté en buenas condiciones ya que o hace que no coja presión o suponga un riesgo de seguridad, no poder encontrar repuestos hace que la olla perfectamente válida quede inservible y haya que comprar otra. Por otro lado si los repuestos son caros hace que el precio a lo largo de su vida se incremente sensiblemente. En ambos casos lo barato puede salir más caro.

He elegido un modelo de una marca conocida y que habitualmente es fácil encontrar en comercios habituales como El Corte Inglés y Amazon junto con sus repuestos.

También hay que tener el cuenta el diámetro de la olla y de los fuegos de la vitrocerámica o placa de inducción, sabiendo que en la base de la parte inferior que entra en contacto con el calor es algo menor que el diámetro de sus especificaciones.

Mis opciones preferentes han estado entre las marcas Fissler, WMF y Kuhn Rikon, son modelos considerados de la gama alta, todos con precios de venta similares.

He visto algún modelo más económico como Elo Praktika Xs, Alza Space y Bra Vitesse.

Mi madre tenía una Fissler y le ha durado mucho tiempo aunque permite elegir la presión que no tiene otros modelos finalmente la he descartado porque el modelo nuevo Fissler Vitavit Comfort para la válvula tiene una membrana de silicona en vez de ser completamente de metal como el anterior, esto hace que tenga otro elemento que posiblemente necesita repuesto y puede que frágil, además la válvula es algo más difícil de limpiar por la pieza de metal que tiene en ella.

La WMF Perfect Plus también utiliza una membrana para la válvula y no permite seleccionar la presión de trabajo. Quizá hubiese elegido una WMF porque hay algún modelo con 3 litros de capacidad, sin embargo sus repuestos los he visto algo más caros, y por lo de la membrana de la válvula al final la que más me ha convencido es una Kuhn Rikon Duromatic Supreme. Todas tenían un precio alrededor de 130€.

Modelo que he elegido, Kuhn Rikon Duromatic Supreme 3,5 litros

De Kuhn Rikon hay varias gamas, en unas varía algo el aspecto estético o en el aspecto funcional al tener asas o mango pero todas son muy similares con su aspecto acampanado en la parte superior. He elegido una Kuhn Rikon Duromatic Supreme de 3,5 litros, esta gama tiene capacidades en capacidades de 2,5, 3,5, 4, 5, 6, y 8 litros.

Sus dimensiones son bastante compactas y es más pequeña de lo que pensaba habiendo visto una Fissler de 2,5 litros pero de 18 cm de diámetro:

  • Diámetro del cuerpo de 20 cm.
  • Base en contacto con el fuego de 17 cm de diámetro.
  • Altura de 12 cm sin la tapa puesta
  • Altura de 17 cm con la tapa puesta.
  • La tapa desde el mango tiene una longitud de 36,5 cm.

El contenido de la caja es:

  • Cuerpo de la olla de 20 cm de diámetro y 3,5 litros.
  • Tapa de la olla de 20 cm con válvulas de seguridad y embellecedor de la tapa.
  • Goma de la olla.
  • Bandeja para cocinar al vapor.
  • Manual de instrucciones.

Tiene marcas interior sobre el metal con lo que no desaparecerá con el lavado ni uso del límite máximo de 2/3 y de 1/2 en caso de alimentos que al cocerlos se expanden ocupando un volumen mayor. Los mangos de baquelita son del material típico empleado en las ollas.

El sistema de cierre es automático, el bulón de la tapa se retrae cuando la tapa está correctamente cerrada, haciendo que la goma se fije al perímetro exterior y la olla sea capaz de adquirir presión. Una vez la olla ha adquirido algo de presión la tapa no puede ser abierta con un empleo normal de fuerza.

Su sistema de liberación de presión no es el habitual que está en el mango sino que hay que presionar la válvula indicadora de la presión hacia abajo, el embellecedor de la válvula hace que el vapor se libere de forma segura sin riesgo de quemarse. Este embellecedor o tapa de plástico no es imprescindible para su funcionamiento pero si para liberar la presión que hace que se expulse el vapor con más seguridad. Algunos usuarios comentan algo de fragilidad de esta tapa con lo que la quitarla y ponerla es conveniente hacerlo con cuidado para evitar romper alguna de las patas de plástico que le permiten ajustarse a la válvula.

Algunas cosas a tener en cuenta es que la goma esté bien ajustada a la tapa antes de cerrarla, otra es diluir la sal en el al agua para evitar la corrosión que se produce si se queda adherida al fondo, en caso contrario esto puede provocar algún defecto estético que no afecta al funcionamiento pero afecta a su aspecto. Otra cosa es no meter la goma en el lavavajillas porque se degrada en menos tiempo, es mejor lavarla a mano y de vez en cuando darle un poco de aceite de cocinar.

Caja ollaCaja ollaCaja olla

Caja ollaCaja olla

Caja olla

Cuperpo olla, tapa y elementosCuperpo olla, tapa y elementosCuperpo olla, tapa y elementos

Cuperpo olla, tapa y elementosCuperpo olla, tapa y elementosCuperpo olla, tapa y elementos

Cuperpo olla, tapa y elementosCuperpo olla, tapa y elementosCuperpo olla, tapa y elementos

Cuperpo olla, tapa y elementosCuperpo olla, tapa y elementosCuperpo olla, tapa y elementos

Cuperpo olla, tapa y elementosCuperpo olla, tapa y elementosCuperpo olla, tapa y elementos

Cuperpo olla, tapa y elementosCuperpo olla, tapa y elementos

Cuperpo olla, tapa y elementos

ManualManualManual

Manual

Manual

Repuestos para ollas Kuhn Rikon

A lo largo de la vida de la olla hay que sumarle los repuestos que necesite. Cambiar la goma es necesario cada unos dos años dependiendo de su uso ya que con el paso del tiempo van perdiendo sus propiedades de flexibilidad y en algún momento hacen que la olla gotee algo de agua por los bordes o no coja presión impidiendo su correcto funcionamiento.

Dado que las Kuhn Rikon son modelos fáciles de encontrar a la venta por ser una marca reconocida, se venden en El Corte Inglés y también pueden encontrarse en Amazon además de las gomas, la tapa embellecedora y protector de vapor al realizar la pérdida rápida de presión, la cápsula de la válvula o la válvula completa.

Encontrar repuestos hace que no sea necesario comprar una nueva olla que salvo la pieza estropeada seguiría funcionando perfectamente. Los repuestos de las Fissler son algo más caros.

Primer uso

En el primer uso he comprobado que su funcionamiento es muy sencillo, no emite apenas ruido y salvo algo muy puntual no emite nada de agua ni vapor. En 9 minutos coge presión y una vez la primera anilla roja o la segunda según la comida aparece basta con dejarla el tiempo indicado en el manual para que el alimento quede cocinado. Una vez pasado el tiempo hay que apagar el fuego y apartarla, para que baje la presión se puede dejar a que de forma natural o presionando el émbolo indicador de presión para hacer una despresurización rápida.

La mayor duda que tenía era sobre la capcidad de la olla, si los 3,5 litros se me quedarían grandes o pequeños. Para mi caso creo que he acertado con el tamaño, posiblemente la de 2,5 litros me hubiese quedado pequeña, la de 3,5 me permitirá hacer comida para desde 2 platos hasta 4 sin problemas que era lo que quería.

La limpieza de la olla también es muy sencilla a mano, no tiene ningua parte donde especialmente puedan quedarse restos de suciedad. Lo único que hay que tener en cuenta es que no es apta para el lavavajillas.

Primer uso, con unas alubiasPrimer uso, con unas alubias

Primer uso, con unas alubias

Recipientes para transportar comida

Si comes en el trabajo es necesario utilizar también unos contenedores para llevar la comida, además de la olla he comprado unos recipientes. Mis requisitos en este caso era que fueran de cristal ya que son más fáciles de limpiar, no adquieren olores ni con el paso del tiempo color sobre todo con el tomate de unos espaguetis. El otro aspecto que buscaba era que el cierre fuese con bisagra y no una fina pieza de plástico que con la acción continuada de abrir y cerrar al final se termina rompiendo. El último aspecto que buscaba era que fuesen rectangulares para que entrasen bien en una mochila.

Teniendo en cuenta las propiedades que deseaba, opté por un conjunto de recipientes de 840 ml que una vez recibidos dan la sensación de buena calidad, la tapa se ajusta a la perfección para cerrar herméticamente el contenido, la junta y las asas de cierre de la tapa se puede desmontar y se pueden lavar tanto el cuerpo de cristal como la tapa de plástico en el lavavajillas.

Los tuppers de 840 ml tiene unas dimensiones de 18,5 cm de largo, 12 cm de ancho y 6 cm de alto.

Recipientes de comidaRecipientes de comidaRecipientes de comida

Recipientes de comida

Recipientes de comida

840 ml es el equivalente de la capacidad de un plato hondo pero puede quedarse pequeño, en ese caso unos recipientes de 1040 ml es otra opción, la comida tendrá más espacio.

Otros complementos

Un complemento a una olla exprés son los robots de cocina que permiten realizar algunas recetas y elaboraciones adicionales como salsas, cremas y sofritos, la diferencia está en que suelen tener una capacidad de mayor de 5 litros y ser sensiblemente más caros al menos los modelos de gama alta. Son un complemento porque hasta donde he visto estos aparatos no hacen la función de una olla rápida, no trabajan con presión.

Por supuesto otros elementos indispensables son las típicas sartenes de diferentes tamaños. Hace ya tiempo compre un conjunto de sartenes de la marca BRA con las que estoy muy contento con su calidad.

Por el momento creo que para las comidas que suelo hacer con la olla y las sartenes además de las típicas cacerolas bajas tengo más que suficiente.

Variable not found: Describiendo APIs ASP.NET Core con Swagger

$
0
0
Open APILa OpenAPI Specification (OAS) es un estándar abierto para la descripción de APIS REST promovido por la Iniciativa OpenAPI, un consorcio de compañías de primer nivel como Microsoft, Google, IBM, Paypal y otros.

El objetivo de OpenAPI es conseguir una fórmula normalizada para describir las capacidades de un servicio REST, independientemente de los lenguajes o tecnologías con las que sea implementado. Esta descripción, normalmente especificada en formato JSON o YAML, permite a clientes (sean humanos o máquinas) descubrir servicios, comprender sus capacidades y conocer sus detalles de funcionamiento sin necesidad de tener acceso a su código fuente o documentación textual.

Esta especificación formal abre interesantes posibilidades, pues a partir de la definición estandarizada de servicios es posible, entre otros,
  • disponer de herramientas de diseño y modelado de servicios,
  • generar automáticamente páginas de documentación,
  • generar automáticamente código cliente y servidor para dichos servicios para distintos, frameworks y lenguajes de programación,
  • generar automáticamente código de testing y validaciones,
  • o generar automáticamente mocks de servicios.

¿Y qué tiene que ver Swagger en todo esto? Pues bastante, porque Swagger fue la semilla de OpenAPI. De hecho, Swagger era un proyecto liderado por la compañía Smartbear, que definió las dos primeras versiones de la especificación, y luego la donó a la nueva iniciativa abierta OpenAPI, quedando renombrada a partir de ese momento a "OpenAPI Specification". Por tanto, a efectos prácticos, cuando hablamos de la especificación Swagger y de OpenAPI, en muchas ocasiones nos estamos refiriendo a lo mismo.

A partir de la puesta en marcha de la iniciativa OpenAPI, el término Swagger pasó a utilizarse principalmente para denominar el framework o conjunto de herramientas que implementan la especificación, tanto de forma comercial como open source: diseñadores, generadores de código, parsers, generadores de documentación, etc.

La web Swagger.io es el sitio de referencia para las herramientas básicas y open source de Swagger.

Herramientas en Swagger.io

¿Qué pinta tiene la descripción OpenAPI de un servicio?

Imaginemos una API tan simple como la siguiente, creada con ASP.NET Core MVC:
[Route("[controller]")]
public class CalculatorController : ControllerBase
{
/// <summary>
/// Divides two numbers
/// </summary>
/// <param name="a">The dividend</param>
/// <param name="b">The divisor</param>
/// <response code="200">Result of dividing "a" by "b"</response>
/// <response code="400">It's not possible to divide by zero</response>
[HttpGet("[action]/{a}/{b}")]
[Produces("application/json")]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<int> Divide(int a, int b)
{
if (b == 0)
{
return BadRequest();
}
return a / b;
}
}
La descripción o esquema OpenAPI de este servicio en formato JSON podría ser la siguiente (he añadido algunos comentarios para explicar los principales puntos):
{
"openapi": "3.0.1",
"info": {
"title": "Calculator",
"version": "v1"
},
"paths": {
"/Calculator/Divide/{a}/{b}": { // <-- Ruta del endpoint
"get": { // <-- Verbo HTTP
"tags": [
"Calculator"
],
"summary": "Divides two numbers",
"parameters": [
{
"name": "a", // <-- Parámetro "a"
"in": "path",
"description": "The dividend",
"required": true,
"schema": {
"type": "integer",
"format": "int32"
}
},
{
"name": "b", // <-- Parámetro "b"
"in": "path",
"description": "The divisor",
"required": true,
"schema": {
"type": "integer",
"format": "int32"
}
}
],
"responses": {
"200": { // <-- Retorno 200 OK
"description": "The result of dividing \"a\" by \"b\"",
"content": {
"application/json": {
"schema": {
"type": "integer",
"format": "int32"
}
}
}
},
"400": { // <-- Retorno 400 Bad request
"description": "It's not possible to divide by zero"
}
}
}
}
}
}
Sin duda algo verboso, pero no tenemos que preocuparnos por ello porque vamos a ver algo más adelante que un componente llamado Swashbuckle puede generar esta descripción por nosotros :)

Lo importante es que el contenido es bastante claro y que el servicio queda especificado por completo, al más mínimo detalle.

Describiendo nuestras APIs HTTP

El paquete NuGet Swashbuckle.AspNetCore proporciona componentes para generar de forma automática la descripción OpenAPI de servicios creados con ASP.NET Core. Obviamente tendremos que ayudarlo un poco, como habéis visto en el servicio anterior, por ejemplo introduciendo comentarios o indicando expresamente los tipos de resultado, porque de otra forma este componente no podría aportar tanta información a los clientes.

Pero la ventaja es que esto lo haremos a nivel de código, e incluso disponemos de analizadores estáticos de Open API que nos ayudarán a completar la información que necesitemos para lograr una documentación de calidad.

Para generar automáticamente la documentación de nuestros API, lo primero que debemos hacer es instalar el paquete Swashbuckle.AspNetCore y, tras ello, registrar sus servicios en el inyector de dependencias de ASP.NET Core:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("api", new OpenApiInfo { Title = "Awesomic calculator", Version = "v1" });
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath);
});
...
}
En la llamada a SwaggerDoc() establecemos los parámetros esenciales: el nombre que vamos a dar al documento generado, y luego alguna metainformación básica sobre el API, como su nombre descriptivo o versión (ambos aparecerán en la descripción OpenAPI).

A continuación, indicamos al componente dónde puede encontrar el archivo XML con la documentación de clases y métodos, obteniendo primero la ruta correcta y pasándosela al método IncludeXmlComments().

Podemos activar la generación de documentación XML desde las propiedades del proyecto, o bien introduciendo el siguiente bloque en el archivo .csproj (fijaos que el <NoWarn> es sólo para que el sistema no nos avise en otras clases que tengamos sin documentar):
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
Tras el registro de servicios, ya sólo tenemos que añadir al pipeline el middleware que se encargará de retornar la descripción del API:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseSwagger();
...
}
¡Y esto es todo! Usando la configuración por defecto, una petición a la ruta /swagger/api/swagger.json retornará el esquema de la API según la especificación OpenAPI. Fijaos que ese "api" de la ruta debe corresponder con el nombre que dimos al documento cuando registramos el servicio anteriormente:

Especificación OpenAPI de nuestro servicio

A partir de este momento,ya podremos comenzar a utilizar herramientas que se alimenten de esta definición como Swagger UI o generadores de código, pero, para no extendernos más, lo dejaremos para otro post más adelante :)

Publicado en Variable not found.

Fixed Buffer: Cómo hacer mock de ILogger en .Net Core 3.x durante las pruebas

$
0
0
Tiempo de lectura:5minutos
Imagen ornamental para la entrada "Cómo hacer mock de ILogger en .Net Core 3.x durante las pruebas" donde se ven unas trazas de un log

Este mes he estado trabajando en un nuevo proyecto para un cliente que consiste en un servicio totalmente desatendido. Como servicio desatendido que es necesita un sistema de logging muy integrado de modo que haya toda la información posible en caso de fallo porque corre en equipos de difícil acceso. Funcionalidad a funcionalidad voy añadiendo las pruebas al código y me encuentro con una no muy agradable sorpresa… Los cambios en las clases de .Net Core 3 hacen que ILogger no se pueda mockear, al menos no a simple vista…

Por dar algo de contexto, el servicio lo he implementado con un Worker Service de .Net Core 3.1 por lo que la opción natural es registrar el logger dentro de la infraestructura de .Net Core 3.1 a través de ILogger y utiliza Entity Framework Core Code First.

¿Cómo se hacia mock de ILogger en .Net Core 2.x?

Para poder hacer las pruebas sobre código que utiliza ILogger teníamos (y tenemos en .Net Core 3.x) una implementación genérica que no hace nada para poder hacer las pruebas. Esta implementación es NullLogger y gracias a ella las pruebas van a poder lanzarse aunque el logger no haga nada. Si por el contrario necesitamos hacer algo sobre el logger, sea una configuración de callback para loguear a través de la consola de runner o simplemente verificaciones sobre los mensajes, vamos a tener que hacer nuestro propio mock.

Pese a que no era algo especialmente sencillo, hacer un mock de ILogger en .Net Core 2.x era posible sin tener que implementar código extra. La interfaz ILogger tiene entre muchos métodos de extensión, un método con una firma así:

public void Log<TState> (LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState,Exception,string> formatter);

Sobre esta interfaz, el tipo genérico con el que se llama a esta interfaz es ‘FormattedLogValues‘. Sabiendo esta información se puede hacer un mock perfectamente con librerías como por ejemplo Moq sin mucho esfuerzo:

var logger = Mock.Of<ILogger<Program>>();
//Configuración
Mock.Get(logger).Setup(
           m => m.Log(
           It.IsAny<LogLevel>(),
           It.IsAny<EventId>(),
           It.IsAny<FormattedLogValues>(),
           It.IsAny<Exception>(),
           It.IsAny<Func<object, Exception, string>>()
           )
      ).Callback(/*Callback*/);
//Verificación
Mock.Get(logger).Verify(
           m => m.Log(
           It.IsAny<LogLevel>(),
           It.IsAny<EventId>(),
           It.IsAny<FormattedLogValues>(),
           It.IsAny<Exception>(),
           It.IsAny<Func<object, Exception, string>>()
           )
      );

El código es perfectamente funcional y con el se pueden escribir cualquier requisito para las pruebas.

¿Y por qué no se puede en .Net Core 3.x?

Si como comentábamos hace poco la interfaz no ha cambiado, y los métodos no han cambiado, ¿dónde está el problema? ¿Si pongo ese mismo código en mis pruebas porque no va a funcionar? Pues el problema está en que entre .Net Core 2 y 3 han cambiado algunas clases y estructuras, entre ellas ‘FormattedLogValues’ que ha pasado de ser pública a ser interna.

Esto hace que si ponemos el mismo código, pero utilizando las versiones de los paquetes para .Net Core 3.x, tengamos un error como este:

La imagen muestra el error de accesibilidad al tratar de hacer mock a ILogger en .Net Core 3.x

Si bien es cierto que los frameworks de mocking se adaptan para dar el mejor servicio posible ante estos cambios, no siempre son suficientes. Por ejemplo, para la parte de verificación Moq ya tiene una solución para reemplazar la prueba y es tan simple como esto:

Mock.Get(logger).Verify(
                  log => log.Log(
                    It.IsAny<LogLevel>(),
                    It.IsAny<EventId>(),
                    It.IsAny<It.IsAnyType>(),
                    It.IsAny<Exception>(),
                    (Func<It.IsAnyType, Exception, string>)It.IsAny<object>()),
                  Times.Once);

¿Cómo hacer mock de ILogger en .Net Core 3.x?

En mi caso concreto esta funcionalidad de verificación no fue suficiente ya que estaba teniendo problemas con las pruebas en el entorno de integración que no se replicaban en ninguna otra máquina. Para poder aprovechar toda la información de log que el propio código genera necesitaba relanzar el logger hacia la consola del runner de xUnit.

En versiones anteriores de .Net Core me hubiese valido utilizar un callback del método ‘Log’, pero con el cambio de ‘FormattedLogValues’ no es una opción. Precisamente por eso he tenido que hacer mi propia implementación de ILogger basada en la del NullLogger, pero con los extras bajo el capó:

public class SpyLogger<T> : ILogger<T>
{
    private readonly ITestOutputHelper _outputHelper;

    public SpyLogger(ITestOutputHelper outputHelper)
    {
        _outputHelper = outputHelper;
    }

    public IDisposable BeginScope<TState>(TState state)
    {
        return NullScope.Instance;
    }

    public bool IsEnabled(LogLevel logLevel)
    {
        return true;
    }

    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
    {
        _outputHelper.WriteLine($"{DateTime.Now.TimeOfDay}--{typeof(T).Name}-->{state}");
    }
}
internal class NullScope : IDisposable
{
    public static NullScope Instance { get; } = new NullScope();

    private NullScope()
    {
    }
    public void Dispose()
    {
    }
}

En este código las cosas importantes son 2. La primera es la clase ‘NullScope’ que es la misma implementación que tiene ‘NullLogger’. Esta clase es necesaria para la implementación de ‘BeginScope’ de nuestro propio ILogger. La segunda es que mi ‘SpyLogger’ recibe como parámetro el logger de xUnit y escribe sobre él. Con esto la salida de las pruebas registra todos los mensajes de log que registraría la aplicación y tengo una información muy valiosa sobre la ejecución de las pruebas.

La imagen muestra varias trazas de log en la consola de xUnit conseguidas gracias a hacer el mock de ILogger en .Net Core 3.1

Con esta clase ‘SpyLogger’ he conseguido hacer un mock sobre ILogger en .Net Core 3.x y relanzar los mensajes hacia la consola del runner de xUnit.

Aunque en este caso concreto la necesidad era relanzar las trazas de log hacia la consola de xUnit, esta puede ser la implementación base sobre la que añadir diferentes funcionalidades. Por ejemplo, si hacer verificaciones fuese necesario además de la funcionalidad que ya hay, se podría hacer el código necesario para las verificaciones o incluso recibir un ILogger en el constructor y cambiar el método Log para que llame de nuevo al ILogger. El cambio sería que ahora ese ILogger recibido como parámetro en el constructor si sería un mock normal de Moq sobre el que si podemos hacer verificaciones.

Aunque el código es un poco enrevesado y hay que añadir una capa extra de trabajo, es la mejor solución que he encontrado y quería compartirla por si a alguien le puede ayudar a afrontar el problema con el que me he encontrado yo.

Si por el contrario ya te ha tocado enfrentar este problema de hacer mock de ILogger en .Net Core 3 y crees que tu solución es mejor, no dudes en dejar un comentario planteándola.

**La entrada Cómo hacer mock de ILogger en .Net Core 3.x durante las pruebas se publicó primero en Fixed Buffer.**

Picando Código: Mozilla Thunderbird se muda a MZLA Technologies Corporation

$
0
0

Mozilla Thunderbird

Mi cliente de correo favorito, Thunderbird, encontró un nuevo hogar:

A partir de hoy, el proyecto Thunderbird operará desde una subsidiaria completamente nueva de la Fundación Mozilla, MZLA Technologies Corporation. Esta mudanza se ha estado trabajando por un tiempo a lo que Thunderbird ha crecido en donaciones, staff y aspiraciones. Esto no va a impactar las actividades día-a-día o la misión: Thunderbird seguirá siendo libre y de código abierto, con el mismo calendario de lanzamientos y gente detrás del proyecto.

Hubo un tiempo en el que el futuro de Thunderbird era incierto, y no estaba claro qué iba a pasar con el proyecto tras la decisión de que Mozilla Corporation no lo financiaría. Pero en años recientes las donaciones de usuarios de Thunderbird le han permitido crecer y florecer orgánicamente dentro de la Fundación Mozilla. Ahora, para asegurar el éxito operacional a futuro, siguiendo meses de planificación, se está forjando un nuevo camino hacia adelante. Mudarse a la Corporación MZLA Technologies no sólo le permitirá al proyecto Thunderbird más flexibilidad y agilidad, sino que también permitirá explorar la oferta de productos y servicios a los usuarios que no eran posibles bajo la Fundación Mozilla. La movida permitirá al proyecto recaudar ingresos a través de asociaciones y donaciones no-caritativas, lo cual a cambio puede ser usado para cubrir los costos de nuevos productos y servicios.

El enfoque de Thunderbird no va a cambiar. Se mantiene comprometido a crear tecnología increíble de código abierto enfocada en estándares abiertos, privacidad del usuario y comunicación productiva. El Consejo de Thunderbird continua administrando el proyecto, y el equipo que guía el desarrollo de Thunderbird sigue siendo el mismo.

Por último, esta mudanza a la Corporación MZLA Technolocies permite al proyecto Thunderbird contratar con mayor facilidad, actuar de manera más rápida, y perseguir ideas que previamente no eran posibles. Más información sobre la dirección futura de Thunderbird será compartida en próximos meses.

Thunderbird Blog: Thunderbird’s New Home

Es bueno ver que el cliente de correo tenga un futuro asegurado, sobretodo después de ese período en el que su destino era bastante incierto. Por suerte con el software libre generalmente éstos proyectos tan populares terminan encontrando un camino. Pero aplicaciones tan complejas siempre necesitan un poco de respaldo para seguir adelante.  Habrá que mantenerse atentos a las novedades que trae el cambio.

Picando Código: Exhibición sobre Tiranosaurios en el Museo Nacional de Escocia

$
0
0

Del 23 de enero al 4 de mayo el Museo Nacional de Escocia en Edimburgo está presentando una exhibición sobre Tiranosaurios🦖

Mientras que la especie más famosa es el poderoso T. rex, los tiranosaurios venían en todas formas y tamaños, y su historia se extiende por más de 100 millones de años. La exhibición muestra especímenes fósiles extremadamente raros, esqueletos de yeso – incluyendo uno de “Scotty”, uno de los esqueletos de T. rex más grandes y completos del mundo – e increíbles modelos de dinosaurios con plumas. Los visitantes también podrán explorar la diversidad de cráneos de tiranosaurio y encontrar lo que variaciones en la estructura nos pueden decir sobre distintas estrategias de caza y alimentación.

Más información.

El domingo estuve por el museo y disfruté por algunas horas un tiempo con estos fósiles y aprendiendo más sobre la familia Tiranosauria. Por suerte he tenido la oportunidad de ver más de un modelo de esqueleto de Tiranosaurio. El último había sido recientemente Tristan Otto en Berlín. El de Scotty es bastante impresionante, y está bueno ver su tamaño en comparación a otros especímenes de la familia. Me encanta presenciar esos modelos e imaginar lo que sería estar frente a un animal de ese tipo.

Las placas informativas de la exhibición incluian información de lo más actualizado que se conoce sobre la familia de Tiranosaurios. También hay menúes interactivos y demás para los más pequeños (y no tan pequeños). Hay también unos modelos de tiranosaurio con plumas como dice la descripción. Esto es algo que no se sabía hasta hace unos años y ahora se cree que todos o la mayoría de los tiranosaurios eran emplumados.

Algunas fotos de la exhibición:

Cráneos de Tiranosaurio

Cráneos de Tiranosaurio

Tiranosaurios varios

Tiranosaurios varios

Más Tiranosaurios

Más Tiranosaurios

Modelo de Scotty el Tiranosaurio

Modelo de Scotty el Tiranosaurio

Modelo de Scotty el Tiranosaurio

Modelo de Scotty el Tiranosaurio

El Museo Nacional de Escocia tiene entrada gratuita (aunque se sugiere dejar alguna donación), y es espectacular. Así que cuando anden por Edimburgo, es un paseo súper recomendable. 

Cuentan con su propio modelo permanente de Tiranosaurio Rex basado en MOR 555, también conocido como “Wankel Rex”. Con un 46% del esqueleto encontrado, es el segundo esqueleto más grande y más completo de T. Rex (más información en el sitio del museo). También hay un modelo de Estegosaurio y un montón de cosas interesantes más. Ya que estaba en el museo pasé a saludar a Wankel para que no se pusiera celoso del resto de la exhibición…

MOR 555 o "Wankel Rex"

MOR 555 o “Wankel Rex”

Blog Bitix: Los modificadores de acceso de clases, propiedades y métodos en Java

$
0
0

Java

Uno de los principios básicos de los lenguajes orientados a objetos es la encapsulación, mediante la cual se garantiza que los datos de una clase solo son modificados por las operaciones apropiadas implementadas en los métodos de sus clases para preservar su invariante, las reglas que define la clase y el estado consistente de su estado.

El acceso a las propiedades y métodos se determina mediante las palabras reservadas de los modificadores de acceso, en Java hay cuatro modificadores de acceso que definen ámbitos de visibilidad de más restrictivos a menos restrictivos:

  • private: únicamente la clase puede acceder a la propiedad o método.
  • package private (valor por defecto si no se indica ninguno): solo las clases en el mismo paquete pueden acceder a la propiedad o método.
  • protected: las clases del mismo paquete y que heredan de la clase pueden acceder a la propiedad o método.
  • public: la propiedad o método es accesible desde cualquier método de otra clase.

Las clases tienen uno de los modificadores de acceso public o package private con el mismo significado que en las propiedades y métodos, visibles desde cualquier otro paquete y solo visible desde su propio paquete.

Los modificadores de acceso son una palabra reservada del lenguaje y se colocan delante de la propiedad o método, el modificador de acceso package private no tiene palabra reservada se aplica en caso de que no se especifique un modificador de acceso explícitamente.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
packageio.github.picodotdev.blogbitix;publicclassFoo{privateStringproperty1;Stringproperty2;protectedStringproperty3;publicproperty4;publicStringgetProperty1(){     returnthis.format;}StringgetProperty2(){     returnproperty2;}protectedStringgetProperty3(){     returnproperty3;}privateStringgetProperty4(){     returnproperty4;}}
Foo.java

Los ámbitos de visibilidad según el modificador de acceso y el origen de acceso a la propiedad o método son los siguientes.

Modificador de accesoMisma clase o anidadaClase en el mismo paqueteClase que hereda en otro paqueteClase que no hereda en otro paquete
privateNoNoNo
default (package private)NoNo
protectedNo
public

En este gráfico hay representados paquetes que contienen clases, clases con rectángulos, las flechas indican herencia entre clases y las clases que están coloreadas indican que tienen visibilidad de la propiedad y método según el ámbito de acceso, la ubicación de la clase que accede y si hay una relación de herencia. En esencia es la misma información de la tabla pero representada de forma gráfica.

Modificadores de acceso en Java

Modificadores de acceso en Java Fuente: wikipedia.org

Una detalle a tener en cuenta es que los modificadores afectan a las clases, una propiedad privada de una clase es accesible para todas las instancias de esa clase. En concreto, este código es válido y el resultado es two, bar1 puede acceder a la propiedad thing de la instancia bar2 aún siendo privada en la clase.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
packageio.github.picodotdev.blogbitix;publicclassBar{privateStringthing;publicvoidBar(Stringthing){       this.thing=thing;}publicStringgetOtherThing(Barother){       returnother.thing;}publicstaticvoidmain(String[]args){       Barbar1=newBar("one");       Barbar2=newBar("two");       Stringthing=bar1.getOtherThing(bar2);       System.out.println(thing);}}
Bar.java

No hay encapsulación entre las instancias de la misma clase, la encapsulación es para la clase accedida desde otras clases según los modificadores de acceso. Pero aunque una instancia tenga acceso y capacidad de modificar las propiedades de otra instancia se ha de seguir manteniendo la invariante, si una instancia modifica los datos de otra instancia ha de seguir manteniendo la invariante de la clase de esa otra instancia. Para mantener la invariante y la encapsulación generalmente se proporciona acceso a un método y no directamente a las propiedades.

Picando Código: ATuServicio 2020

$
0
0

Como casi todos los 1° de febrero desde 2015, este año se lanza una versión actualizada de ATuServicio. Y como todos los meses de enero de los últimos años, con DATA anduvimos a las corridas arreglando, actualizando y corrigiendo cosas para poder tener todo en marcha. Se van a venir algunas cosas nuevas en breve, pero mientras tanto ya se pueden ver los datos actualizados ahora que se volvió a abrir el corralito mutual en Uruguay.

ATuServicio.uy

 

Copio y pego el mensaje de DATA:

Empieza un nuevo período de movilidad regulada (MORE), también conocido como “corralito”, y con él vuelve A Tu Servicio, como desde hace seis años.

Desde hoy, sábado 1º, y hasta el 28 de febrero, los/as usuarios/as del sistema de salud que cumplan con los requisitos, podrán cambiar de prestador de salud si así lo desean. Las personas interesadas en hacerlo deberán presentarse con su cédula de identidad en la mutualista a la cual quieren ingresar.

Decisiones informadas y basadas en datos

A Tu Servicio es una herramienta que permite obtener, visualizar y comparar datos de los diferentes prestadores de salud de Uruguay, para promover la toma de decisiones informadas de los/as usuarios/as y la transparencia del sistema.

Por eso, si estás pensando en cambiar de prestador, te invitamos a ingresar a la herramienta para comprar datos y así definir qué es lo que más te conviene, según las prioridades que vos definas. Y si no, igual es una gran oportunidad para conocer más sobre tu prestador de salud 😁.

Esta plataforma es desarrollada por DATA y el Ministerio de Salud Pública.

Más información:

Viewing all 2725 articles
Browse latest View live