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

Blog Bitix: Decidido a comprar un Intel NUC Bean Canyon entre las opciones que he evaluado

$
0
0
Intel

El ordenador portátil que tenía sigue siendo perfectamente útil, sin embargo, en algunos casos concretos de mi uso la cantidad de memoria que tenía se me estaba quedando corta y cuando me pasa esto suelo aprovechar si alguien de mi entorno necesita ordenador traspasarlo y yo comprarme otro nuevo.

El ordenador que tenía era un Sony VAIO de finales del 2012 con un procesador Intel i3 3210M con gráfica integrada HD 4000, 8 GiB de memoria, un disco duro de estado sólido Samsung 840 EVO de 256 GiB con interfaz SATA y una pantalla de resolución 1600x900. Durante todo este tiempo me ha funcionado a la perfección, incluso con su gráfica me fue suficiente para un entorno de escritorio GNOME con GNU/Linux y he acabado muy contento con la marca Sony al contrario de mi anterior portátil Dell XPS 1530 de la que no pienso comprar nunca nada de esta marca, quizá tuve mala suerte pero el portátil Dell no fue barato, no acabé contento con la calidad del producto pasado el encantamiento inicial y al final acabó totalmente muerto sin ni siquiera encenderse.

Con lo que desde hace unos meses he empezado a barajar opciones para comprar equipo con los requisitos que tengo de ser lo más pequeño posible, silencioso, con 32 GiB de memoria, procesador con mínimo 4 cores y 8 hilos, no necesito tarjeta gráfica dedicada ya que no jugaré a juegos o una integrada con bajar calidad de detalles me servirá a modo ocasional. También quería una pantalla externa de 25” o 27” con resolución de 2K para mayor comodidad y evitar problemas por estar con la cabeza medio agachada durante bastante tiempo. Habiendo pasado 5 años desde mi anterior portátil Sony quiero que el ordenador sea un salto significativo en lo que tenía por eso el requerimiento de los 4 cores, los 32 GiB de memoria y la pantalla 2K. La memoria a pesar del caro precio de la DDR4 en el momento de este artículo. El SSD es la mejor inversión para mejorar el rendimiento que uno puede hacer, más que el procesador. El SSD probablemente elija uno en formato M.2 con interfaz NVMe que tienen una tasa de transferencia 3 veces superior a los SSD con interfaz SATA que ya son rápidos, los NVMe son algo más caros pero no mucho más.

He barajado varias opciones principalmente ordenadores en factor de forma pequeños como los Intel NUC, Gigabyte Brix, Zotac, MSI Cubi, Slimbook ONE, Slimbook PRO2 o AMD Ryzen montando un mini-ITX. Ya estoy casi decidido a lo que compraré y no quiero esperar mucho más a tener equipo propio de cuando se comercialicen y aunque estoy aguantando con un Mac del trabajo comentando Tu con tu macOS yo con mi GNU/Linux. Será con mucha probabilidad un Intel NUC Bean Canyon que se lanzarán en la segunda mitad del 2018.

A pesar de saber que todos los procesadores Intel de la última década está afectados por los importantes problemas de seguridad Meltdown y Spectre que se están mitigando por software, de momento no se ha descubierto una forma de aprovecharlos pero quizá en un futuro se pueda y afecte de forma importante al rendimiento para corregirlos si es que se puede. Pero es que el resto de opciones he ido descartando por otros motivos.

MeltdownSpectre Logotipos de Meltdown y Spectre

El precio que calculo tendrá el Intel NUC Bean Canyon con procesador Intel i5 8250U (4 núcleos, 8 hilos, 6 MiB cache) estará en el momento de su salida entre los 350 y 450€ sin incluir la memoria y el SSD, respecto al modelo con el Intel i3 7100U (2 núcleos, 4 hilos, 3 MiB cache) que cuesta unos 250€ se puede dudar si esos dos núcleos adicionales y 3 MiB de caché más en el procesador merecen la pena la diferencia de precio. En mi caso estoy estoy dispuesto a pagarlo queriendo tener algo significativamente con mejor rendimiento teórico que lo que tenía.

He revisado algunos análisis de los NUC y me han gustado, en este por ejemplo se explica cómo instalar la memoria, el SSD, como es la BIOS/UEFI y sus opciones de configuración como por ejemplo el ring que puede mostrar la actividad del SSD y se pueden personalizar los colores, también muestra el rendimiento en algunos juegos. Y en otro la gráfica HD 620 es suficiente para jugar a Diablo 3 a 30 fotogramas por segundo en un resolución de 1080p bajando detalles, esta gráfica integrada equivale a una dedicada NVIDIA 920m o GeForce 730 que no está del todo mal para un jugador ocasional si no importa jugar bajando algunos detalles de calidad. En GNU/Linux es posible jugar a juegos destinados a Windows con PlayOnLinux.

El uso que le daré es el de programación, virtualización, contenedores Docker, navegación, ofimática, leer PDF, tal vez algún juego ocasional, quizá Diablo 3 si pudiese, y usando GNU/Linux con la distribución Arch Linux. En un futuro lo quiero como equipo servidor dedicado personal con por ejemplo Nextcloud.

