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

Variable not found: Enlaces interesantes 331

$
0
0

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

Por si te lo perdiste:

.NET / .NET Core

ASP.NET / ASP.NET Core

Azure / Cloud

Data

HTML / CSS / Javascript

Visual Studio / Complementos / Herramientas

Xamarin / Cross-platform

Otros

Publicado en Variable not found.


Picando Código: 2 paquetes de ebooks interesantes: Learn you some Code y Game Development by Pack

$
0
0

La gente de Humble Bundle tiene 2 paquetes de ebooks bastante interesantes. Los ebooks están disponibles en PDF, ePUB y MOBI, por lo que pueden ser leídos en casi cualquier dispositivo. Como se acostumbra en los paquetes Humble Bundle, además de elegir el precio, podemos elegir dónde destinamos el dinero que pagamos, incluyendo una organización de beneficencia.

En el primer bundle se trata de Electronic Frontier Foundation, la fundación sin fines de lucro que defiende nuestros derechos en el mundo digital. Activistas, abogados y tecnólogos que luchan en las cortes y el congreso para proteger la privacidad y libre expresión en línea en todo el mundo. El segundo beneficia a Code.org, fundación sin fines de lucro dedicada a expandir la participación en ciencias de la computación habilitándola en más escuelas, y aumentando la participación de mujeres y estudiantes de color.

Los paquetes:

Humble Book Bundle: Game Development and Learn you some CodeGame Development by Packt– Un paquete con 25 libros sobre desarrollo de videojuegos, incluyendo uno sobre Godot, el motor de desarrollo de videojuegos software libre. Quedan 6 días para comprarlo:

Game Development by Packt

Pagando el monto mínimo de USD 1, obtenemos: Creating a Game with Blender Game Engine, Mastering SFML Game Development, Game Physics Cookbook, Basics of Coding with Unreal Engine 4 y Beginning C++ Game Programming

Pagando USD 8 o más, también obtenemos: Practical Game AI Programming, Modern OpenGL C++ 3D Game Tutorial Series & 3D Rendering, Mastering Unreal Engine 4.x Game Development, Virtual Reality Blueprints, Building a Character using Blender 3D, Unity 2017 Mobile Game Development, Unity 2017 Game Optimization, Practical Game Design y Learning C# 7 By Developing Games with Unity 2017

Pagando USD 15 o más, el paquete incluye: Vulkan Cookbook, Godot Engine Game Development Projects, Swift 3 Game Development, Mastering Unity 2017 Game Development with C#, Getting Started with Unity 2018, Unity 2017 Game AI Programming, Unity 2017 2D Game Development Projects, Unity Virtual Reality Projects, Learning C++ by Creating Games with Unreal Engine 4, Game Development Patterns and Best Practices y Learning C# by Developing Games with Unity

Visita Humble Book Bundle: Game Development

Humble Book Bundle: Learn You Some Code

Learn you some Code tiene algunos títulos muy interesantes a partir de los USD 8, los leería todos. Los de Haskell y Lisp son clásicos (el de Haskell lo empecé alguna vez…). Quedan 13 días para comprarlo:

Humble Book Bundle: Learn You Some Code

Pagando el monto mínimo de USD 1, obtenemos: Automate the Boring Stuff with Python: Practical Programming for Total Beginners, The Linux Command Line: A Complete Introduction, The Book of F#: Breaking Free with Managed Functional Programming, Learn Java the Easy Way: A Hands-On Introduction to Programming y Perl One-Liners: 130 Programs That Get Things Done

Pagando USD 8 o más, también obtenemos: Ruby Under a Microscope: An Illustrated Guide to Ruby Internals, Learn You Some Erlang for Great Good!: A Beginner’s Guide, Learn You A Haskell for Great Good!: A Beginner’s Guide, Clojure for the Brave and True: Learn the Ultimate Language and Become a Better Programmer y Land of Lisp: Learn to Program in Lisp, One Game at a Time!

Pagando USD 15 o más, el paquete incluye: Python Crash Course: A Hands-On Project-Based Introduction to Programming, Python Playground: Geeky Projects for the Curious Programmer, Think Like a Programmer: An Introduction to Creative Problem Solving, The Book of R: A First Course in Programming and Statistics y Wicked Cool Shell Scripts: 101 Scripts for Linux, OS X, and UNIX Systems

Visita Humble Book Bundle: Learn you some Code

Adrianistán: Alojando una web en IPFS

$
0
0

En el primer post vimos como interactuar con IPFS de forma sencilla. Ahora vamos a dar un paso más y vamos a alojar una web en IPFS, aprovechando todas las ventajas de escalabilidad y disponibilidad que nos ofrece la red. Para ello usaremos además otro protocolo llamado IPNS, que sería similar a DNS pero en la red IPFS.

Las páginas ideales para IPFS actualmente son las que siguen el JAMstack, es decir, uso extensivo de JavaScript en el cliente, que podrá conectarse a APIs para obtener/actualizar información. Las APIs no tienen por qué ser centralizadas, ya que JavaScript con WebRTC puede buscar peers, posibilitando APIs descentralizadas.

Generando el contenido estático

El primer paso será generar el contenido estático de la web. Para ello existen herramientas muy conocidas como Jekyll, Hugo o Pelican.

No nos vamos a alargar más en esto, ya que cada herramienta tiene sus pasos. El resultado final será una carpeta con ficheros HTML, CSS, fuentes, imágenes y JavaScript.

Subir a IPFS

Teniendo el nodo IPFS en funcionamiento, subimos la carpeta del modo habitual, en mi caso, voy a subir la página que está en http://adrianistan.eu .

ipfs add -r adrianistan.eu/

Y anotamos el último hash.

Comprobamos que la web es accesible, tanto desde la gateway del nodo, como una externa:

Tanto en el nodo local como en uno externo, la web carga perfectamente con el hash

IPFS tiene direccionamiento por contenido

En el post anterior mencionamos que IPFS direcciona por contenido gracias a los hashes. Esto tiene unas consecuencias interesantes. Por ejemplo, si se añade un archivo duplicado a IPFS, este tiene exactamente la misma dirección, ya que comparten hash. Por otro lado, los documentos no se pueden actualizar, porque entonces su hash cambia. Sin embargo en una web queremos cambiar contenido, ahí entra en acción IPNS.

IPNS, gestión de nombres para IPFS

IPNS es un protocolo parecido en intenciones a DNS que redirige un ID única al hash correspondiente en ese momento. Registramos el hash de la web actual en IPNS.

ipfs name publish HASH

Ahora sí, el hash IPNS puede publicarse por la red, ya que siempre apuntará a la última versión de la web.

Para acceder a recursos a través de IPNS tenemos que cambiar de protocolo, en vez de /ipfs/HASH, tenemos que poner /ipns/HASH. Vale tanto para comandos como para las gateways HTTP.

https://cloudflare-ipfs.com/ipns/QmYDVeoadAzk9ZW6zwJK3E3KHrA1LWLveEdqUv4XAcCjKa/

En cualquier momento podemos comprobar a que dirección IPFS apunta el hash IPNS:

ipfs name resolve QmYDVeoadAzk9ZW6zwJK3E3KHrA1LWLveEdqUv4XAcCjKa

Para actualizar el contenido simplemente se vuelve a repetir el paso de ipfs name publish. IPFS automáticamente modificará la redirección de IPNS.

Los contenidos antiguos no desaparecen, pero pueden no ser accesibles ya que ningún nodo tenga copia de ellos.

