Weblogs Código

Picando Código

Kingdom Rush Origins

octubre 20, 2018 01:00

Kingdom Rush Origins

El estudio uruguayo Ironhide vuelve a la carga con Kingdom Rush Origins: La más reciente entrega de la saga Kingdom Rush está disponible en Steam para Linux, Mac y Windows y GOG (Mac y Windows).

Kingdom Rush es una saga de juegos que combina tower defense y estrategia en un universo fantástico con caballeros, héroes, magos, dragones y otras criaturas místicas. La mecánica es relativamente sencilla, tenemos que proteger nuestra base de olas de enemigos, pero a medida que avanzamos la estrategia es clave para poder seguir adelante.

Contamos con distintos tipos de torres que son más o menos efectivas según el enemigo que enfrentemos, y la combinación de torres que elijamos. Arqueros, magos, druidas de piedra e infantería élfica son la base de nuestro ejército y hay más de 18 habilidades para nuestras torres: tiradores elfos, osos, magos y hasta árboles gigantes.

Los niveles son bastante coloridos con una estética caricaturesca y los distintos personajes y enemigos son muy particulares. Arañas gigantes, gnomos, magos, vampiros y más. El juego mantiene la tradición de incluir homenajes a distintas series y juegos que parecen venir del cariño que de los desarrolladores a dichas series. Son pequeños huevos de pascua que divierten mucho al ser descubiertos, hay que estar atentos para encontra estos detalles. Entre los escenarios esta vez contamos con bosques élficos, reinos de hadas mágicos y ruinas aéreas de una antigua metrópolis.

La historia se cuenta con mini cómics entre algunos de los niveles, y este título es una precuela de los que vinieron antes. Pero no necesitan haber jugado los Kingdom Rush anteriores para divertirse jugando éste.

Como en instancias anteriores, contamos con héroes que van subiendo de nivel y ganando poder a medida que generan experiencia en el campo de batalla. Por ahora mi héroe preferido es Faustus, el dragón. Pero no los he probado todos. Cada héroe tiene su estrategia también, y según el nivel o nuestra forma de jugar algunos héroes son mejor que otros.

Nuevamente tuve el privilegio de poder probar la versión beta de Kingdom Rush Origins en Steam. Llegué a terminar la aventura principal sin encontrar ningún error y nuevamente volví a jugarlo entero con mi Steam Controller como hice con Kingdom Rush Frontiers. Al terminar la historia principal, me puse a jugar en el modo heróico, un poco más difícil con ciertas limitaciones en lo que podemos usar. Le sigue el modo Iron, todavía más limitado en las torres y habilidades, que pone a prueba nuestra capacidad como estrategas. Cuenta también con varios achievements de Steam que son bastante divertidos de ir encontrando.

[See image gallery at picandocodigo.net]

Como si todo esto fuera poco, faltan algunas actualizaciones gratuitas con más contenido. Al terminar la aventura principal podemos ver que el mapa tiene varias partes sin explorar y quedan héroes por descubrir:

Última semana de Diciembre – Actualización 1.1

¡Cuidado! ¡Un poderoso ejército de ogros está preparando una estrategia para invadir y destruir todo!

Esta actualización incluye:

  • La expansión “Hulking rage” (¿la furia a lo Hulk? No sé cómo traducirlo exacto, pero me gusta)
  • Héros nuevos para ayudar con la invasión (Durax, Lilith y Razz & Rags)

Última semana de Enero – Actualización 1.2

El último y más leal teniente de Malicia se ha vuelto loco y está tramando venganza.
¡Lidera las fuerzas élficas y detén los planes de Baj’Nimen el Odioso antes que destruya todo en su camino!

Esta actualización incluye:

  • La expansión “Bittering Rancor” (no creo que lo bitter se refiera a un tipo de cerveza)
  • Héroes poderosos (Bruce, Lynn)

Última semana de Febrero – Actualización 1.3

Como nuestro Reino vuelve a sus antiguos tiempos de paz, el mensaje que mandamos pidiendo ayuda a los enanos nunca volvió, si hay algo más molesto que un enano ruidoso, ¡es uno callado!
Necesitas viajar a su tierra y buscar respuestas.

Esta actualización incluye:

  • Expansión “Forgotten treasures” (tesoros escondidos)
  • Héroes (Wilbur, Phoenix)

No tengo mucho más que decir que si les resulta interesante el género o la ambientación del juego, probablemente les resulte divertido. Cuenta con mucho contenido, y más contenido en camino todavía. En lo personal la saga es de lo que más he jugado en computadora, y siempre estoy atento a nuevas entregas. Así que recomiendo ampliamente que jueguen y disfruten de Kingdom Rush:

Otras reseñas de la saga en el blog:

¡Muchas gracias Ironhide por volver a darme la oportunidad de jugar la versión beta!

Concurso Kingdom Rush

Manteniendo algo así como una tradición iniciada en 2014: Para cerrar el post, por haber leído hasta acá, para repartir la alegría, y celebrar la salida del juego, voy a estar regalando claves de Kingdom Rush para Steam. El juego está disponible en GNU/Linux, Mac OS y Windows. Como en otros sorteos, hay varias formas de participar:

  • Dejando un comentario en este post con su correo electrónico real (no voy a compartirlo con ninguna empresa que los quiera espamear, simplemente tengo que contactarlos de alguna manera si son los ganadores).
  • Publicando un tweet mencionando a @picandocodigo con un link a este post y el hashtag #AwokMilanga o #KingdomRushLinux

La semana que viene anunciaré los ganadores. ¡Suerte y a jugar Kingdom Rush!

» Leer más, comentarios, etc...

Picando Código

La Programación…

octubre 20, 2018 11:50

» Leer más, comentarios, etc...

Blog Bitix

Sun Microsystems cae, la adquiere Oracle

octubre 19, 2018 09:00

Sun Microsystems
Oracle

Era enero del 2010 y se anunciaba que Oracle adquiría Sun (Stanford University Network) por unos 7400 millones de dólares. Sun Microsystems era asimilada por uno de los grandes entre el mundo empresarial que eliminaba a uno de sus competidores. Fue un hecho importante debido a varias de las tecnologías que había desarrollado Sun y poseía como aún a día de hoy uno de los lenguajes más populares para el desarrollo de software, Java, y otras tecnologías importantes que había adquirido hace no tanto tiempo como la base de datos MySQL competencia de Oracle.

Otras tecnologías de Sun relevantes eran el sistema operativo Solaris, la tecnologías de depuración DTraze, el avanzado sistema de archivos ZFS utilizando a día de hoy en los sistemas BSD, el paquete ofimático OpenOffice predecesora de LibreOffice, la herramienta de automatización de proyectos Hudson también predecesora de Jenkins, el software de virtualización VirtualBox o la plataforma de microprocesadores Sparc.

La adquisición de Oracle generó dudas por la cultura de empresa más cerrada que la que tenía Sun que contribuyó e influenció notablemente en el mundo tecnológico aún a día de hoy. Después de unos meses de la adquisición varias personas salieron de la compañía como James Gosling creador de Java, Tim Bray creador de formato XML, Kohsuke Kawaguchi desarrollador principal de Hudson o Bryan Cantrill creador de DTrace.