Los Gigabyte Brix ya hay algunos modelos con los Intel i5 8250U a un precio de unos 440€, sin embargo, no me gusta que no tienen luz indicador de actividad de SSD y creo que su BIOS/UEFI es en modo texto. La luz de actividad de SSD me parece importante para saber si en algún momento el ordenador se queda bloqueado o por algún tipo de problema lee, o peor escribe, constantemente al disco duro cuando no debería. Los Zotac están dotados de una buena cantidad de puertos USB, incluso algunos tiene dos conexiones de red pero son algo caros y la mayoría de sus modelos están orientados a gamers, no son fáciles de encontrar ni siquiera en Amazon ni en PC Componentes que es donde compraré finalmente el equipo. De MSI Cubi no hay muchos modelos y aún no he visto ninguno anunciado con un Intel de 4 núcleos. Los Slimbook ONE me gustaban pero los modelos con los Intel de 4 núcleos solo tienen una ranura de memoria, se les pueden instalar 32 GiB… cuando haya módulos de memoria de 32 GiB, ahora me tendría que conformar con 16 GiB.

También he seguido los NUC con un Intel Core i3 7100U sin embargo tiene solo 2 cores y 4 hilos con 3 MiB de memoria será algo mejor que el Intel i3 3210M que tenía pero no me parece una mejora significativa habiendo pasado 5 años y a pesar de que el 7100U está fabricado a 14 nanómetros y el 3210M a 22 nanómetros, los NUC con Intel i7 8650U son más caros, sobre los 580€ y teniendo en cuenta que la memoria y SSD hay que comprarlos aparte. Los NUC más económicos sobre los 175€ con Intel Pentium J5005 solo admiten 8 gigas como máximo y me parece que están limitados artificialmente a ese tamaño máximo de memoria. En Aliexpress hay productos similares a los NUC con procesador i5 8250U pero a ver quien se la juega a importar desde China por aduanas y con la incertidumbre de lo que llega y que tal funciona, también he estado mirando placas ARM aunque no con el objetivo que sea mi equipo principal, 7+ computadoras baratas del tamaño de una tarjeta de crédito basadas en GNU/Linux y ARM, como la Rock64 que tiene 4 gigas pero siguiendo su desarrollo y foros no son pocos los problemas que la gente crea en su repositorio de Github con lo que me da que pensar que la experiencia podría ser algo frustrante, la arquitectura x86/x64 es mucho más compatible, en ARM cada placa es un mundo aparte de que su rendimiento es mucho más limitado.

Preferiría un microprocesador AMD ya que solo están afectados por algunas variantes de Spectre, pero AMD no tiene tanta diversidad de productos como tiene Intel, no tienen nada parecido a los Intel NUC y en portátiles prácticamente todos los modelos equipan un Intel, quizá cambia ahora algo con los Ryzen. Por rendimiento y precio posiblemente elegiría un AMD Ryzen 2400G pero de momento las placas con el chipset B450 para sacarle el máximo rendimiento aún no están disponibles, en la generación 1xxx de los Ryzen no hay modelos con gráfica integrada, tendría que ser un mini-ITX y el equipo me lo tendría que montar yo, no es difícil pero si tuviese algún imprevisto o incompatibilidad sería un problema por tener que devolver piezas y buscar otras, además no estoy seguro del ruido que haría, lo quiero muy silencioso al menos en tareas ofimáticas, navegación por internet y cosas simples, no estoy seguro de que lo sea con el ventilador de la CPU y fuente de alimentación. Ocupa más que un NUC para mi importante si en un futuro le quiero dar uso como ordenador secundario, servidor personal o quisiera traspasarlo. Pero por 400€ se tiene un ordenador muy decente en plataforma AMD Ryzen a falta de memoria y SSD.

La pantalla que estoy siguiendo es una 2K de BenQ PD2700Q en tamaño de 27”, 4K me parece excesiva resolución para ese tamaño de pantalla, a su máxima resolución en una 27” 4K las cosas ven muy pequeñas y tendría que escalarla a 2K, busco que sea IPS ya que los colores en este tipo de paneles se ven significativamente mejor que en un panel TN, uno al lado del otro la diferencia es clara. Apreciaré una mejora notable en la calidad de la pantalla de la que tenía en el portátil Sony. No es barata pero es algo que no necesitan renovarse tan a menudo como el ordenador seguramente pueda tener un uso durante una década si no presenta ningún problema de funcionamiento. Otros aspectos interesantes son ser regulable en altura y horizontalmente, colocable en posición vertical y puertos USB, HDMI y DisplayPort por otro lado una información en pantalla o OSD aceptable y de fácil configuración.

Entre otras cosas están el teclado y ratón que me conformo con un modelo básico y barato como el Logitech MK120 y una alfombrilla que cubra la mesa.

Cuando realmente compre el equipo publicaré varios artículos con el unboxing, instalación, análisis, uso y opinión personal de varios de ellos.


Variable not found: Enlaces interesantes 327

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

.NET / .NET Core

ASP.NET / ASP.NET Core

Azure / Cloud

Conceptos / Patrones / Buenas prácticas

Data

HTML / CSS / Javascript

Visual Studio / Complementos / Herramientas

Xamarin

Otros

Publicado en Variable not found.

Variable not found: ¿Dónde está la directiva @helper de Razor en ASP.NET Core?

$
0
0
ASP.NET CoreCon ASP.NET MVC 5 y anteriores solíamos utilizar @helper para crear porciones de HTML reutilizables en el interior de nuestras vistas, tanto para conseguir un código más limpio como para abrazar el principio DRY (Don’t Repeat Yourself), tan frecuentemente apaleado en la capa de presentación.