DNSLink

Aún así, ir dándole a la gente un hash IPNS es demasiado complicado. Afortunadamente, podemos usar el DNS tradicional para indicar una ruta IPNS y así, como veremos, facilitar bastante las cosas.

Para ello añadimos un campo TXT en los DNS de nuestro dominio. El contenido es el siguiente:

dnslink=/ipns/HASH

Con esto podremos usar /ipns/dominio.com en la red IPFS. Pero todavía hace falta un cliente IPFS.

Afortunadamente, podemos redirigir mediante CNAME a una gateway HTTP de confianza y ¡la web funcionará correctamente! Para ello hay que crear un campo TXT en el subdominio _dnslink con el mismo contenido que el anterior.

Todas las gateways de IPFS soportan DNSLink para que la transición a IPFS sea lo más transparente posible.

Así, finalmente la página carga con un dominio normal y corriente en un navegador normal y corriente.

Fijaos en la URL

De hecho, vosotros mismos podéis acceder:

http://adrianistan.yayeyo.ga

IPFS Companion

Si usamos mucho IPFS, puede que nos interese una extensión que maneje el protocolo ipfs:// . Tanto en Firefox como en Chrome existe IPFS Companion, una extensión que nos permite acceder a contenido IPFS de forma sencilla.

Servicio systemd

Por último, quiero dejar el servicio de systemd necesario para tener el nodo IPFS funcionando constantemente en nuestro ordenador. En este caso, IPFS lo instalé vía Snap.

[Unit]
Description=IPFS daemon

[Service]
ExecStart=/snap/bin/ipfs daemon
Restart=on-failure

[Install]
WantedBy=default.target

sudo cp ipfs.service /etc/systemd/user/

sudo systemctl --user start ipfs.service
sudo systemctl --user enable ipfs.service

Y con esto ya tendríamos suficiente como para jugar con IPFS un buen rato.

La entrada Alojando una web en IPFS se publicó primero en Adrianistán.

Variable not found: ¿Aplicar [Authorize] a todos los controladores MVC de una carpeta?

$
0
0
ASP.NET Core MVCHace unos días, un alumno del curso online de ASP.NET Core en CampusMVP (por cierto, desde hace unas semanas actualizado a la versión 2.1) me planteaba una cuestión que quizás podría interesar a alguien más, por lo que vamos a comentarla por aquí.

Básicamente, la duda era la siguiente:
¿Hay alguna forma sencilla de añadir el atributo [Authorize], pero sólo a los controladores que se encuentren en una carpeta determinada del proyecto, sin tener que aplicarlo uno a uno?
La respuesta rápida es: sí. Bueno, con matices ;) Incluso hay varias opciones, así que vamos a ver algunas de ellas, y de paso repasamos conceptos de ASP.NET Core MVC :)

Opción 1: Usar clases base

La primera forma que se me ocurre, y quizás la más sencilla, es hacer los controladores presentes en la carpeta hereden de una clase base y aplicar los filtros sobre ella, de forma que todos sus descendientes se vean afectados.
[Authorize(Roles="admin")]
public abstract class AdminController: Controller
{
}

...

// En Controllers/DashboardController.cs
public class DashboardController: AdminController
{
// Esto ya estará protegido
// por el [Authorize] de AdminController
}
Ya, me diréis que recorrer todas las clases que nos interesen y hacer que hereden de AdminController nos llevará el mismo tiempo que aplicarles directamente el atributo [Authorize], y es cierto. Sin embargo, si más adelante tuviéramos que modificar los criterios de admisión para estos controladores (por ejemplo, añadir otros roles o policies), sólo tendríamos que tocar en este punto del código.

Opción 2: Usar atributos personalizados

Otra posibilidad sería crear un authorization filter personalizado e introducirlo como filtro global de la aplicación.