¿Cuál fue el error o errores de Sun Microsystems para que teniendo unas tecnologías tan importantes tuviese problemas económicos como para que fuese vendida? Fue una de las empresas más afectadas por el estallido de la burbuja de las punto com y una pérdida importante de clientes grandes. Posiblemente el fallo fue que aún poseyendo grandes tecnologías y habiendo realizado importantes adquisiciones, algunas de dudoso acierto y muy caras, no fue capaz de rentabilizarlas económicamente, quizá que GNU/Linux le estuviese haciendo competencia al sistema Solaris u opciones más económicas como la arquitectura x86 a Sparc.

Oracle se ha deshecho muchas de las tecnologías a las que creía no sacar rentabilidad, otras como Java las ha seguido desarrollando creo en una buena dirección con la publicación de Java 7 y más tarde incluyendo cambios más importantes con Java 8, más recientemente Java 9, 10 y 11. Con Java EE ha dado también un paso importante para proporcionarle un modelo de desarrollo más abierto y rápido traspasando el desarrollo a la fundación Eclipse y adoptando un nuevo nombre de Java EE a Jakarta EE. Algunas otras conserva como VirtualBox con buena salud.

Java Solaris Sparc
LibreOffice MySQL Virtualbox

En el artículo The Java Saga se comentan varios aspectos importantes de Java como que inicialmente este lenguaje estaba orientado a la electrónica donde la fiabilidad es más importante que la rapidez, C++ no era lo suficientemente fiable para lo que Gosling tenía en mente. Diseñaron la primera tableta electrónica, aún así pasa a ser la base de la emergente web para hacerla interactiva. Otro artículo interesante es The downfall of Sun Microsystems en el que precisamente se comenta la falta de rentabilizar varias de sus tecnologías y la crisis de las punto com.

En Sun Microsystems, Inc. se indica que parte del éxito de Java se atribuye a la frase «write once, run anywhere» significando que un programa escrito en Java no tiene que se reescrito para cada sistema operativo de cada computadora. Si es ejecutado en una computadora UNIX, debería ejecutarse en una máquina Windows o Macintosh mediante el uso de la máquina virtual de Java o JVM. La Java Virtual Machine se proporcionaba con UNIX, Macintosh y otros systemas asi como navegadores web como Netscape o Internet Explorer. Esa versatilidad hizo de Java un lenguaje popular al escribir aplicaciones para la web y para varios observadores disminuyendo la importancia de los sistemas operativos.

En 1997 Microsoft viendose amenazada y haciendo uso de su técnica adoptar, extender y extinguir publicó una JVM que era incompatible con otras JVMs rompiendo de forma efectiva la promesa «write once, run anywhere» de los programas Java. En noviembre de 1998 la justicia instó a Microsoft a no distribuir más copias de su versión de Java.

En los artículos La historia de Sun Microsystems, 1ª Parte: Network is the computer y La historia de Sun Microsystems. 2ª Parte: Write Once. Run Everywhere se hace un buen repaso de la historia de esta empresa desde sus inicios e hitos más importantes asi como las personas que intervinieron en ellos pasando por los malos momentos hasta la finalmente adquisición por Oracle. Otro artículo y sus comentarios interesante es Así es como Oracle ha sometido a Sun Microsystems a una muerte larga y agónica.

Por afinidad hacia el open source con su cultura de empresa la que hubiese preferido que adquiriese Sun es Red Hat una compañía que ha demostrado que con el software libre se puede hacer negocio además de contribuir a la comunidad beneficiandose de ella al mismo tiempo, en el año 2012 alcanzó la cifra de 1000 millones de dólares de facturación y 2000 millones en el 2018. Sin embargo, no hubiese sido posible en ese momento porque Red Hat no era lo suficientemente grande como para hacer una adquisición de tal tamaño para con Sun Microsystems.

Sun Microsystems dejó una larga herencia que dura aún en día y frases legendarias y visionarias como «the network is the computer» atribuida a John Gage o «write once, run anywhere» de Java.

» Leer más, comentarios, etc...

Blog Bitix

Sun Microsystems cae

octubre 19, 2018 09:00

Sun Microsystems
Oracle

Era enero del 2010 y se anunciaba que Oracle adquiría Sun Microsystems por unos 7400 millones de dólares. Sun Microsystems era asimilada por uno de los grandes entre el mundo empresarial. Fue un hecho importante debido a varias de las tecnologías que había desarrollado Sun y poseía como aún a día de hoy uno de los lenguajes más populares para el desarrollo de software, Java, y otras tecnologías importantes que había adquirido hace no tanto tiempo como la base de datos MySQL competencia de Oracle.

Otras tecnologías de Sun relevantes eran el sistema operativo Solaris, la tecnologías de depuración DTraze, el avanzado sistema de archivos ZFS utilizando a día de hoy en los sistemas BSD, el paquete ofimático OpenOffice predecesora de LibreOffice, la herramienta de automatización de proyectos Hudson también predecesora de Jenkins, el software de virtualización VirtualBox o la plataforma de microprocesadores Sparc.

La adquisición de Oracle generó dudas por la cultura de empresa más cerrada que la que tenía Sun que contribuyó e infiluencio notablemente en el mundo tecnológico aún a día de hoy. Después de unos meses de la adquisición varias personas salieron de la compañía como James Gosling creador de Java, Tim Bray creador de formato XML, Kohsuke Kawaguchi desarrollador principal de Hudson o Bryan Cantrill creador de DTrace.

¿Cuál fue el error o errores de Sun Microsystems para que teniendo unas tecnologías tan importantes tuviese problemas económicos como para que fuese vendida? Fue una de las empresas más afectadas por el estallido de la burbuja de las punto com y una pérdida importante de clientes grandes. Quizá el fallo para mi fue que aún poseyendo grandes tecnologías y habiendo realizado importantes adquisiciones no fue capaz de rentabilizarlas económicamente, quizá que GNU/Linux le estuviese haciendo competencia al sistema Solaris u opciones más económicas como la arquitectura x86 a Sparc.

Oracle se ha deshecho muchas de las tecnologías a las que creía no sacar rentabilidad, otras como Java las ha seguido desarrollando creo en una buena dirección inicialmente con la publicación de Java 7 y más tarde incluyendo cambios más importantes con Java 8, más recientemente Java 9, 10 y 11. Con Java EE ha dado también un paso importante para proporcionarle un modelo de desarrollo más abierto y rápido traspasando el desarrollo a la fundación Eclipse y adoptando un nuevo nombre de Java EE a Jakarta EE. Algunas otras conserva como VirtualBox con buena salud.

En el artículo The Java Saga se comentan varios aspectos importantes de Java como que inicialmente este lenguaje estaba orientado a la electrónica donde la fiabilidad es más importante que la rapidez, C++ no era lo suficientemente fiable para lo que Gosling tenía en mente. Diseñaron la primera tableta electrónica, aún así pasa a ser la base de la emergente web para hacerla interactiva. Otro artículo interesante es The downfall of Sun Microsystems en el que precisamente se comenta la falta de rentabilizar varias de sus tecnologías y la crisis de las punto com.