Recordaréis que esta directiva permitía crear “funciones” en cuyo interior podíamos escribir código Razor (mezclando marcado y C#) que podía ser invocado desde distintos puntos:
@* File: Test.cshtml *|

@Multiplication(2)
@Multiplication(3)

@helper Multiplication(int x)
{
<h2>Multiplication table of @x</h2>
<ul>
@for (var i = 1; i <=10; i++)
{
<li>
@x * @i = @(x * i)</li>
}
</ul>
}
Además de definirlos y consumirlos desde la misma vista, también era posible crear helpers globales introduciéndolos en App_Code, aunque esta opción me gustaba menos y creo que no la utilicé jamás en aplicaciones reales.
Pues bien, por algunas extrañas razones, en ASP.NET Core la directiva @helper no está disponible, lo que puede complicarnos un poco a la hora de portar vistas antiguas o, simplemente, cuando queramos usarla para mejorar la legibilidad de nuestro código.

¿Podemos conseguir algo similar en ASP.NET Core?

En realidad, en ASP.NET Core existen muchas fórmulas para reutilizar código de marcado; es relativamente sencillo crear HTML helpers, view components, tag helpers o vistas parciales, que nos permitirían conseguirlo. Sin embargo, en mi opinión, ninguna de estas opciones ofrece una solución en determinados escenarios tan elegante, eficiente y fácil de escribir como @helper.

Pero bueno, ciertamente existe una forma que, aunque no con la misma limpieza, al menos nos permite acercarnos un poco a nuestra añorada directiva ;)

El truco consiste en crear un delegado en forma de función lambda Func<T, IHtmlContent>, cuyo cuerpo podemos expresar utilizando sintaxis Razor, como en el siguiente ejemplo:
@* File: Test.cshtml *|
@{
Func<int,IHtmlContent> Multiplication = @<text>
<h2>Multiplication table of @item</h2>
<ul>
@for (var i = 1; i <=10; i++)
{
<li>
@item * @i = @( item * i)</li>
}
</ul>
</text>;
}

@Multiplication(2)
@Multiplication(3)
Pero ojo, que aunque a priori pueda parecer bastante similar a @helper, encontraremos varios inconvenientes:
  • Primero, que al tratarse de una definición inline, sólo puede ser utilizada después de haber sido definida. En la práctica, quiere decir que debemos implementar estas funciones muy al principio de la vista para que estén disponibles en ella.
     
  • Su definición y uso es estrictamente local al archivo actual, es decir, no podemos crearla en _ViewImports.cshtml o en _ViewStart.cshtml y esperar que esté disponible en todas las vistas.
     
  • Siempre necesitaremos especificar un tipo para @item en el primer parámetro genérico, incluso cuando no sea necesario. O sea, estas lambdas son obligatoriamente de la forma Func<T, IHtmlContent>, siendo T el tipo de item. Si el código de marcado no usa @item, podemos especificarlo como object o dynamic y luego pasar un nulo al invocarlo:
    Func<object, IHtmlContent> Time = @<h1>@DateTime.Now</h1>;
    ...
    @Time(null)