El siguiente código muestra un filtro que, establecido de forma global, observaría todas las peticiones entrantes y comprobaría que el usuario esté logado y ostente el rol "admin", pero sólo en aquellas acciones cuyos controladores hayan sido definidos en el espacio de nombres que comience por "MyApp.Controllers.Admin":
public class AdminAuthorizeAttribute : IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
var actionName = context.ActionDescriptor.DisplayName;
if(actionName.StartsWith("MyApp.Controllers.Admin."))
{
var user = context.HttpContext.User;
if (!user.Identity.IsAuthenticated || !user.IsInRole("admin")) {
context.Result = new ForbidResult();
}
}
}
}
Obviamente, no estamos teniendo en cuenta las carpetas físicas en las que se encuentran los controladores, puesto que son simplemente una forma de organizar el código fuente, sino sus namespaces, que es la forma en que se organizan los componentes.
Con esto, ya sólo habría que establecer el filtro como global, algo que conseguimos retocando ligeramente el método ConfigureServices() de la clase Startup:
public void ConfigureServices(IServiceCollection services)
{
[...]
services.AddMvc(opt =>
{
opt.Filters.Add(new AdminAuthorizeAttribute());
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
Fijaos que, quizás de una forma extraña, pero acabamos de definir una convención en nuestra aplicación que podríamos definir así: "todos los controladores del espacio de nombres MyApp.Controllers.Admin" deben estar decorados con el atributo [Authorize]".

Hey, ¿y no traía MVC Core algo para facilitar la implementación de convenciones? Pues sí, y ya hablamos de ello hace bastante tiempo...

Opción 3: Usar convenciones personalizadas

Si echáis un vistazo al enlace anterior, seguro que veis rápidamente que en esta feature del framework MVC es donde tenemos la solución más elegante a nuestro problema.

Básicamente, la idea consiste en introducir código que modifique el ApplicationModel, una estructura en memoria creada por ASP.NET Core MVC en el momento del arranque, que describe todas las "piezas" que componen la aplicación: controladores, acciones, filtros, parámetros, rutas, constraints, etc.

El código que modifica el modelo de aplicación es lo que en el framework llamamos una convención. Por ejemplo, podríamos crear una convención que hiciera que las acciones cuyo nombre acabe por "Post" sean sólo accesibles mediante el verbo HTTP post, o añadir un filtro que compruebe el token JWT a todos los controladores que hereden de una clase determinada, o modificar las rutas en función de cualquier criterio... En definitiva, podemos hacer casi cualquier cosa :)

Suena complejo, ¿verdad? Pues nada más lejos de la realidad. En la práctica, estas convenciones son clases que implementan las interfaces IApplicationModelConvention, IControllerModelConvention, IActionModelConvention o IParameterModelConvention, dependiendo del ámbito en el que vayamos a aplicar nuestra convención.

En nuestro caso, dado que queremos aplicar una convención a los controladores, la interfaz que nos interesa es IControllerModelConvention, cuya signatura es la siguiente:
public interface IControllerModelConvention
{
void Apply(ControllerModel controller);
}
Durante el arranque de la aplicación ASP.NET Core MVC irá invocando sucesivamente este método por cada controlador de nuestra aplicación, enviándonos en el objeto ControllerModel toda la información disponible sobre el mismo. Y, como comentaba antes, lo mejor es que gran parte de esta información puede ser modificada al vuelo.

El siguiente código muestra la convención AdminControllersAreOnlyForAdminsConvention que añade automáticamente el filtro Authorize, configurado apropiadamente, a todos los controladores cuyo espacio de nombres sea el que nos interesa:
public class AdminControllersAreOnlyForAdminsConvention : IControllerModelConvention
{
public void Apply(ControllerModel controller)
{
if (controller.DisplayName.StartsWith("MyApp.Controllers.Admin."))
{
var policy = new AuthorizationPolicyBuilder()
.RequireRole("admin")
.Build();
controller.Filters.Add(new AuthorizeFilter(policy));
}
}
}
Para que sea tenida en cuenta, esta convención se debe añadir al registro de servicios de la clase de inicialización Startup como una opción de configuración del _framework MVC:
services.AddMvc(opt =>
{
opt.Conventions.Add(new AdminControllersAreOnlyForAdminsConvention());
});
Y de esta forma tan sencilla, de nuevo hemos llegado a nuestro objetivo :)

Publicado en Variable not found.

Picando Código: The Legend Of Zelda: Breath of the Wild en Game Boy Color

$
0
0

La Leyenda de Zelda es de esas sagas que sigue publicando nuevos títulos y reinventándose. El año pasado Breath Of The Wild sorprendió al mundo rompiendo récords de ventas y revolucionando el género open world. Link’s Awakening fue el primer Zelda que jugué. Con sólo 8 bits, y a través de la pantalla verde del Game Boy que me prestaba mi vecino, el juego lograba transportarme a Koholint Island y vivir las aventuras como Link intentando despertar al Wind Fish. Por la intriga y el sentimiento de aventura y misterio que me despertaba (y el factor nostalgia) sigue siendo uno de mis juegos favoritos. Con Breath Of The Wild volví a vivir la experiencia, esta vez en un mundo mucho más amplio y poblado.

El siguiente video muestra cómo podría verse una versión “Link’s Awakeningesca” de Breath Of The Wild. Como si fuera poco los gráficos y la música, usan el modelo de Game Boy Color Atomic Purple que compré hace tantos años y donde volví a jugar varias veces esta aventura con Link’s Awakening DX:

Después de mirarlo no sé si ponerme a jugar a Breath Of The Wild o Link’s Awakening…

Picando Código: Hackea con Tor en México 🇲🇽

$
0
0

TorEl proyecto Tor organiza una serie de eventos en Ciudad de México a partir de la semana que viene. Sumamente interesantes, para aprender qué tienen planeado, cómo tener un repetidor de Tor, y cómo unirse a la comunidad. A continuación la información de los eventos, desde el blog oficial de Tor:

A finales de septiembre, personas que colaboran con Tor en todo el mundo se reunirán en la Ciudad de México por uno de nuestros encuentros bianuales. Hablaremos sobre el futuro de Tor como organización y decidiremos en qué protocolos y características enfocaremos nuestros esfuerzos. Es una oportunidad para que los equipos distribuidos en Tor pasen tiempo juntos y definan en qué trabajar en los próximos meses y años.

Como parte de este encuentro, también tendremos dos días de hackatón abierto para que todos pueden sumarse. Los días de puertas abiertas durante el encuentro en Ciudad de México serán el martes 2 de Octubre y el miércoles 3 de Octubre en el Sheraton María Isabel. Para obtener más información, consultá la wiki de la reunión.

¿Qué son los días abiertos?

Estos días son oportunidades para desarrolladores y personas sin experiencia técnica para venir y pasar el rato con algunos miembros del equipo de Tor. Aquí se puede obtener más información acerca de Tor, hackear algo con nosotros o simplemente conocer a gente interesante que también esté interesada en el software libre y de código abierto, la privacidad en línea y la libertad de expresión.

Estos días están abiertos a todos, independientemente de su nivel de habilidad técnica. Si estás interesado en contribuir con Tor (ya sea como voluntario o por un puesto pagado), este es también un buen momento para aprender más sobre lo que estamos haciendo y unirte a nuestra comunidad.

Este año, tendremos varias sesiones diseñadas para los recién llegados. Estas incluyen Introducción a Tor para principiantes (en inglés y en español) y “State of Onion” una charla sobre dónde estamos y hacia dónde vamos. Estaremos desarrollando el cronograma hasta los mismos días del evento, pero puedes ver todo lo que tenemos planeado hasta ahora.

¡Ven a contribuir con Tor!

Los días de puertas abiertas durante la encuentro de Tor, al igual que todos los eventos de Tor, se ejecutan según las pautas y el código de conducta de nuestros participantes.  ¡Traé tus ideas y preguntas, vamos a juntarnos y hackear! La mayoría de las sesiones se realizarán en inglés, pero habrá algunas en español. Recuerda que habrá oradores de múltiples idiomas asistiendo.

¿Que más sucede?

Tor Mexico City Hack Days

Relay Meetup

2 de octubre, 6:30 p.m. Sheraton María Isabel. En inglés.

La red Tor está compuesta por miles de voluntarios que dan su tiempo y ancho de banda para hacer del mundo un lugar mejor ejecutando nodos o relays. Los días de puertas abiertas de esta reunión incluyen una reunión de operadores de relays organizada por Colin Childs, aka Phoul en el IRC.

Vení y conocé a otros operadores de relays y escuchá las últimas noticias sobre Tor: tendremos camisetas y calcomanías para equipar sus dispositivos. Si no maneja un nodo o relay pero le gustaría saber más, habrá muchas personas en la reunión dispuestas a ayudarlo.

Coloquio “Mecanismos de Privacidad y Anonimato en Redes”

4-5 de octubre, de 10 a.m. a 6 p.m. Auditorio Sotero Prieto, Facultad de Ingeniería, en la Universidad Nacional Autónoma de México (UNAM). Este evento se llevará a cabo en español e inglés.

Después de la reunión, se llevará a cabo un coloquio centrado en la privacidad y la seguridad en la UNAM. El evento está siendo coordinado por gwolf. Haga clic aquí para obtener información del mapa y programa.

Tor: Diálogos feministas

Tor Meetup Feminista

Tormenta: diálogos feministas para las libertades y autocuidados digitales
4 de octubre, de 4 a 8 p.m. Facultad de Ingeniería, UNAM. Sala de videoconferencia, en el sótano del Centro de Ingeniería Avanzada. En Español.

Invitación a un encuentro de activistas feministas de México a las mujeres y personas no binarias de la comunidad de Tor, para conversar y compartir experiencias sobre el uso de internet, y el desarrollo de herramientas técnicas para el anonimato. El objetivo de este encuentro es reconocer el trabajo y las apuestas que están detrás de algunas de las herramientas de protección digital que utilizamos todos los días. Será un encuentro informal de entrada libre, abierta y gratuita.

Bitácora de Javier Gutiérrez Chamorro (Guti): Análisis estático de FileOptimizer

$
0
0

Después de haberme centrado en el rendimiento de FileOptimizer, con análisis, limpiezas y optimizaciones regulares había llegado el momento de centrarse en su estabilidad y su seguridad. Al igual que en cuanto a la eficiencia podemos guiarnos por nuestro “saber hacer”, apoyarse en herramientas es algo de gran ayuda. Además de las advertencias del compilador, […]

La entrada Análisis estático de FileOptimizer aparece primero en Bitácora de Javier Gutiérrez Chamorro (Guti).

Blog Bitix: Novedades y nuevas características de Java 11

$
0
0

Java 11 es la primera versión de soporte extendido publicada o LTS bajo el nuevo ciclo de publicaciones que adoptó Java en la versión 9. Añade varias novedades importantes en cuanto a seguridad y elimina otras que en versiones anteriores ya fueron marcadas como desaconsejadas.

Java

En la plataforma Java era habitual que entre versión y versión mayor pasasen varios años normalmente 3 o más. Este ciclo de publicaciones no se adapta a las necesidades de todas las empresas, organizaciones y usuarios. Algunas empresas y usuarios desean ciclos de publicaciones más cortos quizá con no tantas novedades en cada uno de ellos pero sí de forma más constante incorporando mejoras. Otras organizaciones necesitan confiar en una versión que tenga un ciclo de soporte largo para sus aplicaciones.

Para adaptarse a ambos requerimientos Java a partir de Java 9 adoptó un nuevo ciclo de publicaciones siendo cada seis meses para los que desean mejoras de forma regular y cada tres años para los que necesitan soporte extendido. Java 9 incorporó la esperada modularización que cambia la forma de desarrollo de las aplicaciones con numerosas mejoras. Java 10 añadío la inferencia de tipos para variables locales con la palabra reservada var. Ahora Java 11 siendo una versión de soporte extendido o LTS, el soporte de Java 11 está planificado que dure hasta 2023 y hasta 2026 de forma extendida lo que son 8 años de soporte.

En esta nueva versión de Java 11 publicada el 25 de septiembre de 2018 las novedades no son tan relevantes como lo fuero Java 8 con las lambadas y Java 9 con los módulos pero continúa con las mejoras incrementales y proporciona una versión LTS en la que empresas grandes confiarán como base para sus desarrollos.

La lista más relevante de novedades de Java 11 es la siguiente:

Eliminación de módulos Java EE y CORBA

Se eliminan del JDK paquetes ya desaconsejados hace varias versiones anteriores y que no eran muy usados en cualquier caso. Estos paquetes son los de CORBA una forma de llamada a procedimientos remotos que se utilizó como alternativa a RMI pero que nunca tuvo un uso extendido prefiriéndose SOAP o más recientemente interfaces REST.

La lista de paquetes eliminados son los siguientes.

  • java.xml.ws (JAX-WS, plus the related technologies SAAJ and Web Services Metadata)
  • java.xml.bind (JAXB)
  • java.activation (JAF)
  • java.xml.ws.annotation (Common Annotations)
  • java.corba (CORBA)
  • java.transaction (JTA)
  • java.se.ee (Aggregator module for the six modules above)
  • jdk.xml.ws (Tools for JAX-WS)
  • jdk.xml.bind (Tools for JAXB)

Sintaxis de variables locales para parámetros en lambdas

Ahora los parámetros de una lambda pueden declararse con var con inferencia de tipos. Esto proporciona uniformidad en el lenguaje al declarar los parámetros permite usar anotaciones en los parámetros de la función lambda como @NotNull.

Esta funcionalidad tiene algunas restricciones. No se puede mezclar el uso y no uso de var y no se puede mezclar el uso de var y tipos en lambdas explícitas. Son consideradas ilegales por el compilador y producirá un error en tiempo de compilación.

Cliente HTTP

En Java 9 se incorporó de forma experimental un cliente HTTP con soporte para HTTP/2 en el propio JDK. En Java 11 alcanza la categoría de estable. Este cliente HTTP es una forma sencilla de hacer llamadas a servicios web ya sean REST o GraphQL. Las clases del nuevo cliente se encuentran en el paquete java.net.http. Al estar este cliente HTTP incorporado en el JDK no será necesario depender de librerías de terceros.

Ejecución desde archivo de código fuente único

Para ejecutar un programa Java es necesario compilarlo a bytecode y posteriormente ejecutarlos. Se necesitan dos pasos. Para facilitar la ejecución de los programas que se componen de un único archivo de código fuente se añade la posibilidad de lanzar un programa desde el archivo de código fuente. Esto es útil par programas pequeños o para los casos de estar aprendiendo el lenguaje.

Esta funcionalidad es compatible con los shebang de los sistemas Unix.

Java 11 HelloWorld!

Unicode 10

Tratar texto es una parte importante casi de cualquier aplicación, este soporte de Unicode 10 añade 16018 nuevos caracteres soportados, 128 nuevos emojis y 19 símbolos nuevos para el estándar en televisiones 4K.

TLS 1.3

Algunas de las versiones anteriores de TLS ya no se consideran seguras añadir soporte para la versión más reciente TLS 1.3 permite a las aplicaciones Java ser más compatibles y más seguras. El protocolo TLS 1.3 proporciona dos beneficios principalmente, es más seguro y más rápido que sus versiones anteriores.

Otras mejoras

Se añaden implementaciones específicas para la arquitectura Aarch64 para un mejor rendimiento en la plataforma ARM en algunas funciones. Se añade de forma experimental un nuevo recolector de basura ZGC con pausas para recolectar basura menores capaz de manejar cantidades de memoria pequeñas de megabytes y grandes de terabytes. Al mismo tiempo se añade un recolector de basura Epsilon que no reclama la memoria. Se añade soporte para los algoritmos criptográficos ChaCha20 y Poly1305 junto con otras funcionalidades criptográficas RSASSA-PSS, AES Encryption with HMAC-SHA2 for Kerberos 5, …

Se añaden varios métodos a la clase String muy utilizados con los que no será necesario recurrie a librerías de terceros. Estos métodos son repeat, isBlank, strip, stripLeading, stripTrailing, lines.

Java que tradicionalmente marcaba como deprecarted características pero que las seguía manteniendo por compatibilidad hacia atrás parece que ha empezado a eliminar varias de esas características desaconsejadas de forma más agresiva. No solo se añaden nuevas características, también se eliminan algunas y se desaconseja el uso de otras entre ellas el visor de applets, eliminación de Unsafe.defineClass, Thread.destroy() y Thread.stop(Throwable), eliminación de las funcionalidades de despliegue de Java Plugin y Java Web Start que se marcaron como desaconsejadas en Java 9 y para eliminación en Java 10 finalmente en Java 11 se han eliminado sin reemplazo.

Las anteriores son las funcionalidades que he considerado más destacables para todos los usuarios., También hay otras funcionalidades añadidas, soporte eliminado para funciones específicas o de funcionamiento interno.


Picando Código: Profiling de Emacs e instalación Emacs 26

$
0
0

Editando un archivo relativamente largo de código, me empecé a frustrar porque el desplazamiento y renderizado de código andaba lento. Lo primero que tenía que hacer era encontrar el culpable de la lentitud. Por suerte Emacs tiene incorporado un profiler. Para activarlo tenemos que usar M-x profiler-start y seleccionar si queremos hacer profiling de cpu, memoria o ambos. Mi problema parecía de cpu porque se trancaba en momentos que intentaba desplazarme rápido por varias líneas de código. Con M-x profiler-report, podemos ver un buffer nuevo que nos muestra los resultados. Y un test bastante corto mostró cuál era el problema:

Emacs Profiler

No olviden ejecutar M-x profiler-stop si están probando algo, porque no deja de gastar algunos recursos extra tenerlo corriendo.

El nombre linum me resultaba familiar por haber leído al respecto antes, particularmente relacionado a la lentitud de Emacs. Se trata de una biblioteca que provee el número de línea, y viene incluida con Emacs desde su versión 22. Como Emacs no proveía ver el número de línea de forma nativa, las bibliotecas de número de línea en general son bastante lentas.  Pero en la versión estable actual, Emacs 26, finalmente se implementó el número de línea nativo. Así que era el paso que me faltaba para actualizar a Emacs 26. De los cambios de la versión 26:

Ahora Emacs soporta mostrar el número de líneas en el buffer. Esto es similar a lo que provee `linum-mode`, pero mucho más rápido y sin usurpar el margen para los números de línea. Personaliza la variable local de buffer ‘display-line-number’ para activar este display opcional. Alternativamente, se puede usar el modo menor ‘display-line-numbers-mode’ o el global ‘global-display-line-numbers-type’ con el mismo valor que ‘display-line-numbers’.

Los números de línea no se muestran en las ventanas de minibuffers y tooltips, porque no son útiles ahí (…)
‘linum-mode’ y todos los paquetes similares se vuelven obsoletos de ahora en adelante. Se alenta a los usuarios y desarrolladores a cambiar a esta nueva característica en su lugar.

Lamentablemente en Debian y Ubuntu todavía no han actualizado a la versión 26.1 de Emacs. En ArchLinux sí, como era de esperarse. Pero por suerte a los que usamos .deb, siempre nos salva un ppa. En este caso el PPA de Kevin Kelley: https://launchpad.net/~kelleyk/+archive/ubuntu/emacs

Dicho repositorio contiene paquetes basados en las versiones estables de Emacs: 25 y 26. Así que lo agregué a mi apt y procedí a instalar emacs26. Lo bueno es que emacs25 y emacs26 pueden convivir en el sistema. Así que en este momento tengo ambos por las dudas que encuentre alguna cosa que no funcione perfecto en Emacs 26 y pueda usar 25 como respaldo. Por ahora viene todo bien.

Con respecto a la lentitud, ni bien actualicé a la versión más nueva abrí el mismo archivo de código que había destacado el problema en un principio, y la diferencia fue gigante. El desplazamiento entre líneas es mucho más rápido y fluido. Probé con archivos más grandes de miles de líneas, y es el día y la noche.

¿Y Spacemacs?

Desde hace poco más de un año vengo usando Spacemacs (una “distribución” de Emacs). Por suerte Spacemacs soporta la nueva implementación de número de línea desde hace un tiempo. Incluso noté al iniciar Spacemacs con Emasc 26, que se desinstalaba el paquete relacionado a linum, y al iniciar Emacs 25 se vuelve a instalar, por lo que Spacemacs sabe qué usar dependiendo de la versión de Emacs.

Así que por el momento, sigo usando Emacs 26 🙌🏻

Navegapolis: ¿Expertos o eternos principiantes?

$
0
0

elefante cacharreríaEl conocimiento profesional de nuestros padres, y no digamos de nuestros abuelos, era relativamente estable y servía para toda una vida profesional. Sin embargo la velocidad actual nos puede dejar profesionalmente oxidados en menos de una década.

Hoy podemos ser expertos y dentro de un año incompetentes, o como define Fred Kofman,(1) ciegos: profesionales incompetentes que ignoran que lo son —si no lo ignoran, Kofman los llama cretinos—

Es sugerente el ciclo que Kofman describe en el capítulo "Aprendiendo a aprender" del tomo I de Metamanagement, porque ilustra que a la velocidad actual, en las profesiones de conocimiento podemos pasar de expertos a ciegos sin darnos cuenta. 

Con el permiso de Fred Kofman y mi agradecimiento por ello comparto el siguiente fragmento de "Aprendiendo a aprender": 

"Consideremos la siguiente grilla. En ella se describen los progresos del principiante en un recorrido opuesto al sentido de las agujas del reloj, desde el cuadrante superior izquierdo (ciego) hasta el cuadrante superior derecho (experto)

 

de ciego a experto

 

 

Blog Bitix: Almacenar cifrados los valores de configuración sensibles en Spring Cloud Config

$
0
0
Spring
Java

Para no tener que hacer cambios en el código que implica recompilar la aplicación y generar de nuevos los artefactos al cambiar algunos valores de la aplicación se utilizan los archivos de configuración. Los archivos de configuración son archivos de texto plano que pueden seguir algún formato como properties, xml o yaml, externos a la aplicación pero que lee sus propiedades al iniciarse. Algunas propiedades de configuración de ejemplo pueden ser la cadena de conexión a una base de datos, el usuario y contraseña.

Dado que algunos valores de configuración son sensibles como en el ejemplo anterior la cadena de conexión, usuario y contraseña es recomendable por mayor seguridad almacenar estos valores cifrados y que la aplicación los descifre con la clave correspondiente al necesitar su valor original.

Spring Cloud Config permite guardar los archivos de configuración con algunos valores cifrados. Hay varias posibilidades de configuración para guardar los datos cifrados: mediante clave simétrica, clave privada-pública, guardarlos en el servicio externo Vault de [Hasicorp][hasicorp], mantenerlos cifrados solo en el almacenamiento persistente o transmitirlos cifrados y que sea el cliente el que los descifre.

Utilizando la forma más simple para mantener los datos cifrados con una clave simétrica en el servicio de configuración hay que mantener en una propiedad de configuración la clave simétrica para cifrar y descifrar los datos.

Definida la clave simétrica e iniciado el servidor de configuración este ofrece dos endpoints para cifrar y descifrar datos. Utilizando el de cifrado se obtiene el valor cifrado del dato sensible que se quiere proteger. Con el endpoint de descifrado se puede descifrar. Se observa que utilizando varias veces el endpoint de cifrado se devuelve en cada una un valor distinto, sin embargo, descifrando cada uno de estos valores con el endpoint de descifrado siempre se obtiene el valor original. Esto es debido seguramente a que en la operación de cifrado se utiliza la técnica del salt para que a los valores cifrados se les pueda aplicar un ataque de diccionario, el salt es incluido en el valor devuelto para que la operación de descifrado devuelva el valor original.

El valor cifrado obtenido por este endpoint se puede guardar en los archivos de configuración entrecomillándolo y precediéndolo con la cadena {cipher}.

En este caso el servicio al iniciarse obtiene su configuración del servicio de configuración, los datos se transmiten en forma plana sin cifrar y el cifrado utilizando en el servidor de configuración es transparente para el cliente. Accediendo al endpoint del servidor de configuración que devuelve la configuración de un servicio con una propiedad cifrada se observa que al obtener el valor se devuelve en texto plano al cliente, esta petición es la misma que hace el servicio para obtener su configuración, de modo que aunque la información está cifrada en el servidor de configuración se transmite al servicio sin cifrar en texto plano. En este ejemplo se utiliza el protocolo inseguro HTTP, lo recomendable es utilizar el protocolo HTTPS para cifrar el tráfico entre el servidor de configuración y el cliente de modo que los valores sensibles queden protegidos también en la transmisión.

Iniciado el servicio de descubrimiento, el de configuración y un servicio que tiene un dato cifrado de configuración el valor que obtiene está ya descifrado. En este caso el servicio client obtiene el valor de la propiedad config.password descifrado con el valor secret.

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 ./gradle-run.sh && ./curl-1.sh.

Variable not found: Enlaces interesantes 332

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

Por si te lo perdiste:

.NET / .NET Core

ASP.NET / ASP.NET Core

Azure / Cloud

Data

HTML / CSS / Javascript

Visual Studio / Complementos / Herramientas

Xamarin

Otros

Publicado en Variable not found.

Variable not found: Quizás no estés comparando con null de forma totalmente correcta

$
0
0
¿Qué podría salir mal?Pues como uno que os habla, seguro que muchos de vosotros habéis comparado miles de veces si un objeto es nulo utilizando un patrón de código C# como el siguiente:
var invoice = _invoiceRepository.GetById(18);
if(invoice == null)
{
// Hacer algo
}
¿Qué podría salir mal, verdad?

Pues aunque pueda parecer raro, hay casos en los que la comparación anterior no funcionaría bien... o mejor dicho, no funcionaría como esperamos.

Hace unos días leía un post de Khalid Abuhakmeh en el que hacía referencia a una charla de Channel 9 en la que Mads Torgersen recomendaba no utilizar la doble igualdad para comparar con null (minuto 33:00, aprox.)

En su lugar, la recomendación del lead designer del lenguaje C# en Microsoft es utilizar la expresión is null, como en el siguiente ejemplo:
var invoice = _invoiceRepository.GetById(18);
if(invoice is null)
{
// Hacer algo
}

Ahí queda eso :)