En Sun Microsystems, Inc. se indica que parte del éxito de Java se atribuye a la frase «write once, run anywhere» significando que un programa escrito en Java no tiene que se reescrito para cada sistema operativo de cada computadora. Si es ejecutado en una computadora UNIX, debería ejecutarse en una máquina Windows o Macintosh mediante el uso de la máquina virtual de Java o JVM. La Java Virtual Machine se proporcionaba con UNIX, Macintosh y otros systemas asi como navegadores web como Netscape o Internet Explorer. Esa versatilidad hizo de Java un lenguaje popular al escribir aplicaciones para la web y para varios observadores hacer disminuir la importancia de los sistemas operativos.

Sin embargo, en 1997 Microsoft mediante su técnica adoptar, extender y extinguir publicó una JVM que era incompatible con otras JVMs rompiendo de forma efectiva la promesa «write once, run anywhere» de los programas Java. En noviembre de 1998 la justicia instó a Microsoft a no distribuir más copias de su versión de Java.

Por afinidad y percepción con su cultura la que a mi me hubiese gustado más que adquiriese Sun es Red Hat una compañía que ha demostrado que con el software libre se puede hacer negocio siendo en en el año 2012 cuando alcanzó la cifra de 1000 millones de dólares de facturación y 2000 millones en el 2018. Sin embargo, no hubiese sido posible en ese momento porque Red Hat no era lo suficientemente grande como para hacer hacer una adquisición de tal tamaño para con Sun Microsystems.

Sun Microsystems dejó una larga herencia que dura aún e día y frases legendarias y visionarias como «the network is the computer» atribuida a John Gage o «write once, run anywhere».

» Leer más, comentarios, etc...

Picando Código

Nintendo en Madrid Games Week

octubre 18, 2018 09:15

Si están en Madrid este fin de semana, no se pierdan Madrid Games Week, la feria del videojuego referente a nivel nacional. Se realiza a partir de hoy 18 de octubre hasta el 21 de octubre en el pabellón 12 de IFEMA.

Nintendo va a tener una gran presencia, con 850 metros cuadrados de espacio dedicado a Nintendo Switch y más de 90 puestos de juego. Van a haber más de 30 juegos a disposición de los asistentes, incluyendo Super Smash Bros. Ultimate y Pokémon Let’s Go Pikachu y Pokémon Let’s Go Eevee.

Nintendo en Madrid Games Week

El “¡Todos están aquí!” es la expresión perfecta para hablar de Super Smash Bros. Ultimate, el crossover de personajes que no solo enfrenta en divertidos y frenéticos combates a Mario, Link, Pikachu, y otros personajes de toda la historia de Nintendo, sino que engloba a grandes estrellas invitadas y todos los personajes que han estado alguna vez en la saga Smash, como los míticos Sonic y Pac-Man. El juego más completo de la saga, con más de 70 personajes y más de 100 escenarios, llegará a las tiendas el 7 de diciembre, pero todos los asistentes a Madrid Games Week podrán probarlo meses antes de su lanzamiento.

Estarán también todos los Pokémon de la primera generación por primera vez en Nintendo Switch, y por primera vez en España, gracias a Pokémon: Let’s Go, Pikachu! y Pokémon: Let’s Go, Eevee!. Madrid Games Week será la primera oportunidad que tendrán los fans de todo el país para probar esta nueva aventura que combina elementos de la saga clásica con elementos de Pokémon GO, el fenómeno de masas que a día de hoy sigue superando récords de actividad gracias a su entregada comunidad. Pokémon: Let’s Go, Pikachu! y Pokémon: Let’s Go, Eevee! se pondrán a la venta el próximo 16 de noviembre, y los asistentes a la feria podrán probar varias de sus novedades, como el modo cooperativo para explorar, capturar y combatir en compañía, y el control con el nuevo accesorio Poké Ball Plus.

En la Zona Mario los asistentes se podrán montar fiestas sobre la marcha con sus acompañantes y disfrutar con los minijuegos de Super Mario Party, o demostrarán quién es el rey de la pista con Mario Tennis Aces y quién domina mejor el volante y los caparazones con Mario Kart 8 Deluxe.

Las aventuras de mayor calibre están en la Zona RPG, como The Legend of Zelda: Breath of the Wild, el considerado por la crítica (y el autor de este blog) como el mejor juego del año 2017 y uno de los mejores de la historia.

En la Zona de Acción y deportes no sólo están títulos exclusivos de Nintendo Switch como Splatoon 2. El apoyo third party está patente en EA SPORTS FIFA 19, Dragon Ball FighterZ y el gran fenómeno de Fortnite en un formato que permite jugar en cualquier lugar. Ubisoft tendrá un gran peso en esta zona con Starlink: Battle for Atlas, el título de acción y exploración espacial que el mismísimo Shigeru Miyamoto presentó en el pasado E3.

Nintendo Switch, la consola de los indies

Nintendo Switch es la consola en la que todos los desarrolladores independientes quieren estar. Así, la Zona Nindies crece con un gran número de experiencias diferentes, con títulos
ya considerados por muchos como inolvidables como Celeste, Hollow Knight, Dead Cells, y apuestas con la originalidad por bandera como Toki, Flipping Death, The Gardens Between.

Todos los asistentes al stand de Nintendo en Madrid Games Week tendrán la posibilidad de llevarse una de las dos Nintendo Switch que se sortearán cada día (de viernes a
domingo) entre todos aquellos que hayan conseguido un número de sellos por jugar en cada una de las diferentes zonas. A través de Twitter también se sortearán tres Nintendo Switch
entre todos aquellos que tuiteen una foto desde cualquier lugar del stand utilizando el hashtag #NintendoEnMGW.

Quien busque la diversión en la emoción de la competición, también tendrá su lugar en el stand de Nintendo en Madrid Games Week. Los asistentes podrán inscribirse en los torneos de Mario Tennis Aces y Mario Kart 8 Deluxe, y para quienes disfruten de ver una competición de alto nivel tanto como de jugar, se celebrará un Torneo Invitacional de Super Smash Bros. Ultimate, en el que los mejores jugadores del país se enfrentarán en frenéticos combates.

La guinda al pastel de la competición la pone la clasificación nacional del Splatoon 2 European Championship 2019, en el que los mejores equipos de inklings y octolings se llenarán las caras de tinta para demostrar quién merece representar a España en el campeonato europeo que se celebrará en primavera de 2019.

Están los juegos más esperados meses antes de su lanzamiento, están los juegos third party en las mejores versiones para jugar en cualquier lugar, están los Nindies, están los mejores
juegos para la diversión en familia, están las aventuras más sorprendentes, están las competiciones de alto nivel, están los regalos y sorteos… Todos están aquí, ¡solo faltas tú!

Más información:
http://www.nintendo.es
https://www.nintendo.es/nintendoswitch
https://twitter.com/nintendoes
https://www.facebook.com/NintendoES
https://www.facebook.com/NintendoSwitchES
http://www.youtube.com/NintendoES
https://instagram.com/nintendoes/
https://www.instagram.com/NintendoSwitchES