En definitiva, aunque con la solución que hemos visto podemos acercarnos algo, aún estamos lejos de nuestro querido @helper. Afortunadamente, en muchos issues de Github podemos encontrar referencias y comentarios relativos a la intención inicial del equipo de ASP.NET Core de traerlo de vuelta, aunque ciertamente no existen fechas ni señales del avance en este sentido :(

Publicado en Variable not found.

Blog Bitix: Hemeroteca #13

$
0
0

El primer semestre del 2018 ya ha pasado. Estos primeros meses he publicado 38 artículos sobre la temática habitual de esta bitácora como programación, software libre, GNU/Linux algunos de opinión relacionados con la tecnología. Las visitas e ingresos de AdSense no han crecido tanto como en ocasiones anteriores pero se han mantenido a un nivel similar sobre los 30K páginas vistas y los 30€ de ingresos en AdSense que no están nada mal.

Dado que desde hace unos cuantos meses no tengo ordenador propio y solo dispongo de el del trabajo normalmente solo los fines de semana no he podido investigar, probar tantas cosas que me gustaría y he publicado más artículos de opinión que de software libre y GNU/Linux. Como comento en algunos de los artículos publicados más o menos ya tengo decidido que mi siguiente equipo será un Intel NUC pero estoy esperando a que salgan esta segunda mitad los Bane Canyon para que el salto que experimente sea notable tanto en el microprocesador con un Intel Core i5 8250U o 8259U, 4 núcleos y 8 hilos, 6 MiB de caché y 32 GiB de memoria sobre lo que tenía antes un Intel Core i5 3210M, 3 MiB de caché, 2 núcleos, 4 hilos y 8 GiB de memoria. Con tal cantidad de memoria podré hacer algunas pruebas con contenedores y virtualización que con solo 8 GiB de memoria ya incluso se me quedaba escaso. Cuando adquiera este nuevo equipo publicaré varios artículos con el desempaquetado o unboxing y el análisis de varios de esos componentes.

Evolución Analytics y AdSense

Entre los artículos sobre programación han estado los habituales sobre Java, destacando las novedades de Java 10, un par sobre Apache Tapestry. Como resolver varios de los problemas clásicos de sincronización, programación concurrente en Java, Webjars, …

En la categoría de software libre o GNU/Linux como tener una consola de juegos retro con una Raspberry Pi, varias computadoras similares a la Raspberry Pi.

En la categoría de opinión están el importante problema de seguridad que se hacía público a principio de año y que afectaba a todos los microprocesadores de Intel fabricados desde hace una década con Meltdown. Intel, AMD y ARM afectados otras variantes denominadas Spectre. Como el hardware estos microprocesadores es defectuoso ni solucionable por microcódigo solo se ha podido mitigar mediante parches de software en los nucleos de los sistemas operativos y compiladores que en cualquier caso pueden suponer una merma en el rendimiento. Aún no se conoce un software capaz de aprovechar estos fallos de seguridad pero no quiere decir que no se descubran. Afecta aún más si cabe a entornos de computación en la nube al compartirse los recursos de computación, en estos entornos es especialmente grabe por seguridad ya que el fallo permite leer la memoria del kernel, aplicaciones, contenedores, datos, claves, …

También publiqué un artículo el ordenador con las opciones que barajaba, una opinión sobre el Slimbook AIO Curve y cómo internet está transformando el sector del comercio y distribución o mi opinión de que me quedo GNU/Linux sobre un Mac. También los artículos con las opciones que estoy tomando para comprar equipo ya no a mucho tiempo tardar.

Para finalizar otro artículo fuera de tema del habitual de este blog con los plantones de roble que tengo, como han crecido y como están desde que los planté el año pasado. Aunque aún no lo he publicado algunos están mostrando síntomas de fallecimiento y lo que es peor no tengo claro por que si por la cantidad de agua, excesiva luz directa del sol, humedad, calor, …

Blog Bitix: Decidido a comprar un Intel NUC entre las opciones que he evaluado

$
0
0
Intel

El ordenador portátil que tenía sigue siendo perfectamente útil, sin embargo, en algunos casos concretos de mi uso la cantidad de memoria que tenía se me estaba quedando corta y cuando me pasa esto suelo aprovechar si alguien de mi entorno necesita ordenador traspasarlo y yo comprarme otro nuevo.

El ordenador que tenía era un Sony VAIO de finales del 2012 con un procesador Intel i3 3210M con gráfica integrada HD 4000, 8 GiB de memoria, un disco duro de estado sólido Samsung 840 EVO de 256 GiB con interfaz SATA y una pantalla de resolución 1600x900. Durante todo este tiempo me ha funcionado a la perfección, incluso con su gráfica me fue suficiente para un entorno de escritorio GNOME con GNU/Linux y he acabado muy contento con la marca Sony al contrario de mi anterior portátil Dell XPS 1530 de la que no pienso comprar nunca nada de esta marca, quizá tuve mala suerte pero el portátil Dell no fue barato, no acabé contento con la calidad del producto pasado el encantamiento inicial y al final acabó totalmente muerto sin ni siquiera encenderse.

Con lo que desde hace unos meses he empezado a barajar opciones para comprar equipo con los requisitos que tengo de ser lo más pequeño posible, silencioso, con 32 GiB de memoria, procesador con mínimo 4 cores y 8 hilos, no necesito tarjeta gráfica dedicada ya que no jugaré a juegos o una integrada con bajar calidad de detalles me servirá a modo ocasional. También quería una pantalla externa de 25” o 27” con resolución de 2K para mayor comodidad y evitar problemas por estar con la cabeza medio agachada durante bastante tiempo. Habiendo pasado 5 años desde mi anterior portátil Sony quiero que el ordenador sea un salto significativo en lo que tenía por eso el requerimiento de los 4 cores, los 32 GiB de memoria y la pantalla 2K. La memoria a pesar del caro precio de la DDR4 en el momento de este artículo. El SSD es la mejor inversión para mejorar el rendimiento que uno puede hacer, más que el procesador. El SSD probablemente elija uno en formato M.2 con interfaz NVMe que tienen una tasa de transferencia 3 veces superior a los SSD con interfaz SATA que ya son rápidos, los NVMe son algo más caros pero no mucho más.

He barajado varias opciones principalmente ordenadores en factor de forma pequeños como los Intel NUC, Gigabyte Brix, Zotac, MSI Cubi, Slimbook ONE, Slimbook PRO2 o AMD Ryzen montando un mini-ITX. Ya estoy casi decidido a lo que compraré y no quiero esperar mucho más a tener equipo propio de cuando se comercialicen y aunque estoy aguantando con un Mac del trabajo comentando Tu con tu macOS yo con mi GNU/Linux. Será con mucha probabilidad un Intel NUC Bean Canyon que se lanzarán en la segunda mitad del 2018.

A pesar de saber que todos los procesadores Intel de la última década está afectados por los importantes problemas de seguridad Meltdown y Spectre que se están mitigando por software, de momento no se ha descubierto una forma de aprovecharlos pero quizá en un futuro se pueda y afecte de forma importante al rendimiento para corregirlos si es que se puede. Pero es que el resto de opciones he ido descartando por otros motivos.

MeltdownSpectre Logotipos de Meltdown y Spectre

El precio que calculo tendrá el Intel NUC Bean Canyon con procesador Intel i5 8250U (4 núcleos, 8 hilos, 6 MiB cache) estará en el momento de su salida entre los 350 y 450€ sin incluir la memoria y el SSD, respecto al modelo con el Intel i3 7100U (2 núcleos, 4 hilos, 3 MiB cache) que cuesta unos 250€ se puede dudar si esos dos núcleos adicionales y 3 MiB de caché más en el procesador merecen la pena la diferencia de precio. En mi caso estoy estoy dispuesto a pagarlo queriendo tener algo significativamente con mejor rendimiento teórico que lo que tenía.

He revisado algunos análisis de los NUC y me han gustado, en este por ejemplo se explica cómo instalar la memoria, el SSD, como es la BIOS/UEFI y sus opciones de configuración como por ejemplo el ring que puede mostrar la actividad del SSD y se pueden personalizar los colores, también muestra el rendimiento en algunos juegos. Y en otro la gráfica HD 620 es suficiente para jugar a Diablo 3 a 30 fotogramas por segundo en un resolución de 1080p bajando detalles, esta gráfica integrada equivale a una dedicada NVIDIA GeForcd 920m laptop o GeForce 730 desktop que no está del todo mal para un jugador ocasional si no importa jugar bajando algunos detalles de calidad. En GNU/Linux es posible jugar a juegos destinados a Windows con PlayOnLinux.

Investigando más he visto también el Intel i5 8259U, solo cambia el último número pero la diferencia es importante en el apartado gráfico ya que este en vez de una UHD 620 lleva una Iris Pro 655 que es nada más y nada menos el doble de potente en teoría gracias a que tiene el doble de execution units, shading units y memoria dedicada de 128 MiB (que la UHD 620 no tiene). No llegará al nivel de una gráfica dedicada de NVIDIA o AMD pero es suficiente para el jugador ocasional.

El uso que le daré es el de programación, virtualización, contenedores Docker, navegación, ofimática, leer PDF, tal vez algún juego ocasional, quizá Diablo 3 si pudiese, y usando GNU/Linux con la distribución Arch Linux. En un futuro lo quiero como equipo servidor dedicado personal con por ejemplo Nextcloud.

Los Gigabyte Brix ya hay algunos modelos con los Intel i5 8250U a un precio de unos 440€, sin embargo, no me gusta que no tienen luz indicador de actividad de SSD y creo que su BIOS/UEFI es en modo texto. La luz de actividad de SSD me parece importante para saber si en algún momento el ordenador se queda bloqueado o por algún tipo de problema lee, o peor escribe, constantemente al disco duro cuando no debería. Los Zotac están dotados de una buena cantidad de puertos USB, incluso algunos tiene dos conexiones de red pero son algo caros y la mayoría de sus modelos están orientados a gamers, no son fáciles de encontrar ni siquiera en Amazon ni en PC Componentes que es donde compraré finalmente el equipo. De MSI Cubi no hay muchos modelos y aún no he visto ninguno anunciado con un Intel de 4 núcleos. Los Slimbook ONE me gustaban pero los modelos con los Intel de 4 núcleos solo tienen una ranura de memoria, se les pueden instalar 32 GiB… cuando haya módulos de memoria de 32 GiB, ahora me tendría que conformar con 16 GiB.

También he seguido los NUC con un Intel Core i3 7100U sin embargo tiene solo 2 cores y 4 hilos con 3 MiB de memoria será algo mejor que el Intel i3 3210M que tenía pero no me parece una mejora significativa habiendo pasado 5 años y a pesar de que el 7100U está fabricado a 14 nanómetros y el 3210M a 22 nanómetros, los NUC con Intel i7 8650U son más caros, sobre los 580€ y teniendo en cuenta que la memoria y SSD hay que comprarlos aparte. Los NUC más económicos sobre los 175€ con Intel Pentium J5005 solo admiten 8 gigas como máximo y me parece que están limitados artificialmente a ese tamaño máximo de memoria. En Aliexpress hay productos similares a los NUC con procesador i5 8250U pero a ver quien se la juega a importar desde China por aduanas y con la incertidumbre de lo que llega y que tal funciona, también he estado mirando placas ARM aunque no con el objetivo que sea mi equipo principal, 7+ computadoras baratas del tamaño de una tarjeta de crédito basadas en GNU/Linux y ARM, como la Rock64 que tiene 4 gigas pero siguiendo su desarrollo y foros no son pocos los problemas que la gente crea en su repositorio de Github con lo que me da que pensar que la experiencia podría ser algo frustrante, la arquitectura x86/x64 es mucho más compatible, en ARM cada placa es un mundo aparte de que su rendimiento es mucho más limitado.

Preferiría un microprocesador AMD ya que solo están afectados por algunas variantes de Spectre, pero AMD no tiene tanta diversidad de productos como tiene Intel, no tienen nada parecido a los Intel NUC y en portátiles prácticamente todos los modelos equipan un Intel, quizá cambia ahora algo con los Ryzen. Por rendimiento y precio posiblemente elegiría un AMD Ryzen 2400G pero de momento las placas con el chipset B450 para sacarle el máximo rendimiento aún no están disponibles, en la generación 1xxx de los Ryzen no hay modelos con gráfica integrada, tendría que ser un mini-ITX y el equipo me lo tendría que montar yo, no es difícil pero si tuviese algún imprevisto o incompatibilidad sería un problema por tener que devolver piezas y buscar otras, además no estoy seguro del ruido que haría, lo quiero muy silencioso al menos en tareas ofimáticas, navegación por internet y cosas simples, no estoy seguro de que lo sea con el ventilador de la CPU y fuente de alimentación. Ocupa más que un NUC para mi importante si en un futuro le quiero dar uso como ordenador secundario, servidor personal o quisiera traspasarlo. Pero por 400€ se tiene un ordenador muy decente en plataforma AMD Ryzen a falta de memoria y SSD.

La pantalla que estoy siguiendo es una 2K de BenQ PD2700Q en tamaño de 27”, 4K me parece excesiva resolución para ese tamaño de pantalla, a su máxima resolución en una 27” 4K las cosas ven muy pequeñas y tendría que escalarla a 2K, busco que sea IPS ya que los colores en este tipo de paneles se ven significativamente mejor que en un panel TN, uno al lado del otro la diferencia es clara. Apreciaré una mejora notable en la calidad de la pantalla de la que tenía en el portátil Sony. No es barata pero es algo que no necesitan renovarse tan a menudo como el ordenador seguramente pueda tener un uso durante una década si no presenta ningún problema de funcionamiento. Otros aspectos interesantes son ser regulable en altura y horizontalmente, colocable en posición vertical y puertos USB, HDMI y DisplayPort por otro lado una información en pantalla o OSD aceptable y de fácil configuración.

Entre otras cosas están el teclado y ratón que me conformo con un modelo básico y barato como el Logitech MK120 y una alfombrilla que cubra la mesa.

Otras personas no se lo piensan tanto pero en un área del que más o menos entiendo algo me gusta saber con mucho detalle lo que estoy comprando. Una vez que uno comprende las especificaciones técnicas de los productos, que diferencias hay entre cada una de ellas, se entiende las diferencias de precios y se compra con criterio.

No es lo mismo comprar un NUC7i3BNH con un i3-7100 que tiene una gráfica HD Graphics 620 con un precio de unos 250€ que un NUC7i5BNH con un i5-7260U que tiene un gráfica Iris Plus 640 con un precio de unos 360€.

La diferencia del precio está en que el procesador i5-7260U que tiene 4 MiB de cache por 3 MiB del i3-7100 que le proporciona algo más de rendimiento y la gráfica Iris del primero es el doble de potente con 48 execution units, 384 shading units, con memoria gráfica dedicada de 64 MiB eDRAM para proporcionar unos 700800 GFLOPS de rendimiento contra la gráfica HD Graphics 620 que tiene 24 execution units, 192 shading units, 0 MiB eDRAM (sin memoria dedicada) con unos 400 GFLOPS. Aún siendo ambas gráficas integradas para jugadores ocasionales en todo caso mucho menos capaces que una dedicada con su memoria más veloz, la Iris Plus 640 del i5-7260U es el doble de potente que la HD Graphics 620 del i3-7100. Por este motivo se justifica la diferencia de precio entre los modelos. Dependiendo del uso que se le dé al NUC será preferible un modelo u otro.

En estas dos páginas se pueden conocer muchos detalles de los procesadores y gráficas de Intel.

Cuando realmente compre el equipo publicaré varios artículos con el unboxing, instalación, análisis, uso y opinión personal de varios de ellos.

Variable not found: ¡Microsoft MVP 2018-2019!

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

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

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

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

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

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

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

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

Desarrollador supermotivado
Source: Giphy

Publicado en Variable not found.

Variable not found: Enlaces interesantes 328

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

.NET / .NET Core

ASP.NET / ASP.NET Core

Azure / Cloud

Conceptos / Patrones / Buenas prácticas

Data

HTML / CSS / Javascript

Visual Studio / Complementos / Herramientas

Xamarin

Otros

Publicado en Variable not found.

Variable not found: El filtro [ApiController] en ASP.NET Core MVC 2.1

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

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

Obligatoriedad de usar rutas explícitas

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

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

Inferencia del origen de parámetros

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

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

Cuando entra una petición dirigida hacia una acción perteneciente a un controlador decorado con [ApiController], el binder cargará sus parámetros y aplicará automáticamente las validaciones asociadas a los datos de entrada. Como es habitual, el resultado de dicha validación lo tendremos en la propiedad ModelState.IsValid.
Pues bien, por defecto, el framework comprobará todos los objetos recibidos, y retornará un error HTTP 400 cuando se produzcan errores de validación. A continuación puedes ver un ejemplo de acción que devuelve el mismo objeto que recibe como parámetro, y el resultado obtenido de algunas peticiones:
publicclass Friend
{
[Required]
publicstring Name { get; set; }
[Range(0, 120)]
publicint Age { get; set; }
}

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

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

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

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

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

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

Personalización o desactivación de algunos comportamientos

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

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

Publicado en Variable not found.

Blog Bitix: Qué es un SUT, fake, Stub, Mock y Spy en las pruebas con un ejemplo

$
0
0

Las pruebas unitarias y de integración tratan de probar que el comportamiento del sujeto bajo prueba es el esperado. Este sujeto bajo prueba usará colaboradores que en las pruebas deben ser reemplazados por fakes para probar las condiciones deseadas del de sujeto bajo prueba. Depdendiendo del comportamiento asignado al colaborador tenemos varios tipos: Stub, Mock o Spy.

Al desarrollar pruebas unitarias o de integración se emplean varios términos que no son imprescindibles conocer para hacer una prueba pero si es recomendable conocerlos para saber que diferencias hay entre ellos y saber que posibilidades tenemos para construir la prueba. Los términos básicos son sujeto bajo prueba o subject under test, fake, mock, stub y spy.

En una prueba el objeto bajo prueba es el elemento del que se quiere probar su comportamiento y que las pruebas verificarán que para los casos de prueba funciona según lo esperado. Dado que raramente el sujeto bajo prueba funciona de forma aislada sino que que se comunica con otros elementos estos colaboradores han de reemplazarse preprogramado su comportamiento, a los colaboradores se les denomina impostores o fakes ya que no son los objetos reales que se usan en el programa en ejecución pero simulan su comportamiento.

Según el tipo de fake que sea un objeto están los siguientes tipos:

  • Stub: es un fake al que se le reprograman sus valores de retorno y se proporciona al objeto bajo prueba teniendo control sobre cuales son los valores que usa el sujeto bajo control.
  • Mock: es un fake que después de terminada la prueba puede ser examinado para comprobar si las interacciones con el sujeto bajo prueba han sido las correctas, se puede probar si un método ha sido llamado o cuántas veces ha sido llamado junto con sus parámetros. Adicionalmente al igual que los Stub puede preprogramarse su comportamiento. Si solo se necesita preprogramar los resultados se suele utilizar un Stub y solo cuando además se necesitan verificar las interacciones se usa un Mock.
  • Spy: es un fake en el que solo un subconjunto de métodos son fake y a menos que explícitamente sean mockeados el resto de métodos son los reales.

Los colaboradores permiten hacer los casos de prueba deterministas haciendo que siempre produzcan el mismo resultado y las pruebas no se vean afectados por condiciones externas, los colaboradores evitan efectos colaterales, evitan depender del entorno de computación, hacen que las pruebas sean rápidas por no necesitar de sistemas externos como una base de datos o servicio de red y permiten probar comportamientos inusuales en un entorno real.

En el ejemplo se quiere probar un sistema de alarma que cuando detecte en tres mediciones consecutivas que la temperatura está por encima de cierto valor suene una alarma. Los elementos de este sistema serán una clase Monitor que obtiene las temperaturas de un sensor y si detecta la condición de una temperatura elevada hace sonar una alarma. El monitor será el sujeto bajo prueba y el sensor y la alarma los colaboradores. El sensor será un fake de tipo Stub ya que solo se necesita preprogramar sus valores de retorno de temperaturas y la alarma un fake de tipo Mock ya que se debe comprobar que el monitor ha llamado una vez al método que haría sonar la alarma, esto es se necesitan verificar las interacciones.

Sistema de control de temperatura simulado

Se pueden hacer más casos de prueba como por ejemplo probar que tras dos temperaturas altas siendo la siguiente baja y posteriormente otra alta la alarma no es disparada.

En el libro Java Testing with Spock explican toda esta teoría básica de pruebas además de explicar bastante detalladamente todas las posibilidades de la herramienta de testingSpock.

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

Referencia:

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

$
0
0

Arrays con nombre dinámico en Bash

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

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

Arrays con nombre dinámico

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

Ejemplo para Bash < 4.3

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

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

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

evalecho \${$REFERENCIA[2]}

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

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

Ejemplo para Bash >= 4.3

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

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

echo${REFERENCIA[2]}

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

Foto principal: unsplash-logoRuben Ortega

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

Blog Bitix: Pruebas funcionales con Geb en una aplicación web Java

$
0
0
Geb
Java

Las pruebas automatizados permiten comprobar que una aplicación se comporta de la manera esperada en los casos probados, creando pruebas automatizadas se evita hacer las aburridas y repetitivas pruebas manuales que consumen gran cantidad de tiempo. Hay diferentes categorías de pruebas: unitarias, de integración y las funcionales. Para las pruebas unitarias y de integración en la plataforma Java unas de las más populares herramientas son JUnit y Spock, para las pruebas funcionales están Selenium y la herramienta que explicaré en este artículo Geb que puede usarse junto con Spock haciendo que el código de los teses sea muy descriptivo.

Geb soporta una APi similar a la que emplea jQuery para la interacción con los elementos de la página bajo pruebas. Este ejemplo prueba a ir a la página del buscador Google y que el resultado es el esperado usando alguna de las múltiples formas de interacción con el contenido de la página.

Para hacer más sencillos las pruebas se pueden describir las páginas, sus URLs y los elementos que contienen. Para ello hay que crear una clase que extienda de Page y definir propiedades como url, at y content, se pueden incluso definir métodos. En la documentación de Geb está más detallado la definición de las páginas. También se pueden crear módulos para definir elementos comunes a varias páginas.

La automatización de las pruebas además de comprobar que la página devuelva es la esperada, en el caso de estos ejemplo con una propiedad meta o con el título de la página, consiste en realizar las interacciones que un usuario realizaría como introducir datos en formularios, hacer clic en elementos de una página y comprobar la presencia de elementos que valide la prueba. Con esta herramienta se pueden probar los casos y flujos funcionales más importantes de la aplicación como sería el proceso de compra en una aplicación de comercio electrónico y la búsqueda, alta y modificación de un registro en la aplicación de gestión.

En este ejemplo se realiza una búsqueda en Google y se comprueba el resultado devuelto. Primero se accede a ella con la sentencia to, se introduce el texto de búsqueda Chuck Norris y se pulsa el botón de búsqueda. La comprobación consiste en asegurar que la página devuelta es la página de resultados de búsqueda con la sentencia at y que el primer resultado de la búsqueda contiene la palabra Chuck, GoogleHomePage define la página de búsqueda, GoogleResultsPage la página de resultados y GoogleSearchSpec contiene la interacción de la prueba.

Las dependencias de Geb necesarias a incluir en el archivo de configuración de la herramienta de gestión del proyecto usando Gradle son las siguientes:

Usando una aplicación con Spring Boot para ejecutar los teses de integración se debe iniciar la aplicación web previamente con la anotación SpringBootTest mostrado en el caso IndexSpec además de excluir los teses de integración y los unitarios de los funcionales. En el ejemplo con la tarea de Gradle integrationTest se ejecutan los teses de funcionales de Geb.

Con Gradle el informe de resultados de las pruebas se genera en build/reports/tests/integrationTest en una colección de páginas HTML con el siguiente aspecto. Si hubiese algún error se mostraría un mensaje descriptivo del fallo ocurrido. La prueba IndexSpec tarda medio minuto ya que previamente ha de iniciar el servidor de aplicaciones con la aplicación, en este caso usando Spring Boot.

Informe de las pruebas funcionales

Algunas otras herramientas que son ampliamente usadas en proyectos Java son las que comentaba en el artículo Nueva visita a herramientas para un proyecto Java.

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

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

$
0
0

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

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

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

Inteligencia colaborativa:

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

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

Pensamiento de grupo:

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

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

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

 

 

pensamiento de grupo

 (1) Referencias - MIT - Anita Williams.

Bitácora de Javier Gutiérrez Chamorro (Guti): C++ Builder in the requirements

$
0
0

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

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

Koalite: APIs con Node, TypeScript, Koa y TypeORM

$
0
0

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

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

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

Las acciones web

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

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

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

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

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

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

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

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

Las rutas

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

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

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

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

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

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

// routes.ts

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

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

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

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

Los datos

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

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

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

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

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

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

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

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

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

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

El proyecto

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

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

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

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

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

En resumen

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

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

Posts relacionados:

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

Variable not found: Enlaces interesantes 329

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

.NET / .NET Core

ASP.NET / ASP.NET Core

Azure / Cloud

Conceptos / Patrones / Buenas prácticas

Data

HTML / CSS / Javascript

Visual Studio / Complementos / Herramientas

Otros

Publicado en Variable not found.

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

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

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

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

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

El estándar Problem details (RFC7807)

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

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

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

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

Problem details en ASP.NET Core 2.1

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

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

{
id: 19,
productsCount: 22
}

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

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

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

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

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

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

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

Publicado en Variable not found.

Adrianistán: La perlificación de Python

$
0
0

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

Marge Simpson, Los Simpson

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

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

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

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

Lenguajes de programación barrocos

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

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

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

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

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

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

Antoine de SaintExupéry

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

Los procesos comunitarios

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

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

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

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

¿Te ha gustado el artículo?

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

Enlace Amazon.es

Será muy bien recibido

 

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

Variable not found: Task.Factory.StartNew(EnjoySummer, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);

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

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

Costa Ballena, Cádiz
Imagen original

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

¡Felices vacaciones a todos!

Publicado con ánimo vacacional en Variable not found.

Bitácora de Javier Gutiérrez Chamorro (Guti): WinAPI contra C

$
0
0

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

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

Blog Bitix: La librería log4j2 para emitir trazas en aplicaciones Java

$
0
0
Java

La librería log4j2 es la librería sucesora de log4j y logback para emitir las trazas de depuración e información indispensables cuando son requeridas en una aplicación Java. Suele usarse en combinación slf4j ya que esta permite cambiar de librería de logging subyacente sin hacer ningún cambio en la aplicación.

Algunas de las nuevas características de log4j2 son:

  • Rendimiento mejorado usando funcionalidades asíncronas en los loggers.
  • Soporte para múltiples APIs como SL4J, Commongs Logging y java.util.logging (JUL).
  • Sin encadenamientos a la librería al poder en cualquier momento usar cualquier librería compatible con SLF4J.
  • Recarga automática de la configuración sin perder ninguna traza.
  • Filtrado avanzado basado en datos de contexto, marcadores, expresiones regulares y otros componentes.
  • Arquitectura basada en plugins.
  • Soporte de propiedades definidas en archivos de configuración, propiedades del sistema, variables de entorno, el mapa ThreadContext y datos del evento.
  • Soporte de lambdas de Java 8. Las expresiones lambdas no se evalúan si no está activado el nivel de log consiguiendo el mismo efecto que con una sentencia if pero en menos código.
  • Niveles de log personalizados fácilmente definibles sin necesidad de realizar subclases.
  • Recolección de basura reducida lo que evita presión al recolector de basura y mejora el rendimiento de las aplicaciones.

Por defecto, la configuración de log4j2 se describe en un archivo xml aunque también soporta definirlo en un formato menos verboso como yaml. La siguiente aplicación de Spring Boot al iniciarse emite en la consola varios mensajes usando log4j2.

Usando la clase LogManager se obtiene una referencia a la clase Logger con la que se emiten las trazas y que posee diferentes métodos para cada nivel de traza.

Una vez se ha iniciado la aplicación Spring Boot invoca el método run y se emiten las trazas propias de la aplicación después de las que también Spring Boot y otras librerías emiten., en este caso usando texto en forma de arte ascii.

En el archivo de construcción de la aplicación usando Gradle hay que incluir las dependencias de las librerías.

Las trazas son muy importantes por la valiosa información que proporcionan de lo que está sucediendo en una aplicación a los que recurriendo es posible obtener la valiosa información que permite saber que ha sucedido en una determinada acción o que permite descubrir mucho más rápidamente la causa de un error.

En otro artículo ya he comentado como usar marcadores con sl4j y logback para relacionar trazas que son emitidas en diferentes clases o módulos de la aplicación, también se puede hacer con log4j. En siguientes artículos comentaré como transformar un objeto a un mensaje sin necesidad de convertir ese objeto a un String en cada traza de la aplicación donde se use su información y otra forma de relacionar trazas muy útil en aplicaciones web asignando un indenticador única en cada petición y emitiendolo en todas sus trazas, esto permite saber todo lo que ha ocurrido en una petición entre las muchas que se ejecutan concurrentemente por todos los usuarios de la aplicación.

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

Viewing all 2726 articles
Browse latest View live