El motivo: la sobrecarga de operadores

¿Y cuál es la causa de esta recomendación? Pues básicamente, que no siempre podemos estar seguros del resultado de esta operación. Como recordaréis, muchos de los operadores de C# pueden ser sobrecargados, y la comparación de igualdad == no es una excepción.

Si por algún motivo se sobrescribiera dicho operador y su lógica introducida así lo decidiera, podríamos encontrarnos con un resultado poco previsible y, sobre todo, muy difícil de depurar.

Es decir, imaginemos que un descerebrado desarrollador introduce un código como el siguiente en la clase Invoice:
public class Invoice
{
public int Id { get; set; }
[...]

public static bool operator == (Invoice a, Invoice b)
{
if(a is null || b is null)
{
return true;
}
return a.Id == b.Id;
}
}
Como veis, estamos indicando que el operador de igualdad retornará cierto si alguno de los operandos son nulos, por lo que el siguiente resultado será algo diferente a lo que podríamos esperar:
var invoice = new Invoice {  Id = 1 };
Console.WriteLine(invoice == null); // --> True
Console.WriteLine(invoice is null); // --> False
En cambio, dado que el operador is no es sobrecargable, el resultado será siempre el esperado.

En fin, la verdad es que son escenarios muy raros de encontrar, pero está bien saber que esta posibilidad existe. Por mi parte no creo que me pueda acostumbrar fácilmente a utilizar is en lugar de == y tampoco tengo claro que me valga la pena el esfuerzo, pero, sin duda, sería lo más correcto.