Sobre Nintendo
Pionera en la creación de entretenimiento interactivo, Nintendo Co., Ltd., con sede en Kioto (Japón), fabrica y distribuye hardware y software para su consola de sobremesa Nintendo Switch, y para las familias de consolas portátiles. Desde 1983, cuando lanzó la Nintendo Entertainment System (NES), Nintendo ha vendido más de 4.600 millones de videojuegos y más de 725 millones de unidades de hardware en todo el mundo, incluyendo las actuales consolas Nintendo Switch, New Nintendo 3DS y New Nintendo 3DS XL, Nintendo 3DS, Nintendo 3DS XL y Nintendo 2DS, así como Game Boy™, Game Boy Advance, Super NES™, Nintendo 64™, Nintendo GameCube™, Wii, Nintendo DS, Nintendo DSi, Nintendo DSi XL y Wii U. También ha creado personajes tan conocidos como Mario™, Donkey Kong™, Metroid™, Zelda™ y Pokémon™. Como empresa subsidiaria, Nintendo Ibérica, S.A., con sede en Madrid, actúa como sede central de operaciones de Nintendo en España y Portugal.

» Leer más, comentarios, etc...

Picando Código

10 años de la Ley de Acceso a la Información Pública en Uruguay

octubre 16, 2018 01:30

Hoy se celebran 10 años de la Ley de Acceso a la Información Pública en Uruguay. Una ley que ha ayudado mucho a los datos abiertos y la transparencia, en algunos casos. Gracias a esta ley podemos hacer un pedido de información directamente desde la web con ¿Qué Sabés?.

Para celebrar el aniversario, Fabrizio Scrollini lista 10 cosas que deberíamos ir pensando sobre cómo solucionar en los próximos 10:

1) Aún tenemos organismos que o bien no publican información, o no responden pedidos de acceso. Trasciende partidos, y hay hasta quien quiso (caso de la Intendencia de Maldonado) declarar la ley inconstitucional. Esto no debería ser aceptable.

2) En el país líder en América Latina en gobierno electrónico, hay organismos que no responden pedidos vía correo electrónico. No solo es irónico. Está desfasado de la realidad del siglo XX (ya ni XXI)

3) Necesitamos más recursos para el organismo regulador y posiblemente un nuevo diseño institucional. Eso debería ayudar con el cumplimiento de la ley y la capacitación del servicio civil.

4) En estos 10 años han existido interpretaciones disparatadas (y otras respetables) del Poder judicial sobre como aplicar excepciones. Necesitamos generar doctrina legal adecuada y consistente.

5) La actividades de formación ciudadana son importantes. Deberían escalarse lo cual asume recursos. Solo un 25 % de la ciudadanía (aproximadamente) conoce este derecho y es clave que más lo conozcan.

6) Los programas de Datos Abiertos deben ser fotalecidos para favorecer más publicación y uso de la ley en formas no tradicionales. Ahí vamos por buen camino y podemos hacer mucho más.

7) Nos debemos una conversación seria sobre transparencia en el sector de seguridad y defensa. Está claro que no todo puede ser público pero hay mucha información útil para la ciudadanía y para evaluar que no está aún disponible.

8) Hay un problema en todas las tiendas políticas. La transparencia no gusta. Hay declaraciones disparatas. Precisamos fortalecer una sociedad civil que cobre ese tipo de declaraciones y eso debe incluir financiamiento público.

9) No existe no tener registros ni archivos adecuados sobre los pedidos que se responden. No solo pasa en Uruguay, pero no se puede medir lo que no se cuenta. Si nos vamos a quejar que hay muchos pedidos y toma trabajo, al menos midamos.

10) Seguimos precisando de medios de prensa que molesten al poder y hagan uso de estas herramientas. Cada vez hay más. También la administración ha adaptado sus prácticas. Esconder información no es jugar limpio.

Bonustrack 11). Creer que nuestra democracia ha mejorado solo por esta ley sería un error. Hay gente que resiste la transparencia en todas las tiendas partidarias e institucionales. Son la gente que puede ayudar a que nuestra democracia deje de ser seria.

» Leer más, comentarios, etc...

Bitácora de Javier Gutiérrez Chamorro (Guti)

Watcom C++ y Sieve para DOS

octubre 15, 2018 07:20

Hace unos años redacté Sieve en C, una macro-comparativa del rendimiento de diferentes compiladores de C/C++ para Windows ejecutando una implementación de la Criba de Eratóstenes o Sieve. Unos días atrás publiqué Visual C++ 2008 vs Visual C++ 2017, y volvió a picarme el gusanillo sobre lo que ha evolucionado la calidad del código generado […]

La entrada Watcom C++ y Sieve para DOS aparece primero en Bitácora de Javier Gutiérrez Chamorro (Guti).

» Leer más, comentarios, etc...

Blog Bitix

Proxy para microservicios con Spring Cloud Netflix y Zuul

octubre 13, 2018 09:00

Spring
Java

Teniendo una buen número de microservicios con múltiples instancias ofreciendo cada uno una API y en una ubicación diferente para simplificar la visión de los que actúen clientes de los microservicios se puede utilizar un proxy. Con un proxy es posible centralizar todas las peticiones, que sea éste el encargado de conocer la ubicación de todas las instancias de los microservicios y de hacer la llamada allí donde se encuentre cada una de ellas.

Entre las varias funcionalidades que proporcionar el proyecto Spring Cloud Netflix es esta de proxy mediante Zuul. Para hacer de proxy Zuul necesita tener una correspondencia entre URLs y servicios que realmente proporcionan la funcionalidad, una forma que tiene Zuul de conocer la ubicación de las instancias es utilizando el servicio de registro y descubrimiento Eureka. Además, Zuul como cliente de los microservicios posee la funcionalidad de Hystrix que implementa el patrón circuit breaker para tolerancia a fallos, Ribbon para hacer balanceo de carga entre varias instancias de los microservicios a nivel de servidor además de reintentos cuando una instancia falla.

En el ejemplo que he utilizado para esta serie de artículos sobre Spring Cloud hay un servicio que por defecto se inicia en el puerto 8080 y ofrece un endpoint / que devuelve un mensaje. Para crear un microservicio proxy con Zuul hay que crear una aplicación Spring Boot anotar la clase principal con la anotación @EnableZuulProxy y proporcionar la configuración para la correspondencia de rutas y microservicios, además de las propiedades para hacer reintentos en caso de que un microservicio falle y de timeouts en caso de que se comporte no como se espera en cuanto tiempos de respuesta.

Se puede establecer un tiempo máximo para establecer la conexión, de tiempo de petición, el número de reintentos en la misma instancia si falla o en otro número de instancias, el número máximo de conexiones y el número máximo de conexiones al mismo host. Todas ellas definibles en cada servicio de forma individual bajo las propiedades hystrix.command.service y service.ribbon donde service es el identificativo del servicio. Las rutas se indican bajo la propiedad zuul.routes con la relación identificativo del servicio y path.