Publicado en Variable not found.

Blog Bitix: Tolerancia a fallos en un cliente de microservicio con Spring Cloud Netflix y Hystrix

$
0
0
Spring
Java

Los microservicios son independientes unos de otros y se comunican mediante operaciones de red. Dado que las operaciones se realizan mediante un medio no confiable como la red, dada su naturaleza efímera y dado que pueden fallar en los microservicios es importante que los clientes estén preparados para posibles fallos.

Un patrón o técnica que se suele emplear es el Circuit Breaker en Java y con Spring se ofrece en el proyecto Spring Cloud Netflix mediante Hystrix. Este patrón soluciona varios problemas cuando un microservicio falla.

  • Uno es que cuando un microservicio empieza a fallar es necesario dejar de hacerle peticiones para permitirle recuperarse si está demasiado saturado. Cuando ocurre un fallo es posible realizar una acción en sustitución de la llamada al microservicio y devolver un valor alternativo.
  • Otro problema es que el microservicio aunque no falle tarde demasiado en responder se puede establecer un timeout que si se supera se deja de esperar la respuesta lo que evita que los microservicios que usan uno que tarda demasiado agote sus recursos y empiecen a fallar o tardar demasiado también si tienen muchas llamadas.

En ambos casos se evita que la cadena de microservicios empiece a fallar y con ello sistema completo.