Dado que Zuul es un proxy para múltiples instancias de microservicios a cada microservicio hay que darle una ruta, cuando Zuul realiza la llamada a una instancia del microservicio se encarga de omitirla. En el ejemplo, la ruta en Zuul /service/** está asociada al microservicio service pero el servicio service ofrece su endpoint en /, Zuul se encarga de omitir la parte de la ruta para el proxy y hace la llamada a la ruta / como espera el microservicio.

Lógicamente los clientes deben contactar con el proxy en vez de con el microservicio directamente. Arrancado el servicio de descubrimiento y registro Eureka, el servidor de configuración de Spring Cloud, dos instancias del servicio y el proxy con Zuul haciendo las llamadas al proxy se observa que se obtiene el resultado del microservicio. Como en el ejemplo hay varias instancias del servicio Zuul realiza balanceo de carga entre ellas con Ribbon utilizando la política round-robin y el mensaje es diferente en cada una de las respuestas según la instancia invocada. Con Zuul además se consigue balanceo de carga a nivel de servidor que Ribbon solo ofrece a nivel de cliente.

Las URLs del servicio en el microservicio y en el proxy son.

El cliente de ejemplo realiza peticiones al proxy, en la salida se muestra el resultado del balanceo de carga cuando hay varias instancias, cuando se añade una nueva instancia entra a formar parte del balanceo de carga. Otro beneficio de Zuul es que ofrece la funcionalidad de reintentos de modo que si una instancia de un servicio falla la petición se reintenta en otra. En el artículo Balanceo de carga y resilencia en un microservicio con Spring Cloud Netflix y Ribbon usando solo Ribbon se observaba que cuando una instancia falla se le siguen haciendo peticiones hasta que la lista de instancias del servicio en Eureka se actualiza quitando la fallida, con Hystrix se obtiene la respuesta fallback pero no se evita completamente el error. Zuul puede ocultar el error provocado por una instancia que falla reintentado la petición en la misma nuevamente, en otra u otras instancias según se configure. El comportamiento con Zuul cuando una instancia falla se puede comparar con el comportamiento incluido en el artículo anterior usando en el cliente los microservicios directamente.

Zuul además es capaz de proporciona otras muchas funcionalidades como:

  • Autenticación
  • Seguridad
  • Recolección de métricas y monitorización
  • Pruebas de carga
  • Pruebas de verificación o canary testing
  • Enrutado dinámico
  • Migración de servicio
  • Abandono de carga o load shedding
  • Manejo de respuesta estática
  • Gestión de tráfico active/active

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.sh.

» Leer más, comentarios, etc...

Blog Bitix

Balanceo de carga y resilencia en un microservicio con Spring Cloud Netflix y Ribbon

octubre 12, 2018 06:46

Spring
Java

Un servicio que recibe numerosas peticiones o es crítico para el funcionamiento de una aplicación es necesario escalarlo o crear múltiples instancias de él para atender toda la carga que se demanda o para que en caso de que una instancia falle haya otras disponibles que funcionen correctamente para atender las peticiones.

En este entorno de múltiples instancias se hace necesario un servicio de registro y descubrimiento que usando Spring, Spring Boot y Spring Cloud Netflix una implementación es Eureka. Una vez descubiertas las instancias que hay del servicio es necesario hacer balanceo de carga para conseguir escalabilidad y tolerancia a fallos, en el mismo proyecto de Spring Cloud Netflix para realizar balanceo de carga en el cliente se ofrece Ribbon.

Hay varias formas de usar Ribbon una de ellas es con lo que denominan feign client, con Spring RestTemplate o directamente con LoadBalancerClient que es la que muestro en este artículo. Este cliente con Ribbon obtiene del servicio de registro y descubrimiento la lista inicial de instancias de un servicios registrado con sus ubicaciones siendo el host en el que se encuentran y el puerto en el que ofrecen su servicio. Con esta lista y el estado de los servicios se realiza el balanceo de carga. Sin embargo, dada la naturaleza de los microservicios se pueden añadir con posterioridad más instancias de un servicio o algunas pueden empezar fallar, Ribbon se encarga de mantener actualizada la lista de instancias de un servicio.

Combinado con Hystrix un ejemplo de cliente que hace peticiones a un servicio es el siguiente. Para demostrar su funcionamiento el cliente realiza varias llamadas a un servicio cada unos pocos milisegundos balanceando la carga entre las instancias que existan. Si con posterioridad se añade una nueva instancia del servicio Ribbon al cabo de un tiempo de que haya sido iniciada lo añadirá a la lista y empieza a seleccionarla para enviarle peticiones. Si una instancia falla hasta que Eureka no marca la instancia como fuera de servicio y el cliente no actualiza su lista de instancias en el ejemplo de cliente seguirá enviando peticiones a la instancia fuera de servicio y con Hystrix utilizando el método de fallback como respuesta.

Ante el fallo de una instancia para evitar que temporalmente el cliente empiece a fallar cuando le redirige una petición este puede reintentar las peticiones en otra instancia, esta funcionalidad se proporciona con Spring Retry o utilizando Zuul como proxy.

El cliente usa la clase LoadBalancerClient que en cada invocación del método choose() devuelve una instancia diferente de servicio realizando balanceo de carga utilizando el método round-robin. La clase ServiceInstance proporciona la URL de la instancia del servicio.

La clase del servicio y los comandos para iniciar el servicio de registro y descubrimiento, el servicio de configuración, las instancias del servicio en diferentes puertos y el cliente.

Esta es la salida y funcionamiento del cliente realizando balanceado la carga entre las mútiples instancias y que ocurre cuando se añade una nueva o una empieza a fallar y se elimina de la lista.

Ribbon posee numerosas propiedades de configuración a nivel global para todos los clientes de servicios o de forma específica para cada servicio ya sea con la anotación @RibbonClient o mediante la configuración en archivos externos de Spring Boot. Algunas propiedades de configuración interesantes son las de timeout que permiten que un cliente no agote sus recursos esperando a que a los servicios que llama si tardan en responder y a su vez el cliente actuando de servidor recibe muchas llamadas de sus clientes. En un comando de Hystrix también se puede especificar un timeout de modo que si se realizan reintentos el tiempo total para Hystrix deberá ser superior que el tiempo total de todos los posibles reintentos teniendo en cuenta el timeout del cliente con Ribbon. Unsando el cliente HTTP Jersey como en este caso también pueden establecerse timeouts para una petición.

El balanceo de carga que con Ribbon se realiza en el cliente es más sencillo que realizar el balanceo de carga en el servidor ya que no requiere una pieza más en la infraestructura pero requiere que el cliente tenga algo de lógica para hacer el balanceo de carga.

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.

» Leer más, comentarios, etc...

Picando Código

Taller de tidyverse: manipulación y transformación de datos en R por R-Ladies Montevideo

octubre 11, 2018 08:05

R-Ladies Montevideo

La organización mundial que promueve la diversidad de género en la comunidad de R, R-Ladies, tiene una instancia en Uruguay: R-Ladies MVD. El martes 23 de octubre organizan su cuarto encuentro: Taller de manipulación y transformación de datos con tidyverse en R por Lucía Coudet.

La cita es en Scanntech (Duvimioso Terra 1975) a las 19:00. Pueden confirmar asistencia en este enlace.

Pueden unirse y estar al tanto de su actividad en Meetup o seguir la organización en Twitter.

» Leer más, comentarios, etc...

Variable not found

Enlaces interesantes 333

octubre 09, 2018 09:10

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

Por si te lo perdiste...

.NET / .NET Core

.NET timeline

ASP.NET / ASP.NET Core

Azure / Cloud

    Data

    HTML / CSS / Javascript

    Visual Studio / Complementos / Herramientas

    Xamarin

    Otros

    Publicado en Variable not found.
    Publicado en: www.variablenotfound.com.

    » Leer más, comentarios, etc...

    Fixed Buffer

    Inyección de Dependencias en .Net Framework

    octubre 09, 2018 08:00

    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.**

    » Leer más, comentarios, etc...

    proyectos Ágiles

    Auto-organización – Fundamentos y relación con la motivación intrínseca

    octubre 09, 2018 05:30

    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 responsabilidad sobre 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

     

     

    » Leer más, comentarios, etc...

    Navegapolis

    Las organizaciones triunfan por el compromiso de su gente

    octubre 06, 2018 08:28

    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.

     

     

     

    » Leer más, comentarios, etc...

    Blog Bitix

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

    octubre 06, 2018 07:30

    Spring
    Java

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

    Un patrón o técnica que se suele emplear es el de Circuit Breaker, en Java y con Spring se ofrece en el proyecto Spring Cloud Netflix mediante Hystrix y Javanica. Este patrón soluciona dos problemas cuando un microservicio del que se depende falla y hace al microservicio que lo usa tolerante a fallos.

    • Uno es que cuando un microservicio empieza a fallar es necesario dejar de hacerle peticiones para permitirle recuperarse si está saturado que provoca esos fallos. Cuando ocurre un fallo es posible realizar una acción en sustitución de la llamada al microservicio y devolver un valor alternativo como medida paliativa y hacer que el microsevicio afectado tenga la posibilidad de seguir ofreciendo su servicio aunque sea de forma degradada.
    • 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 e igualmente se realiza la acción de sustitución lo que evita que los microservicios que usan uno que tarda demasiado en responder agoten sus recursos y empiecen a fallar o tardar demasiado también.

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

    Hystrix

    El patrón circuit breaker se denomina así ya que implementa una lógica similar a un circuito eléctrico. El circuito en su estado normal está cerrado y se realizan las llamadas al microservicio servidor. Si el microservicio servidor empieza a fallar se llama a la acción alternativa con su valor, si se supera un umbral de errores el circuito pasa a estado abierto y se dejan de hacer llamadas al microservicio servidor. Cada cierto tiempo definido se realiza una llamada al servicio servidor para comprobar su estado de forma que si responde correctamente el circuito pasa a estado cerrado nuevamente y las siguientes llamadas se realizan al microservicio servidor 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 encapsularse en un método anotado con la anotación @HystrixCommand, como parámetro se indica un método con la acción alternativa o fallback que obtiene un valor en los fallos. También se puede indicar el tiemout de espera antes de considerar que la llamada ha fallado con la propiedad execution.isolation.thread.timeoutInMilliseconds. Igualmente se pueden indicar los valores para abrir el circuito con circuitBreaker.requestVolumeThreshold y circuitBreaker.errorThresholdPercentage. Esos son los básicos 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 y 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 un porcentaje de fallos, se han de cumplir 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 al menos durante el tiempo indicado por metrics.rollingStats.timeInMilliseconds.

    En la aplicación ejemplo hay un microservicio servidor y un microservicio cliente, iniciada 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 las peticiones del cliente al servidor empezarán a fallar y este obtiene el valor alternativo del método fallback, si se supera el umbral de llamadas y de fallos el circuito pasa a estado abierto. Mientras el circuito permanezca abierto el cliente sondea con una petición cada cierto tiempo el estado del servidor, si el servicio servidor se inicia unos instantes después de que esté disponible el cliente con la petición de sondeo comprobará que el servidor funciona, se cerrará el circuito y el cliente empezará a obtener los valores devueltos por el microservicio servidor.

    Para monitorizar en tiempo real el estado del sistema y de los circuitos se ofrece un dashboard en el que visualizan 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 dashboard 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.

    » Leer más, comentarios, etc...

    Variable not found

    Quizás no estés comparando con null de forma totalmente correcta

    octubre 02, 2018 09:08

    ¿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.

    » Leer más, comentarios, etc...

    Variable not found

    Enlaces interesantes 332

    octubre 01, 2018 07:15

    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.

    » Leer más, comentarios, etc...

    Navegapolis

    ¿Expertos o eternos principiantes?

    septiembre 30, 2018 12:28

    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

     

     

    » Leer más, comentarios, etc...

    Blog Bitix

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

    septiembre 29, 2018 11:40

    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, encrypt.key. En este ejemplo la clave simétrica y las propiedades cifradas están en archivos de configuración diferentes pero incluidos en el mismo servidor de configuración. Esto no parece que aporte mucha seguridad ya que si se tiene acceso al archivo de configuración de un servicio con una propiedad cifrada probablemente se tenga acceso al archivo con la clave cifrada y la medida de seguridad no es útil. Sin embargo, esto permite al estar separados los archivos de configuración añadir el archivo con la propiedad cifrada a un repositorio público sin peligro siempre y cuando la clave de cifrado se mantenga en secreto. Los archivos de configuración de los servicios en el servidor de configuración se podrían añadir a un repositorio de Git.

    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.

    » Leer más, comentarios, etc...

    Picando Código

    Profiling de Emacs e instalación Emacs 26

    septiembre 28, 2018 09:44

    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 🙌🏻

    » Leer más, comentarios, etc...

    Una sinfonía en C#

    #NetConf en la Universidad Politécnica de Madrid

    septiembre 27, 2018 09:57

    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.

    » Leer más, comentarios, etc...

    Bitácora de Javier Gutiérrez Chamorro (Guti)

    Análisis estático de FileOptimizer

    septiembre 27, 2018 06:36

    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).

    » Leer más, comentarios, etc...

    Variable not found

    ¿Aplicar [Authorize] a todos los controladores MVC de una carpeta?

    septiembre 25, 2018 08:50

    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.

    » Leer más, comentarios, etc...

    Fixed Buffer

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

    septiembre 25, 2018 08:00

    Entity Framework Core

    Venimos con la segunda parte de “Haciendo fácil el acceso a datos con Entity Framework Core“. Esta vez, vamos a hacer el mismo ejemplo, pero con la opción “Code First”. Utilizando esta opción, vamos a generar nuestra base de datos mediante clases que relacionaremos entre ellas, así veremos las dos caras de la moneda.

    Modelo

    Tengamos el objetivo claro, mediante la opción “Code First” vamos a buscar conseguir un modelo como este:
    Modelo DB

    En el tenemos 2 relaciones 1 a muchos:

    1. Un profesor podrá impartir varios cursos.
    2. Cada curso puede tener varios alumnos.

    Creando la solución en Visual Studio

    En primer lugar, vamos a crear el proyecto, solo que esta vez, será un proyecto de consola Net Core:

    consola .net core

    Paquetes

    Como la vez anterior, instalamos los paquetes de Entity Framework Core vía NuGet:

    efctools

    En caso de querer hacerlo vía consola:

    PM->Install-Package Microsoft.EntityFrameworkCore -Version 2.1.3
    PM->Install-Package Microsoft.EntityFrameworkCore.Tools -Version 2.1.3

    Y lo mismo para el proveedor de MySql

    pomelo

    O como siempre, por consola:

    PM->Install-Package Pomelo.EntityFrameworkCore.MySql -Version 2.1.2

    Creando la solución en DotNet CLI

    Una de las ventajas de Net Core es que nos permite ejecutar sus acciones desde línea de comandos, con eso, conseguimos toda la funcionalidad en plataformas como Linux. En este caso, utilizaremos la Powershell. Para crear un proyecto, crearemos una carpeta y navegaremos a ella con:

    – mkdir PostEntityCore
    – cd PostEntityCore

    Una vez dentro de la carpeta, crearemos el proyecto y añadiremos los paquetes con:

    – dotnet new console
    – dotnet add package Microsoft.EntityFrameworkCore -v 2.1.3
    – dotnet add package Microsoft.EntityFrameworkCore.Tools -v 2.1.3
    – dotnet add package Pomelo.EntityFrameworkCore.MySql -v 2.1.2

    Generando el DbContext

    En este caso, el modelo lo vamos a generar mediante clases en nuestro proyecto, a fin de organizar el proyecto, añadiremos una carpeta “Data” a la solución, donde añadiremos las siguientes clases:

    Entity Framework Core

    Vamos a desgranar las clases:

    //Alumnos.cs
    using System;
    using System.ComponentModel.DataAnnotations;
    
    namespace PostCore.Data
    {
        public class Alumnos
        {
            [Key]
            public int IdAlumno { get; set; } //Clave primaria
            public string Nombre { get; set; } 
            public DateTime Nacimiento { get; set; }
            public int IdCurso { get; set; } //Campo clave foranea
    
            //Entity Framewrok Core
            public Cursos Curso { get; set; } //Objeto de navegación virtual EFC
        }
    }
    
    //Cursos.cs
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    
    namespace PostCore.Data
    {
        public class Cursos
        {
            //Inicializamos el objeto de navegacion virtual de Entity Framework Core
            public Cursos()
            {
                Alumnos = new HashSet<Alumnos>();
            }
    
            [Key]
            public int IdCurso { get; set; } //Clave primaria
            public string Nombre { get; set; }
            public string Ciudad { get; set; }
            public int IdProfesor { get; set; } //Campo clave foranea
    
            //Entity Framewrok Core
            public Profesores Profesor { get; set; } //Objeto de navegación virtual EFC
            public ICollection<Alumnos> Alumnos { get; set; } //Objeto de navegación virtual EFC
        }
    }
    
    //Profesores.cs
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    
    namespace PostCore.Data
    {
        public class Profesores
        {
            //Inicializamos el objeto de navegacion virtual de Entity Framework Core
            public Profesores()
            {
                Cursos = new HashSet<Cursos>();
            }
            [Key]
            public int IdProfesor { get; set; } //Clave primaria
            public string Nombre { get; set; }
    
            //Entity Framewrok Core
            public ICollection<Cursos> Cursos { get; set; } //Objeto de navegación virtual EFC
        }
    }
    
    //PostDbContext.cs
    using Microsoft.EntityFrameworkCore;
    
    namespace PostCore.Data
    {
        //Heredamos de DbContext nuestro contexto
        class PostDbContext : DbContext
        {
            //Constructor sin parametros
            public PostDbContext()       
            {
            }
    
            //Constructor con parametros para la configuracion
            public PostDbContext(DbContextOptions options)
            : base(options)
            {
            }
    
            //Sobreescribimos el metodo OnConfiguring para hacer los ajustes que queramos en caso de
            //llamar al constructor sin parametros
            protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            {
                //En caso de que el contexto no este configurado, lo configuramos mediante la cadena de conexion
                if (!optionsBuilder.IsConfigured) 
                {
                    optionsBuilder.UseMySql("Server=localhost;Database=postefcore;Uid=root;Pwd=root;");
                }
            }
    
            //Tablas de datos
            public virtual DbSet Alumnos { get; set; }
            public virtual DbSet Cursos { get; set; }
            public virtual DbSet Profesores { get; set; }
        }
    }

    Entity Framework Core “Code First” en Visual Studio

    Una vez tenemos el contexto creado en nuestro proyecto, iremos a la “Consola del Administrador de paquetes”, y ahí dispondremos de estos comandos:

    1. add-migration {nombre} -Context {contexto}
    2. remove-migration
    3. update-database {nombre} -Context {contexto}
    4. drop-database -Context {contexto}

    Vamos a explicar los comandos:

    add-migration: Con este comando, generaremos la migración que lanzaremos a la base de datos. Este comando tiene 2 parámetros:

    1. {nombre}: Con este parámetro indicaremos el nombre que queremos indicarle a la migración, ademas, es obligatorio.
    2. -Context {contexto}: En caso de tener más de un contexto de datos en nuestro programa, indicaremos cual de los contextos es mediante este parámetro. Si solo tenemos un contexto de datos, no es obligatorio usarlo.

    remove-migration: Con este comando, eliminaremos la ultima migración que hemos generado. Se puede utilizar varias veces consecutivamente para ir eliminando migraciones desde la última a la primera.

    update-database: Con este comando, enviaremos a la base de datos los cambios de la migración, haciéndola efectiva:

    1. {nombre}: Con este parámetro indicaremos el nombre de la migración que queremos aplicar.
    2. -Context {contexto}: En caso de tener más de un contexto de datos en nuestro programa, indicaremos cual de los contextos es mediante este parámetro. Si solo tenemos un contexto de datos, no es obligatorio usarlo.

    drop-database: Con este comando, eliminaremos la base de datos. Este comando tiene 1 parámetro:

    1. -Context {contexto}: En caso de tener más de un contexto de datos en nuestro programa, indicaremos cual de los contextos es mediante este parámetro. Si solo tenemos un contexto de datos, no es obligatorio usarlo.

    Una vez que conocemos los comandos, vamos a ponernos en faena… Para empezar, utilizamos el comando:

    add-migration init -Context PostDbContext

    Esto genera una carpeta “Migrations” donde va a ir guardando cada una de las migraciones. Conviene no borrar el contenido, ya que almacena las “versiones” del contexto de datos, de modo que podemos revertir los cambios en la base de datos. Ademas, el hecho de almacenar estas migraciones, permite al sistema aplicar cambios de manera incremental en las próximas migraciones, y es requisito para poder aplicar cambios a la base de datos sin que se produzcan errores por tablas ya existentes.

    Con eso, ejecutamos:

    update-database -Context PostDbContext

    Entity Framework Core “Code First” en DotNet CLI

    Igualmente, podemos hacer toda la labor desde el cli de dotnet con los comandos equivalentes de “dotnet ef”:

    1. migrations add {nombre} -c {contexto}
    2. migrations remove
    3. database update {nombre} -c {contexto}
    4. database  drop -c {contexto}

    Vamos a explicar los comandos:

    migrations add: Con este comando, generaremos la migración que lanzaremos a la base de datos. Este comando tiene 2 parámetros:

    1. {nombre}: Con este parámetro indicaremos el nombre que queremos indicarle a la migración, ademas, es obligatorio.
    2. -c {contexto}: En caso de tener más de un contexto de datos en nuestro programa, indicaremos cual de los contextos es mediante este parámetro. Si solo tenemos un contexto de datos, no es obligatorio usarlo.

    migrations remove: Con este comando, eliminaremos la ultima migración que hemos generado. Se puede utilizar varias veces consecutivamente para ir eliminando migraciones desde la última a la primera.

    database update: Con este comando, enviaremos a la base de datos los cambios de la migración, haciéndola efectiva:

    1. {nombre}: Con este parámetro indicaremos el nombre de la migración que queremos aplicar.
    2. -c {contexto}: En caso de tener más de un contexto de datos en nuestro programa, indicaremos cual de los contextos es mediante este parámetro. Si solo tenemos un contexto de datos, no es obligatorio usarlo.

    database drop: Con este comando, eliminaremos la base de datos. Este comando tiene 1 parámetro:

    1. -c {contexto}: En caso de tener más de un contexto de datos en nuestro programa, indicaremos cual de los contextos es mediante este parámetro. Si solo tenemos un contexto de datos, no es obligatorio usarlo.

    Una vez que conocemos los comandos del CLI, vamos a ello

    dotnet ef migrations add init -c PostDbContext

    En este caso, debemos tener las mismas cosas en consideración que si lo hiciésemos desde Visual Studio.

    Con eso, ejecutamos:

    dotnet ef database update -c PostDbContext

    Resultado

    Una vez hecho esto de cualquiera de las 2 maneras, desde el gestor de nuestra base de datos, veremos que se ha creado la base de datos, y si aplicamos la ingeniería inversa para reconstruir el modelo (desde el MySql Workbench), veremos algo así:Entity Framework Core:

    Vemos que hemos conseguido generar el modelo que queríamos, pero tenemos una tabla más, “__efmigrationshistory”, en esta tabla es donde Entity Framework Core registra las versiones del contexto que están aplicadas en la base de datos.

    Ejemplo

    En mi perfil de GitHub he dejado un ejemplo del proyecto, el cual una vez aplicadas las migraciones sobre la base de datos, podemos ver que funciona correctamente ante la misma lógica de programa de la primera parte:

    using (postefcoreContext context = new postefcoreContext())
    {
        //Creamos el profesor
        Profesores profesor = new Profesores() {Nombre = "Pedro" };
        context.Add(profesor);
        //Creamos los cursos
        Cursos curso1 = new Cursos() { Nombre = "Matematicas", IdProfesor = profesor.IdProfesor };
        context.Add(curso1);
        Cursos curso2 = new Cursos() { Nombre = "Lenguaje", IdProfesor = profesor.IdProfesor };
        context.Add(curso2);
        //Creamos los alumnos
        Alumnos alumno1 = new Alumnos() { Nombre = "Jorge", IdCurso = curso1.IdCurso };
        context.Add(alumno1);
        Alumnos alumno2 = new Alumnos() { Nombre = "Juan", IdCurso = curso1.IdCurso };
        context.Add(alumno2);
        Alumnos alumno3 = new Alumnos() { Nombre = "Andrea", IdCurso = curso2.IdCurso };
        context.Add(alumno3);
        Alumnos alumno4 = new Alumnos() { Nombre = "Sandra", IdCurso = curso2.IdCurso };
        context.Add(alumno4);
        //Guardamos los cambios
        context.SaveChanges();
    }
    
    using (postefcoreContext context = new postefcoreContext())
    {
        var profesor = context.Profesores //Indicamos la tabla
                              .Include(x => x.Cursos) //Incluimos los resultados coincidentes de la tabla cursos (inner join)
                              .ThenInclude(x => x.Alumnos) //Incluimos los resultados coincidentes de la tabla alumnos (inner join)
                              .First(); //Seleccionamos el primero
        foreach (var curso in profesor.Cursos)
          foreach (var alumno in curso.Alumnos)
            Console.WriteLine($"El alumno {alumno.Nombre} recibe el curso de {curso.Nombre},impartido por {profesor.Nombre}");
    }

    Nos devolverá:

    El alumno Juan recibe el curso de Matematicas,impartido por Pedro
    El alumno Jorge recibe el curso de Matematicas,impartido por Pedro
    El alumno Sandra recibe el curso de Lenguaje,impartido por Pedro
    El alumno Andrea recibe el curso de Lenguaje,impartido por Pedro

    En caso de no tener Visual Studio, lanzaremos el proyecto desde el CLI de dotnet con :

    dotnet run –proyect PostCore

    Aviso a navegantes

    En caso de que no queramos almacenar las migraciones, se pueden borrar del proyecto eliminándolas como archivo, o simplemente con:

    PM -> remove-migration
    CLI -> dotnet ef migrations remove

    Pero cada vez que queramos crear una nueva migración y aplicarla, no existirá la migración previa, de manera que tendremos que hacer un drop a la base de datos mediante

    PM-> drop-database -Context PostDbContext
    CLI-> dotnet ef database dtop -c PostDbContext

    asumiendo con ello la consiguiente perdida de datos. En caso contrario, el update lanzará un error indicando que las tablas ya existen en la base de datos.

    En entornos de desarrollo, no es necesario revisar la migración ya que presumiblemente no nos importa la posible perdida de datos, pero si vamos a aplicar migraciones en entornos de producción, conviene que revisemos los ficheros generados en la migración, donde veremos que se definen 2 métodos:

    protected override void Up(MigrationBuilder migrationBuilder)
    protected override void Down(MigrationBuilder migrationBuilder)

    Estos dos métodos serán ejecutados durante las actualizaciones de la base de datos (“Up” al aplicar un migración y “Down” al quitarla) y conviene que estemos seguros de que si por ejemplo queremos cambiar como almacenamos los datos de un nombre, unificando dos columnas, hacemos que se genere una nueva columna, se migren los datos de las previas a la nueva, y entonces se borren la previas, de modo que no tengamos una perdida de datos. En cualquier caso, siempre que la migración tenga posibilidades de que se produzca una perdida de información, Entity Framework Core nos lo notificara con el mensaje:

    Entity Framework Core

    En este enlace, dejo un ejemplo de la documentación oficial detallando más sobre ese tema.

    **La entrada Haciendo fácil el acceso a datos con Entity Framework Core (Parte 2) se publicó primero en Fixed Buffer.**

    » Leer más, comentarios, etc...

    Variable not found

    Enlaces interesantes 331

    septiembre 25, 2018 06:14

    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.

    » Leer más, comentarios, etc...

    Meta-Info

    ¿Que es?

    Planeta Código es un agregador de weblogs sobre programación y desarrollo en castellano. Si eres lector te permite seguirlos de modo cómodo en esta misma página o mediante el fichero de subscripción.

    rss subscripción

    Sponsors

    Puedes utilizar las siguientes imagenes para enlazar PlanetaCodigo:
    planetacodigo

    planetacodigo

    Si tienes un weblog de programación y quieres ser añadido aquí, envíame un email solicitándolo.

    Idea: Juanjo Navarro

    Diseño: Albin