El patrón circuit breaker se denomina así ya que implementa una lógica similar a un circuito eléctrico. El circuito de forma normal está cerrado y se realizan las llamadas al microservicio servidor de forma normal. Si el microservicio servidor empieza a fallar se llama a la acción alternativa para obtener un valor, si se supera un umbral de errores el circuito pasa a estado abierto y se dejan de hacer llamadas el microservicio servidor. Cada cierto tiempo definido se realiza una llamada para comprobar el estado de microservicio servidor de forma que si empieza a responder correctamente el circuito pasa a estado cerrado y las siguientes llamadas se realizan al microservicio dejándose de utilizar la acción alternativa.

Diagrama del patrón circuit breaker, de estados y método fallback

Para utilizar Hystrix como implementación del patrón circuit breaker en una aplicación Java con Spring Boot el método que realiza la llamada al microservicio servidor ha de anotarse con la anotación @HystrixCommand, como parámetro se indica el método fallback para obtener un valor por defecto cuando el microservicio falle, también se puede indicar el tiemout de espera antes de considerar que la llamada ha fallado con la propiedad execution.isolation.thread.timeoutInMilliseconds. También se pueden indicar los valores para considerar el circuito abierto con circuitBreaker.requestVolumeThreshold y circuitBreaker.errorThresholdPercentage. Y eso es lo básico que hay que hacer para utilizar este patrón de tolerancia a fallos. Tiene algunos valores adicionales más que se pueden configurar para adaptar el patrón a los valores óptimos de la aplicación.

En el ejemplo el cliente en un bucle realiza las llamadas al servicio con un método get() anotado con @HystrixCommand. En este método se encapsula la petición HTTP que puede fallar utilizando la librería Jersey obtenida la ubicación de una instancia del servicio a su vez del servicio de registro y descubrimiento Eureka.

El circuito se abre cuando el número de llamadas supera un umbral y el porcentaje de fallo se supera, se han de dar las dos condiciones, si el número de llamadas que se realizan no superan el umbral aunque todas fallen el circuito permanece cerrado. Ambos valores son personalizables con las propiedades circuitBreaker.requestVolumeThreshold y circuitBreaker.errorThresholdPercentage. El circuito permanece abierto durante el tiempo indicado por metrics.rollingStats.timeInMilliseconds. Por otro lado, el tiempo de timeout se puede indicar en la anotación por cada llamada a servicio o nivel de clase para todos los métodos del servicio.

En la aplicación ejemplo hay un microservicio servidor y un microservicio cliente, iniciando una instancia de microservicio servidor y una instancia del microservicio cliente que implementa el patrón circuit breaker inicialmente las peticiones se realizarán correctamente si no ocurre un timeout. Si se finaliza el proceso del microservicio servidor de forma inesperada las peticiones del cliente al servidor empezarán a fallar y obtener el valor alternativo del método fallback, si se supera el umbral de llamadas el circuito pasa a estado abierto. Si el servicio servidor se inicia de nuevo pasado unos instantes después de que esté disponible se cerrará el circuito y a obtener los valores devueltos por el microservicio.

Para monitorizar el estado del sistema y de los circuitos se puede visualizar en un dashboard. El número de peticiones que se están realizando, las fallidas, el estado de los circuitos, las que fallan por timeout o las que fallan con error. Para tener acceso a esta página hay que incluir la dependencia org.springframework.cloud:spring-cloud-starter-netflix-hystrix-dashboard. La página dashoard está disponible en la dirección http://localhost:8085/hystrix.

Estados del circuit breaker

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 ./gradle-run.sh.

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 ./gradle-run.sh.

Navegapolis: Las organizaciones triunfan por el compromiso de su gente

$
0
0

albañil"La mayoría de las organizaciones que triunfan, triunfan por el compromiso de su gente". Así lo afirma Fred Kofman en este fragmento de su conferencia "Tu trabajo no es tu trabajo", en el que expone que el que el valor que aportan las personas motivadas y comprometidas no se puede exigir ni comprar. 

Fred Kofman es asesor de liderazgo en Google, director del Centro de Liderazgo Consciente en el Instituto Tecnológico de Monterrey y presidente del Conscious Business Center International. Es doctor en economía por la Universidad Berkeley de California y trabajó de profesor durante años en la Escuela de Management Sloan del Instituto Tecnológico de Massachusetts.

 

 

 


Una sinfonía en C#: #NetConf en la Universidad Politécnica de Madrid

$
0
0

El evento

Como parte de evento que se realiza en todo el mundo durante estos meses, he tenido la suerte de organizar y participar como ponente en la NetConf en Madrid.

Gracias a la generosidad de la gente de la Universidad Politécnica de Madrid el evento ha tenido una locación inmejorable.

Ha sido una versión de tres charla en la que he tenido la suerte de compartir cartel con dos grandes del mundo de .NET de España como Javier Valero y Robert Bermejo.

Sobre Azure DevOps

Cuando preparé la charla no existía Azure DevOps por lo tanto mi charla fuer sobre Visual Studio Team Services, en concreto sobre cómo montar un entorno de despliegue continuo de una aplicación ASP Net Core en Docker sobre Azure.

Dejo un link a las diapositivas que utilicé durante la charla.

Gracias a los ponentes, a la UPM y a Tokiota por el apoyo.

Nos leemos.

Fixed Buffer: Haciendo fácil el acceso a datos con Entity Framework Core

Fixed Buffer: Haciendo fácil el acceso a datos con Entity Framework Core (Parte 2)

proyectos Ágiles: Auto-organización – Fundamentos y relación con la motivación intrínseca

$
0
0

Relación de los fundamentos de la auto-organización con los principios de la motivación intrínseca (autonomía, maestría y propósito).

Para ver el texto más pequeño o imprimir las imágenes en mayor resolución, con el botón derecho del ratón hacer clic en la imagen  y escoger la opción “Abrir imagen en una pestaña nueva”. 

Para que la auto-organización sea un éxito, la persona (o el equipo) debe tener unos objetivos, marco y reglas claros, así como las habilidades e información necesarias para poder realizar ese trabajo de manera efectiva.

Auto-organización - self-management

 

También es importante considerar ciertos aspectos que refuerzan o degradan el éxito de la auto-organización:

  • Las personas siguen las ideas, se motivan por la visión, más que por la persona (el individuo) que ejerce el liderazgo. El liderazgo tiene que proporcionar una visión compartida, que produzca alineamiento de los diferentes individuos.
  • Estos objetivos o visión deberían estar asociados a la satisfacción del que va a recibir el producto/servicio (cliente, usuario, …), lo cual constituye el resultado final a conseguir (este es el punto por el que hay que empezar las conversaciones). Es por ello que el contacto directo entre quienes están realizando el trabajo con el mercado o “cliente” ayuda a:
    • Entender qué necesitan y hacer sentir de manera “real” el impacto del trabajo, si realmente se están cubriendo las demandas de los que se tienen que beneficiar de él.  Idealmente también permite alinear el “propósito” del trabajo con la motivación más intrínseca de la persona (fomentando la responsabilidadsobre los resultados dado que “los han hecho suyos”).
    • Proporcionar la transparencia de contexto del cliente necesaria para que puedan tomar buenas decisiones.
    • Fomentar la innovación en las personas o equipos de trabajo, al entender mejor las necesidades (que no la “solución”), el tipo de negocio o servicio a proporcionar.

Auto-organización - Factores negativos

Crear un entorno donde se empiece dar todo esto permite crear un efecto de peer emulationdonde se da ejemplo de nuevos comportamientos y  profesionalidad (en personas y en equipos). Para ello será importante seleccionar en el inicio las personas, equipos y áreas adecuadas, ya que quizás no todo el mundo (management o personas en la “trinchera”) estén desde el principio receptivas a estos nuevos paradigmas de gestión basados en autonomía y responsabilidad.

s-l300

Evidentemente, el inicio de este cambio requiere:

  • Una aceptación de que las personas o equipos con mayor autonomía pueden cometer errores, pero como mínimo tienen que sacar aprendizaje de ellos para reducirlos en el futuro.
  • Una inversión. Los objetivos y las restricciones pueden estar claramente definidos pero, sin un esfuerzo explícito de medio-largo plazo en el desarrollo de las personas, la organización siempre estará rindiendo por debajo de sus posibilidades y fallando de manera repetitiva.

 

“Es mejor querer más responsabilidad en la organización que tener miedo de dar más responsabilidad a la organización”

— Adaptado de una cita de Bill Cosby

 

Artículos relacionados

 

 

Fixed Buffer: Inyección de Dependencias en .Net Framework

$
0
0

Inyeccion de dependencias

Un mes ya… y hoy vengo a hablaros de la “Inyección de Dependencias” (DI). La inyección de dependencias consiste de manera resumida en evitar el acoplamiento entre clases utilizando interfaces. Gracias esto, conseguimos que cada clase tenga una función única, facilitando así el mantenimiento y el soporte de nuestro código.

Esto que puede parecer un poco lioso a simple vista, y puede parecer mucho trabajo, se puede conseguir fácilmente cambiando levemente nuestro patrón de diseño. Vamos a imaginar que tenemos una clase que lee unos datos desde una base de datos con Entity Framework (“Database First” o “Code First“), y los envía por email:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using PostInyeccion.Models;

namespace PostInyeccion
{
    class Program
    {
        static void Main(string[] args)
        {
            GeneradorInformes generador = new GeneradorInformes();
            generador.GenerarInforme();
        }
    }

    internal class GeneradorInformes
    {
        internal void GenerarInforme()
        {
            //Obtenemos los datos desde el contexto
            using (PostDbContext contexto = new PostDbContext())
            {
                var profesores = contexto.Profesores.Include(x => x.Cursos)
                                                    .ThenInclude(x => x.Alumnos).ToList();
                
                //Trabajo de maquetacion
                //.......                           

                //Enviamos el correo
                var emailSender = new EmailSender();
                var envioOK = emailSender.Enviar(profesores);
                if(!envioOK)
                {
                    //Registramos el fallo en un log
                }
            }
        }
    }

    public class EmailSender
    {
        public bool Enviar(List<Profesores> profesores)
        {
            //Enviar correo
            return true;
        }
    }
}

En primer lugar, vamos a analizar los posibles problemas de esta clase:

  1. Baja mantenibilidad por el acoplamiento en entre clases: Es la propia clase la que instancia las que va necesitando, provocando que cualquier cambio en las clases “auxiliares” pueda cambiar el comportamiento.
  2. Dificultad para realizar pruebas unitarias: En el caso en el que queramos realizar pruebas unitarias, es requisito que todos los servicios estén activos. Desde el punto de vista de las pruebas, esto es nefasto, podemos no tener acceso al servidor de correo, o a la base de datos… Con este patrón, es muy difícil testear nuestra clase.

Inyección de Dependencias

Vamos a ver que pasa si refactorizamos la clase para inyectar las dependencias, de manera que no tengamos dependencias:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using PostInyeccion.Models;

namespace PostInyeccion
{
    class Program
    {
        static void Main(string[] args)
        {
            //Generamos la clase que hara el trabajo
            GeneradorInformes generador = new GeneradorInformes();

            //Obtenemos los datos desde el contexto
            using (PostDbContext contexto = new PostDbContext())
            {
                var profesores = contexto.Profesores.Include(x => x.Cursos)
                                                    .ThenInclude(x => x.Alumnos).ToList();

                //Instanciamos la clase de envio de emails
                var emailSender = new EmailSender();
                generador.GenerarInforme(profesores, emailSender);
            }
        }
    }

    public class GeneradorInformes
    {
        public  void GenerarInforme(List profesores, IEmailSender emailSender)
        {
            //Trabajo de maquetacion
            //.......
            
            //Enviamos el correo
            var envioOK = emailSender.Enviar(profesores); 
            if(!envioOK) 
            { 
                //Registramos el fallo en un log 
            }
        }
    }
}

interface IEmailSender
{
    bool Enviar(List profesores);
}

public class EmailSender : IEmailSender
{
    public bool Enviar(List profesores)
    {
        //Enviar correo
    }
}

Hemos conseguido una mayor mantenibilidad al abstraer totalmente a la clase “GeneradorInforme” de las labores propias de envío de correo y de obtención de datos. Y ahora es cuando me dices, “Pero no hace falta utilizar inyección de dependencias para conseguir lo que has conseguido…”. Efectivamente, para simplemente desacoplar las clases, no sería necesario. Podríamos haberle pasado al método una instancia de EmailSender en vez de su interfaz pero… Si queremos hacer pruebas unitarias, eso no es suficiente. Seguiríamos con el problema de que si el servidor de correo esta caído, nuestra prueba fallaría. Ahí radica la potencia de trabajar inyectando dependencias. En nuestro proyecto de pruebas unitarias, simplemente tendríamos que añadir una nueva clase que implemente “IEmailSender” y que no se conecte a ningún servidor, o que simule la conexión.

En el caso del ejemplo, hemos inyectado las dependencias mediante un parámetro, pero esta solo es una de las maneras. Podemos inyectar dependencias de varias maneras:

  1. Inyección de dependencias en parámetros de constructor.
  2. Inyección de propiedades.
  3. Inyección de dependencias en parámetros de métodos.

Vamos a ver más detalladamente cada uno.

Inyección de dependencias en parámetros de constructor

var emailSender = new EmailSender();
GeneradorInformes generador = new GeneradorInformes(emailSender);
//--------------------------------------------------------------
public class GeneradorInformes
{
    //Dependencia para el envio de correos
    IEmailSender _emailSender;

    //Pasamos la dependencia en el construcor
    public GeneradorInformes(IEmailSender emailSender)
    {
        _emailSender = emailSender;
    }

    public void GenerarInforme(List<Profesores> profesores)
    {
        //Trabajo de maquetacion
        //.......

        _emailSender.Enviar(profesores);
    }
}

 Inyección de propiedades

//Instanciamos la clase de envio de emails
var emailSender = new EmailSender();
GeneradorInformes generador = new GeneradorInformes();
generador.EmailSender = emailSender;
generador.GenerarInforme(profesores);
//-----------------------------------------------------
public class GeneradorInformes
{
    //Propiedad con la dependencia
    public IEmailSender EmailSender { get; set; }
    public GeneradorInformes()
    {
    }

    public void GenerarInforme(List<Profesores> profesores)
    {
        //Trabajo de maquetacion
        //.......

        EmailSender.Enviar(profesores);
    }
}

En este caso, hay que tener en cuenta que la dependencia no estará disponible durante el constructor, por si la necesitásemos.

Inyección de dependencias en parámetros de métodos

Es el caso que hemos visto en el primer ejemplo.

Contenedor IOC

La utilización de contenedores IOC (Inversion Of Control) nos abstraen de la necesidad de generar las clases cada vez. Simplemente es configurar un contenedor el cual nos sirva las dependencias que necesitamos en cada momento. Esto facilita mucho la labor de trabajo al no tener que gestionar nosotros mismos las clases. Existen bastantes sistemas IOC para .NET, pero en este caso, vamos a utilizar “Microsoft.Extensions.DependencyInjection”.

Para eso, tenemos que añadir el paquete desde NuGet:

DI

O vía consola:

PM->Install-Package Microsoft.Extensions.DependencyInjection -Version 2.1.1

Ahora vamos a registrar los servicios (Asumo que tenemos un DbContext creado en base a los post de Entity Framework  Core), pero para ello, primero tenemos que crear el interfaz IGeneradorInformes y hacer que Generador de informes la implemente:

public interface IGeneradorInformes
{
    void GenerarInforme();
}

//.........

public class GeneradorInformes : IGeneradorInformes
//......

Una vez que lo tengamos, empezamos a registrar los servicios:

//Generamos la coleccion de servicios
IServiceCollection serviceCollection = new ServiceCollection();
//Registramos el DbContext
serviceCollection.AddDbContext<PostDbContext>(options=>
                options.UseMySql("Server=localhost;Database=postefcore;Uid=root;Pwd=root;"));
//Registramos el EmailSender
serviceCollection.AddSingleton<IEmailSender, EmailSender>();
//Registramos el generador de informes
serviceCollection.AddSingleton<IGeneradorInformes, GeneradorInformes>();

//Construimos el contendor IoC
var services = serviceCollection.BuildServiceProvider();

Después, simplemente necesitamos llamar a su metodo “GetService<T>()” para obtener una instancia de la clase concreta con todas sus dependencias inyectadas:

IGeneradorInformes generador = services.GetService<IGeneradorInformes>();
generador.GenerarInforme();

Este sistema funciona muy bien en MVC 5 y MVC Core, ya que esta construido totalmente sobre el sistema de inyección de dependencias, pero es cierto que en aplicaciones que no sean MVC, hay que trabajarselo un poco. Digo esto porque necesitamos mantener activa una referencia a “services” para poder pedirle las clases. Esto lo podemos resolver bastante fácilmente con un tipo estático que almacene nuestra referencia:

using Microsoft.Extensions.DependencyInjection;
using System;

namespace PostInyeccion
{
    public static class Injector
    {
        static IServiceProvider _proveedor;

        public static void GenerarProveedor(IServiceCollection serviceCollection)
        {
            _proveedor = serviceCollection.BuildServiceProvider();
        }

        public static T GetService<T>()
        {
            return _proveedor.GetService<T>();
        }
    }
}

Veamos como usarlo en nuestro código:

static void Main(string[] args)
{
    //Generamos la coleccion de servicios
    IServiceCollection serviceCollection = new ServiceCollection();
    //Registramos el DbContext
    serviceCollection.AddDbContext(options =>
        options.UseMySql("Server=localhost;Database=postefcore;Uid=root;Pwd=root;"));
    //Registramos el EmailSender
    serviceCollection.AddSingleton<IEmailSender, EmailSender>();
    //Registramos el generador de informes
    serviceCollection.AddSingleton<IGeneradorInformes, GeneradorInformes>();

    Injector.GenerarProveedor(serviceCollection);
    //Obtengo clase desde el IOC
    IGeneradorInformes generador = Injector.GetService<IGeneradorInformes>();
    generador.GenerarInforme();
}

Con esto, registraremos todas las dependencias al inicio de nuestro programa, y llamaremos a Injector.GetService<T>() cuando necesitemos utilizar una dependencia.

A simple vista, parece que es mucho trabajo y poca recompensa, pero en las siguientes entradas veremos las ventajas que aporta trabajar así cundo hablemos de las pruebas unitarias y del “Moking”.

Puedes descargar el código de ejemplo desde este enlace.

**La entrada Inyección de Dependencias en .Net Framework se publicó primero en Fixed Buffer.**

Viewing all 2731 articles
Browse latest View live