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

Blog Bitix: Las colecciones de Java, estructuras de datos para guardar referencias a objetos

$
0
0
Java

Los programas en su funcionamiento manejan información y esta se guarda en algún tipo de estructura adecuada según el tipo de uso de esa información, ya sea para lectura al recuperar datos y escritura par insertar nuevos datos. En Java hay dos interfaces que el resto de colecciones implementa, una interfaz es Collection y la otra es Map, estas en su contrato define una serie de métodos que las implementaciones deben proporcionar.

Collection tiene métodos para saber si un determinado elementos está en la colección con contains y containsAll basándose en el método equals, iterar los elementos de la colección con iterator, desde Java 8 convertir la colección en un Stream, añadir elementos con add y addAll, eliminar elementos con remove y removeAll, comprobar si la colección está vacía con isEmpty, vaciar la colección con clear, obtener el número de elementos con size y algunos pocos métodos más.

La interfaz Map es para estructuras de datos que asocian a cada valor una clave por la que se recuperan los elementos tiene métodos para saber si existe una clave con containsKey o un valor con containsValue, obtener un valor por su clave con get, eliminar un valor según su clave con remove obtener el conjunto de clave con keySet o los valores con values, obtener el número de elementos de la colección con size, comprobar si está vacía con isEmpty también entre algunos otros más. La interfaz Map se basa en el método hashCode, por eso es importante implementar correctamente los métodos equals y hashCode correctamente en los objetos, de no hacerlo al usar el framework de colecciones se producirán comportamientos no deseados.

La interfaz List la implementan estructuras de datos en ls que los elementos están ordenados según el orden de inserción, como están ordenados se puede acceder por ellos mediante un índice, para ello añade dos métodos con get y remove con un índice por parámetro.

Las colecciones que implementan la interfaz Set no mantienen un orden y no permite valores duplicados basando la igualdad según el método equals de Object.

Queue también mantiene un orden en los elementos pero los elementos siguen la regla FIFO donde los elementos se añaden al final de la cola con add y los elementos se extraen de el inicio de la cola con element, peek, poll y remove.

Stack es una pila donde se sigue la regla LIFO, el método push añade un elemento en la parte de arriba de la pila y peek y pop obtiene el elemento son extraerlo y extraen elementos de la cima de la pila.

Las colecciones TreeSet y TreeMap mantienen los elementos ordenados según el orden natural definido por el método compareTo de la interfaz Comparable guarda la información en una estructura de árbol de forma que las búsquedas son más rápidas que un una lista.

Las implementaciones más utilizadas de estas estas interfaces son ArrayList, HashSet, HashMap, TreeSet, ArrayDeque y Stack.

Desde que en Java 8 se permiten implementaciones de métodos en las interfaces se proporcionan en algunas de estas varios métodos factoría para crear fácilmente colecciones generalmente con un método de nombre of como en la interfaz List. La clase Collections tiene métodos para hacer las colecciones inmutables y sincronizadas impidiendo que se les realicen modificaciones o sincronizadas si varios Thread de forma simultánea.

La librería Vavr proporciona otra API y conjunto de colecciones sin algunos errores de diseño pero que se han de mantener por compatibilidad o con algunas funcionalidades adicionales que la API de colecciones de Java no tiene.


Variable not found: Enlaces interesantes 351

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

Por si te lo perdiste...

.NET / .NET Core

ASP.NET / ASP.NET Core

Azure / Cloud

Conceptos / Patrones / Buenas prácticas

Data

Machine learning / IA

Web / HTML / CSS / Javascript

Visual Studio / Complementos / Herramientas

Otros

Publicado en Variable not found.

Variable not found: Evaluación en cliente de EF Core: sus peligros y cómo evitarla

$
0
0
Entity Framework CoreSin duda, Entity Framework Core es un gran marco de trabajo para implementar el acceso a datos de nuestras aplicaciones, pues es rápido, potente y nos ahorra una gran cantidad de esfuerzo, sobre todo en proyectos muy centrados en datos.

Sin embargo, estas ayudas tienen un coste importante, al igual que ocurre con casi cualquier framework al que vayamos a confiar parte de nuestro sistema, sea del ámbito que sea: hay que conocerlo bien para no dispararse en un pie en cuanto apretemos el gatillo.

Hace muuuuchos, muchos años hablamos de cómo aplicar convenientemente la carga anticipada (eager loading) en Entity Framework podía acelerar de forma drástica el rendimiento en el acceso a datos de nuestras aplicaciones, evitando el temido problema denominado "SELECT N+1". Esto continúa siendo válido para la versión Core de este marco de trabajo: sigue existiendo el extensor Include() e incluso variantes de éste como ThenInclude() que permiten incluir en una única consulta las entidades que sabemos que vamos a necesitar.

Pues bien, en EF Core hay otro detalle que, si bien utilizándolo con conocimiento puede resultar muy interesante, es fácil que nos tumbe el rendimiento de nuestros accesos a datos si no lo usamos con cuidado: la evaluación en cliente.

La evaluación en cliente de Entity Framework Core

A la hora de construir queries a una base de datos usando LINQ o expresiones de consulta, lo habitual es que las expresiones que especificamos en ella sean trasladadas a SQL en el momento de ejecutarlas.

Por ejemplo, es esperable que la siguiente consulta en C#, que incluye tanto criterios de búsqueda como proyecciones, podría ser ejecutada en SQL Server como se incluye más abajo:
// "ctx" es un contexto EF
var johns = ctx.Friends
.Where(f => f.Name.StartsWith("John"))
.Select(f => f.Name).ToList();
SELECT [f].[Name]
FROM [Friends] AS [f]
WHERE [f].[Name] LIKE 'John%' AND (LEFT([f].[Name], LEN('John')) = 'John')
Esto es lo que llamamos evaluación en servidor. El proveedor de EF Core que estemos usando traducirá los árboles de expresión especificados en la consulta al lenguaje utilizado por el motor de datos (SQL Server, SQLite, Oracle...) y será dicho motor el que realmente evaluará las expresiones para filtrar datos o crear las proyecciones solicitadas.

Por tanto, de alguna forma estamos aceptando implícitamente que cualquier tipo de expresión podría ser traducida al lenguaje de consulta del motor de datos, lo cual no tiene por qué ser cierto.
Veamos la siguiente consulta:
// Consulta:
public List<Friend> GetAdults()
{
var adults = ctx.Friends.Where(f => IsAdult(f));
return adults.ToList();
}

private bool IsAdult(Friend f)
{
f.Birthdate < DateTime.Now.AddYears(-18);
}
En este caso, está claro que la expresión IsAdult() no podría ser traducida a SQL ni ningún motor de datos porque se trata de código ejecutable que reside en la aplicación.

En Entity Framework "clásico", una consulta como la anterior daría lugar a un error en tiempo de ejecución indicándonos que el proveedor de EF no sabe traducir dicha expresión al lenguaje usado por el almacén.

Y aquí es donde aparece la evaluación en cliente de Entity Framework Core. Si observamos la sentencia SQL enviada al proveedor al ejecutar la consulta, veríamos algo como lo siguiente:
SELECT [f].[Id], [f].[Birthdate], [f].[Name]
FROM [Friends] AS [f]
Efectivamente, ¡le estamos solicitando todos las filas de la tabla Friends! Por cada fila obtenida, se creará un objeto Friend y se evaluará el predicado condición IsAdult(), descartándose si no cumple la condición. Pero eso sí, la materialización ya se habrá realizado y habremos utilizado memoria y tiempo en crear un objeto que al final no va a ser utilizado.
Es fácil imaginar la repercusión que una consulta de este tipo podría tener en una tabla con millones de filas, cuando en realidad lo único que estamos haciendo es filtrar por fecha de nacimiento.
Bien es cierto que en la consulta anterior se veía muy claramente que la expresión no puede ser traducida a SQL, pero, ¿qué me decís de la siguiente?
var adults = ctx.Friends.Where(f => f.Name.IndexOf('J')==0);
Aunque IndexOf() es un método muy habitual para trabajar con cadenas en .NET, tampoco el proveedor de SQL Server lo soporta, por lo que, de nuevo, la sentencia SQL enviada al motor obtendrá todas las filas de la base de datos e IndexOf() será evaluado en cliente.

Y peor incluso es el hecho de que esto podría variar de un proveedor a otro. Por ejemplo, podría ser que el método IndexOf() estuviera implementado por el proveedor de SQLite pero no por el de SQL Server o viceversa, lo que haría que su uso pudiera producir resultados indeseados dependiendo del motor utilizado al ejecutar la aplicación.
A veces no es fácil prever si una construcción será evaluada en cliente o en servidor.
¿Qué podemos hacer?

Primero: detectar dónde están los problemas

Cuando se produce la evaluación en cliente, Entity Framework Core registrará un warning en el log. El problema es que por defecto no tendremos forma de verlo, salvo que configuremos apropiadamente el logging.

En Entity Framework Core 2.1, esto podríamos conseguirlo fácilmente insertando con un código como el siguiente dentro del contexto de datos:
public class FriendsContext : DbContext
{
private static readonly ILoggerFactory MyLoggerFactory = GetLoggerFactory();

private static ILoggerFactory GetLoggerFactory()
{
return new LoggerFactory(new[]
{
new ConsoleLoggerProvider(
(category, level) =>
category == DbLoggerCategory.Query.Name &&
level == LogLevel.Warning
, true)
});
}

protected override void OnConfiguring(DbContextOptionsBuilder builder)
{
builder.UseLoggerFactory(MyLoggerFactory);
builder.UseSqlServer(@"...");
}
...
}
A partir de EF Core 2.2 esta fórmula ha cambiado y ya no está recomendada, porque esa forma de construir ConsoleLoggerProvider se ha marcado como obsoleta. Esto podemos solucionarlo simplemente modificando el método GetLoggerFactory() visto anteriormente:
// Recommended implementation for EF Core 2.2:
private static ILoggerFactory GetLoggerFactory()
{
IServiceCollection serviceCollection = new ServiceCollection();
serviceCollection.AddLogging(builder =>
builder.AddConsole()
.AddFilter((category, level)=>
category == DbLoggerCategory.Query.Name && level == LogLevel.Warning
)
);
return serviceCollection.BuildServiceProvider()
.GetService<ILoggerFactory>();
}
En ambos, casos, al ejecutar la consulta que incluye evaluación en cliente podremos observar la siguiente salida por consola, por ejemplo:
Query:
======
var adults = ctx.Friends.Where(f => f.Name.IndexOf('J')==0);

Salida por consola:
===================
warn: Microsoft.EntityFrameworkCore.Query[20500]
=> Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor
The LINQ expression 'where ([f].Name.IndexOf(J) == 0)' could not be translated
and will e evaluated locally.

Segundo: desactivar la evaluación en cliente

Si el punto anterior no nos convence, o no lo vemos muy práctico porque no vamos a mirar muy a menudo los logs, podemos recurrir a soluciones más violentas ;-)

Tenemos una forma sencilla de hacer que la aplicación explote en tiempo de ejecución cuando este caso ocurra, indicando en el método OnConfiguring() del contexto de datos que cuando se produzca un warning queremos lanzarlo como excepción cuando se trate de una evaluación en cliente:
protected override void OnConfiguring(DbContextOptionsBuilder builder)
{
builder.ConfigureWarnings(
warning => warning.Throw(RelationalEventId.QueryClientEvaluationWarning));
...
}
Hecho esto, cualquier intento de evaluación en cliente de una expresión lanzará una excepciónInvalidOperationException, y será más fácil que nos demos cuenta de que tenemos que revisar la consulta:
Unhandled Exception: System.InvalidOperationException: 
Error generated for warning 'Microsoft.EntityFrameworkCore.Query.QueryClientEvaluationWarning:
The LINQ expression 'where ([f].Name.IndexOf(J) == 0)' could not be translated and will be
evaluated locally.'. This exception can be suppressed or logged by passing event
ID 'RelationalEventId.QueryClientEvaluationWarning' to the 'ConfigureWarnings'
method in 'DbContext.OnConfiguring' or 'AddDbContext'.

Excepción InvalidOperationException al evaluar el cliente

Tercero: modificar las queries para eliminar la evaluación en cliente

Una vez somos conscientes de que estamos ante una consulta que provoca evaluación en cliente, llega el momento de solucionar el problema.

A veces la cosa puede ser tan sencilla como reformular la consulta para que las funciones utilizadas sean traducibles en el servidor de datos. Por ejemplo, ya hemos visto que IndexOf() no puede utilizarse en SQL Server, sin embargo podríamos conseguir lo mismo usando StartsWith(), que sí está soportado:
// Original query (with client evaluation):
var adults = ctx.Friends.Where(f => f.Name.IndexOf('J')==0);

// Modified query (without client evaluation):
var adults = ctx.Friends.Where(f => f.Name.StartsWith("J"));
Otra posibilidad es intentar utilizar las funciones disponibles en EF.Functions. Se trata de extensiones que representan funciones disponibles en el motor de datos y que pueden ser introducidas con toda tranquilidad en las queries LINQ porque serán traducidas a SQL correctamente.

Por ejemplo, la siguiente consulta utiliza LIKE para buscar personas cuyo nombre cumpla un determinado patrón de texto:
var people = ctx.Friends.Where(f => EF.Functions.Like(f.Name, "%P_r%"));
// --> Peter Parker, Alan Parson, Perla Romero...
Si ninguna de las soluciones anteriores son posibles, probablemente tendríamos que optar por utilizar vistas o procedimientos almacenados en el servidor, pero eso ya es otra historia... ;)

Espero que os sea de utilidad :)

Blog Bitix: Colecciones sincronizadas e inmutables en Java

$
0
0
Java

En la API de Java hay un conjunto amplio de estructuras de datos de diferentes tipos para guardar información de forma eficiente según sea la necesidad de la aplicación. Desde listas de elementos ordenados, conjuntos de elementos no repetidos, estructuras clave-valor, árboles, pilas, colas, … Este conjunto de estructuras se encuentran agrupadas en la API de colecciones. Además de las estructuras de datos se les puede añadir funcionalidades en algunos casos necesarias para hacerlas inmutables de modo que no puedan ser modificadas, y para hacerlas sincronizadas en los casos que varios threads hagan operaciones de consulta y alguno operaciones de escritura de modo que las estructuras no se corrompan, una colección no sincronizada se puede convertir en una sincronizada o también existen colecciones sincronizadas diseñadas específicamente para ser eficientes en las aplicaciones concurrentes.

La interfaz Collection es implementada por varias interfaces y clases ArrayList, HashSet, List, Queue, Set, SortedSet, Stack, TreeSet y algunas otras, por otro lado está la interfaz Map para estructuras clave-valor. Las colecciones que mantienen un orden en sus elementos heredan de la interfaz List que posee métodos con operaciones basadas en un índice como obtener, insertar o eliminar un elemento en una determinada posición. Los Set no permiten elementos que sean iguales según determine el método equals del objeto y los presentes en la colección. Los Map asocian una clave a cada objeto que se utiliza para realizar operaciones en la colección.

Muchos de los métodos de las colecciones funcionan en términos de los métodos equals y hashCode de modo que si en una determinada clase se sobreescriben se ha de hacer implementando el contrato de estos métodos correctamente de otra manera una aplicación puede presentar errores de difícil depuración.

La clase Collections contiene numerosos métodos estáticos entre ellos para hacer una colección que no lo sea en inmutable o sincronizada. Con los métodos synchronizedCollection, synchronizedList, synchronizedMap y synchronizedSet para hacerlas sincronizadas y los métodos unmodifiableCollection, unmodifiableList, unmodifiableMap y unmodifiableSet. Estos métodos estáticos de la clase Collections reciben como parámetro una colección no sincronizada o inmutable y devuelven una colección sincronizada o inmutable.

Las colecciones específicas para la concurrencia son más eficientes que convertir una colección no sincronizada en sincronizada con los métodos de Collections. Las colecciones que se convierten en sincronizadas tienen una contención en toda la colección cuando no es necesario para las operaciones de lectura. Si las operaciones de lectura son mayoría las colecciones específicas para la concurrencia son más eficientes, no tienen tanta contención, por ejemplo, ConcurrentHashMap divide el mapa en varios segmentos y solo bloquea los segmentos relevantes lo que permite a múltiples threads acceder a otros segmentos del mismo mapa sin contención. CopyOnWriteArrayList permite varios lectores sin necesidad de sincronización y cuando ocurre una escritura copia el ArrayList a uno nuevo.

Bitácora de Javier Gutiérrez Chamorro (Guti): GEM y Locomotive BASIC

$
0
0

Aunque últimamente he hablado a menudo de GEOS y Ensemble, mi primer entorno gráfico para PC fue GEM (Graphics Environment Manager). Lo vi en un Amstrad PC-1512 de la oficina de mi padre, no solamente los entornos gráficos eran algo super-avanzado en aquella época, sino que además venía con Locomotive BASIC 2, un BASIC interpretado […]

La entrada GEM y Locomotive BASIC aparece primero en Bitácora de Javier Gutiérrez Chamorro (Guti).

Koalite: ¿Qué significa new this() en Javascript?

$
0
0

Que Javascript es un lenguaje con un diseño sumamente confuso un tanto peculiar es algo que a estas alturas ya no se le escapa a nadie. Todos conocemos los típicos ejemplos de comportamientos impredecibles cuando se empiezan a mezclar las reglas de coerción de tipos con operadores como +, == o ===.

Aun así, si algo tengo que reconocerle a Javascript es que siempre puedes encontrar algo nuevo que te sorprenda. Lo último ha sido ver código parecido a éste:

const x = new this();

Si viendo ese código ya tienes clarísimo lo que hace, te puedes ahorrar el resto del post. Por el contrario, si a simple vista te resulta tan extraño como a mi, vamos a intentar descifrarlo poco a poco.

this en Javascript

Éste debe de ser el único blog que queda en internet sin hablar de esto, y tampoco quiero profundizar mucho ahora, pero para entender lo que significa new this() primero es necesario recordar cómo funciona this en Javascript.

En lenguajes como C# o Java, this hace referencia a la instancia actual de la clase sobre la que se está ejecutando un método. El valor de this queda fijado por la clase en que está definido el método y siempre será una instancia de esa clase (o de una clase derivada de ella).

En el caso de Javascript, this hace referencia al objeto sobre el que se ejecuta una función, pero al no haber un concepto de clase comparable al de C#/Java (y no, la sintaxis class no significa lo mismo), la cosa cambia bastante porque podemos hacer que una función esté enlazada a diferentes objetos:

function sayHello() {
  console.log('Hi, ' + this.name);
}

const m = { name: 'Marcos', sayHello }
m.sayHello() // Hi, Marcos

const j = { name: 'Juan', sayHi: sayHello }
j.sayHi(), // Hi, Juan

Podemos crear una función, asignarla a distintos objetos, y el valor de this al ejecutar la función dependerá del objeto que la contenga en cada momento. Esto no es del todo cierto y se puede controlar mejor con las funciones bind, call, apply, o usando funciones arrow, pero ahora eso nos importa relativamente poco.

La idea con la que te tienes que quedar es que this no tiene nada que ver con clases, sino que referencia el objeto sobre el que se ejecuta una función, que puede coincidir o no con el objeto en el que se definió.

Funciones y objetos en Javascript

En Javascript podemos crear objetos mediante la sintaxis para objetos literales, como veíamos en el ejemplo anterior, o usando funciones constructoras. Y poco más. La sintaxis “nueva” para definir clases es, en realidad, azucar sintáctico sobre las funciones constructoras, pero se puede traducir a ellas. De hecho, cualquier función en Javascript se puede usar como función constructora si la invocamos con new (aunque a veces eso tenga poco sentido):

function sum(a, b) {
  return a + b;
}

const x = new sum(1, 2);
x instanceof sum // true

Además, las funciones en Javascript también son objetos, por lo que pueden tener sus propiedades adicionales y a las que les podemos enlazar otras funciones:

function sum(a, b) {
  return (a + b) * sum.factor;
}
sum.factor = 2;
sum.incFactor = function() { sum.factor ++; }

sum.incFactor();
sum(1, 2) === 9; // true (1 + 2) * 3

Atando cabos

Pensando en lo que acabamos de ver (y que en el fondo ya sabíamos) sobre this y las funciones como objetos en Javascript, es fácil razonar lo que hace ese extraño new this() que veíamos al principio del post.

Imagina este código:

function Person() {
}

Person.create = function() {
  return new this();
}

const p = Person.create();
p instanceof Person; // true

Si entendemos la función como un objeto y le asociamos una propiedad que es otra función, en esa otra función this se referirá a la propia función y, como hemos visto, cualquier función podemos usarla como una función constructora.

Podemos hacer una traducción aproximada del código anterior a sintaxis de clases y tendríamos el mismo resultado:

class Person {
  static create() {
    return new this();
  }
}

const p = Person.create();
p instanceof Person; // true

Esto funciona incluso con relaciones de herencia, permitiendo tener métodos estáticos cuyo comportamiento cambia dependiendo del punto de la jerarquía desde el que se invoquen:

class Employee extends Person {
}

const e = Employee.create();
e instanceof Employee; // true
e instanceof Person; // true

Dependiendo de si invocamos el “método estático” desde el objeto que representa a la clase base o a la clase derivada, el valor de this cambiará y crearemos un tipo de objeto u otro.

Y todo esto, ¿para qué sirve?

Pues la verdad es que no tengo ni idea, más allá de que resulte curioso para pasar el rato. Quizá en algún escenario en el que tuvieras que simular factorías para una jerarquía de “clases” pueda tener algún uso, pero estoy casi seguro de que siempre vas a poder encontrar un diseño más sencillo de seguir.

Conclusión

Javascript es un lenguaje que tiene muchas pegas, pero la flexibilidad que ofrece hace que en ocasiones puedes encontrar planteamientos interesantes desde el punto de vista de metaprogramación. Al manejar muy pocos tipos de primitivas y tener una frontera muy difusa entre ellas (como el caso de las funciones que también son objetos) puedes hacer muchas guarrerías cosas que son complicadas en otros lenguajes de programación.

A veces incluso pueden resultar útiles, como el caso de crear nuevas clases dinámicamente desde funciones, como vimos al hablar de los componentes de orden superior en ReactJS.

Lo importante, con Javascript o con cualquier lenguaje, es intentar entender cómo funcionan las cosas que utilizamos y no quedarnos con la sensación de ser los más listos sólo porque sabemos tirar un par de pantallas con el framework de turno.

Posts relacionados:

  1. Usando C# para entender los constructores de Javascript
  2. Modificar una clase en Javascript: Eliminar los markers de Google Maps
  3. Javascript: Diferencias entre declaración de función y expresión con función

Variable not found: Enlaces interesantes 352

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

Por si te lo perdiste...

.NET / .NET Core

ASP.NET / ASP.NET Core

Azure / Cloud

Conceptos / Patrones / Buenas prácticas

Data

Machine learning / IA / Bots

Web / HTML / CSS / Javascript

Visual Studio / Complementos / Herramientas

Xamarin

Otros

Publicado en Variable not found.

Bitácora de Javier Gutiérrez Chamorro (Guti): Cuerpo Rompe Bolas (C.R.B.)

$
0
0

Creo que Risky Woods fue el último juego de PC que homenajeé aquí, y de eso hace casi una década. Hoy vamos a hablar de Cuerpo Rompe Bolas o C.R.B. para abreviar. Estamos a principio de 1990, los PC han avanzado y la mayoría de títulos comerciales con capaces de representar 256 colores en pantalla […]

La entrada Cuerpo Rompe Bolas (C.R.B.) aparece primero en Bitácora de Javier Gutiérrez Chamorro (Guti).


Variable not found: Cómo crear un paquete Nuget y publicarlo en Nuget.org

$
0
0

Blogger invitado

Blogger invitado

Jorge Turrado

Apasionado de la programación, siempre buscando la manera de mejorar el día a día con el desarrollo de tecnologías .NET. Apasionado de este momento tan cambiante y fabuloso para ser desarrollador C#.
Blog: Fixed Buffer
Tras la última colaboración me quedé con ganas de más y, después de que José me haya vuelto a invitar, vengo a hablaros de los paquetes Nuget.

Como desarrollador del ecosistema .NET, seguro que alguna vez has usado el gestor de paquetes NuGet (y si aún no lo has hecho, lo acabarás haciendo antes o después, créeme). Esta herramienta permite empaquetar componentes que cumplen una necesidad determinada, ya sea de terceros o internos de nuestra empresa, dejándolos listos para obtenerlos e incluirlos rápidamente en nuestros proyectos sin tener que compilarlos cada vez o almacenarlos en forma de binarios en una enorme carpeta con cientos de librerías.

Su máximo referente es el repositorio público Nuget.org, integrado dentro de Visual Studio y repositorio de facto de .NET Core, aunque también existen repositorios NuGet privados, o incluso puedes crear el tuyo sin ningún problema bajándote el paquete Nuget.Server desde el propio Nuget.org e implementándolo, ¿es poético verdad? 😊).

NuGetAhora que hemos introducido qué es NuGet para quien no lo supiese, tal vez te hayas preguntado cómo es posible crear un paquete NuGet y publicarlo para que otros desarrolladores puedan utilizarlo. Vamos a ver que es algo realmente sencillo.

Obtener nuestra API key

Lo primero que necesitamos es obtener nuestra API KEY en Nuget.org, y para ello antes de nada debemos acceder al servicio.

Login en Nuget.org

Hay que tener en cuenta que es necesario utilizar una cuenta Microsoft para poder loguearnos, pero basta que sea una cuenta de Hotmail u Outlook.

Una vez que nos hemos logueado, pulsamos sobre nuestro nombre para abrir el menú, y vamos a la opción "API Keys":

Menú API keys en Nuget.org

Y tras ello, ampliamos la sección "Create":

Sección "Create" en Nuget.org

En el formulario que nos aparece es donde vamos a dar los datos para crear la clave:

Formulario de creación de API key

Los datos que nos va a pedir son:
  • Nombre de la clave: Aquí vamos a ponerle un nombre que nos permita identificar la clave para gestionarla después.
     
  • Duración: Este es el tiempo de vida de la clave. Una vez pasado ese tiempo, tendremos que renovarla.
     
  • Permisos: Aquí le indicamos si queremos que sólo pueda hacer actualizaciones de paquetes, o crear nuevos paquetes también.
     
  • Patrón de permisos de acceso: Con esto vamos a indicar a qué paquetes queremos que se pueda acceder con esta clave. En caso de que tengamos algún paquete ya creado, también podremos seleccionarlo.
Para nuestro caso, vamos a crearlo con permisos de actualización y poder crear nuevos paquetes, y en el patrón de acceso le vamos a poner un “*” para poder acceder a todos, ya que va a ser nuestra clave de trabajo como desarrollador. Si lo que estuviésemos haciendo es una clave para un servicio de CI/CD, lo conveniente sería ajustar los permisos para no permitir control total sobre la cuenta. Después, basta con pulsar sobre el botón “Create”.

Una vez se pulsemos para crear la clave, nos la mostrará en el apartado “Manage”, dándonos la posibilidad de copiarla. Sólo nos va a dejar copiarla esta vez, por lo que es importante que nos la guardemos en un sitio a salvo, ya que, si la volvemos a necesitar y no la hemos copiado, tendremos que regenerarla.

Obtener la API key

Con esto ya tenemos lo necesario para poder publicar un paquete en Nuget.org, así que sólo nos queda crear el paquete, para lo que vamos a crear un proyecto de librería en Visual Studio. La recomendación es crearla con .NET Standard en su versión más baja posible, ya que con eso conseguimos que funcione multiplataforma y con la mínima versión del framework posible, siempre que esa versión incluya todas las APIs que necesitamos.

Tabla de compatibilidad de .NET Standard

Para nuestro ejemplo, vamos a crear una librería .NET Standard 1.0, ya que no vamos a necesitar ninguna API, aunque lo normal es que necesitemos una versión más alta. Para seleccionar la versión de .NET Standard, debemos ir a las propiedades del proyecto de nuestra librería, y seleccionarla en el desplegable.

Selección de versión de .NET Standard

Configurando nuestro proyecto para generar un paquete

Dentro de las opciones, también vamos a ir a la pestaña “Paquete”, donde le vamos a indicar los datos del paquete.

Propiedades del paquete

Aquí conviene rellenarlo todo, así como darle etiquetas que faciliten buscar el paquete para quien busque algo que resuelva su problema, pero como mínimo debe tener un “Id. de paquete” único y una versión, ya que es el nombre con el que aparecerá en el repositorio. Una buena idea es buscar en Nuget.org si ya existe un paquete con el nombre que queremos darle, porque si ya existe no podremos subir el nuestro.

Pese a que esos sean los datos mínimos, es recomendable añadir información adicional sobre el paquete, como el nombre del autor, información de copyright, una descripción ampliada o las direcciones URL del proyecto, entre muchos otros. La siguiente captura de pantalla muestra el formulario prácticamente relleno en su totalidad para nuestro proyecto de ejemplo:

Propiedades del paquete totalmente cumplimentadas

Una vez tenemos esto listo, basta con que sigamos trabajando en nuestro código de manera normal como lo haríamos en cualquier otro proyecto.

Publicando nuestro paquete en Nuget.org desde línea de comandos

Cuando queremos publicar nuestro paquete, lo primero que vamos a hacer es generarlo, para lo que seleccionaremos la opción “Paquete {nombre de nuestro paquete}” desde el menú “Compilar” de Visual Studio.

Opciones de Visual Studio para generar el paquete

Esto nos va a dejar en la carpeta de salida un archivo “.nupkg” que contiene la librería y todos sus metadatos. Este es el fichero que tendremos que mandar a Nuget.org para que el paquete esté disponible.

Archivo .nupkg en la carpeta de salida
Para poder publicar en Nuget.org, necesitamos tener un cliente Nuget en el equipo, esto se puede conseguir de varias maneras, pero la que nos garantiza poder publicar sin problema, es instalar el cliente completocomo se indica en la documentación. Una vez que lo tengamos, basta con un sencillo comando:
nuget push Ruta al paquete\YourPackage.nupkg -ApiKey <tu_API_key> -Source https://api.nuget.org/v3/index.json
Donde los dos parámetros que le indicamos:
  • -ApiKey: Es nuestra clave de acceso al repositorio de paquetes.
  • -Source: Es la URL que nos da el repositorio de paquetes para para enviarle cambios.
En mi caso, como he abierto la PowerShell en la carpeta del paquete, queda algo así:
nuget push NugetColaboracionVNF.1.0.1.nupkg -ApiKey oy2p6bvabu65fjuafebah2oeajh3u5zunjtw6keynpo2uu -Source https://api.nuget.org/v3/index.json
Cuando lo ejecutamos, veremos información en consola indicando que el paquete ha sido enviado correctamente.

Resultado en consola de un envío correcto

Va a pasar un rato hasta que nuestro paquete esté disponible para descargarlo, ya que primero tiene que ser validado por el sistema y luego añadido al índice. Después de este tiempo (nos avisa por email cuando el proceso termina), podemos verlo y descargarlo sin ningún problema.

Paquete ya publicado en Nuget.org

Con esto hemos conseguido crear y publicar nuestro paquete en Nuget.org, de manera que sea posible consumirlo como un paquete más. De todos modos, es cierto que el proceso no es todo lo automatizado que podríamos esperar, y requiere que seamos nosotros quienes nos encargamos de actualizar la versión y subir el paquete cada vez que queramos. En caso de no actualizar la versión y volverlo a subir, nos dará un error diciéndonos que ese paquete ya existe, por ejemplo, si volvemos a lanzar el mismo comando de antes.

Error en consola indicando que el paquete ya existe

Publicando el paquete desde la interfaz web de Nuget.org

Otra opción es utilizar la interfaz web de nuget.org para subir el paquete (con las mismas limitaciones de versiones que hemos comentado y no es automatizable). Esto puede ser útil si no queremos meternos en la labor de automatizar el proceso (aunque como veremos, es muy sencillo).

Para utilizar la interfaz web, dentro del menú desplegable, vamos a “Upload Package”:

Menú para subir paquete a través de la interfaz web

Y dentro del formulario que nos aparece, pulsamos sobre el botón “Browse” para abrir el navegador de archivos y seleccionar el paquete. Una vez seleccionado, se subirá automáticamente, apareciendo tras ello una ventana de verificación con los datos del paquete:

Pantalla de verificación del paquete

Si estamos de acuerdo con todos los metadatos del paquete, simplemente hay que pulsar el botón “Submit” al final de la página.

Envío definitivo del paquete

En cualquier caso, si pensamos que vamos a necesitar actualizar versiones frecuentemente, o simplemente queremos desentendernos de tener que subir los paquetes manualmente, esto se puede solucionar fácilmente utilizando un sistema de despliegue continuo, que sea quien se encargue de identificar la versión y de enviársela al gestor de paquetes.

Si quieres saber cómo puedes hacerlo, facilitándote mucho la vida, como continuación de esta entrada y de mi serie sobre CI/CD, he publicado la entrada:
Además, si nuestro proyecto es abierto, es casi obligatorio habilitar SourceLink para nuestro paquete (si no sabes que es SourceLink, échale un ojo a mi entrada hablando sobre ello), de modo que el código fuente se pueda descargar bajo demanda para que quien utilice nuestro paquete pueda depurarlo. De esta forma podrá ver si el error es suyo, y tal vez si el error está en el paquete te proporcionen información relevante para solucionar el problema.

Esto es realmente fácil, basta con que editemos el archivo “.csproj” y añadamos las siguientes líneas al <PropertyGroup>:
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<RootNamespace>{NombrePaquete}</RootNamespace>
<AssemblyName>{NombrePaquete}</AssemblyName>
Y el siguiente ItemGroup:
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub"
Version="1.0.0-beta-63127-02" PrivateAssets="All" />
</ItemGroup>
Un ejemplo del ".csproj" completo:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.0</TargetFramework>
<PackageId>NugetColaboracionVNF</PackageId>
<Authors>VariableNotFound &amp;&amp; FixedBuffer</Authors>
<Company>Jorge Turrado Ferrero</Company>
<Product>NugetColaboracionVNF</Product>
<AssemblyName>NugetColaboraciónVNF</AssemblyName>
<RootNamespace>NugetColaboraciónVNF</RootNamespace>
<Description>Paquete de ejemplo para entrada sobre como publicar un paquete manualmente y con CI/CD</Description>
<Copyright>VariableNotFound &amp;&amp; FixedBuffer</Copyright>
<PackageProjectUrl>https://github.com/FixedBuffer/CreacionPaqueteNuget</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/FixedBuffer/CreacionPaqueteNuget/blob/master/LICENSE</PackageLicenseUrl>
<RepositoryUrl>https://github.com/FixedBuffer/CreacionPaqueteNuget</RepositoryUrl>
<PackageTags>ejemplo</PackageTags>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>
<Version>1.0.1</Version>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<RootNamespace>NugetColaboracionVNF</RootNamespace>
<AssemblyName>NugetColaboracionVNF</AssemblyName>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub"
Version="1.0.0-beta-63127-02" PrivateAssets="All" />
</ItemGroup>
</Project>
Con esto me despido, ha sido un placer poder volver a colaborar con Variable Not Found, y como dije la última vez, ¡si me dejan volveré pronto! 😊
José M. Aguilar> Ha sido un placer tener por aquí de nuevo, Jorge. Continuaremos atentos a tu blog, y, por supuesto, esperamos que te animes más veces a publicar en Variable Not Found.

Publicado en Variable not found.

Fixed Buffer: Herramientas de desarrollo: AppVeyor

$
0
0

Hoy vengo con otra entrada de esas que me hacen ilusión, y es que volvemos a colaborar con José de VariableNotFound, esta vez para hablar de cómo crear paquetes Nuget (con SourceLink, por supuesto), sobre el repositorio Nuget.org, y sobre como publicar nuestros paquetes automáticamente con un sistema de CI/CD como AppVeyor.

En la primera parte de la entrada, que se ha publicado en VariableNotFound hablábamos de cómo crear un paquete Nuget con SourceLink y publicarlo en Nuget.org (si no sabes lo que es, deberías echarle un vistazo a la entrada hablando del tema). Como comentábamos al final, hacerlo a mano se hace tedioso, por eso es una buena idea utilizar una herramienta de Despliegue Continuo (CD por sus siglas en ingles).

En su momento publique en el blog de compañero de trabajo unas entradas sobre AppVeyor en las que explicaba como añadir AppVeyor a nuestro repositorio. Hoy, vamos a continuar aquella entrada añadiendo el CD hacia Nuget.org (aunque repasemos la parte que es común).

En primer lugar, nos tendremos que crear una cuenta en AppVeyor, algo que es muy fácil si tenemos cuenta de GitHub. Simplemente vamos a “Sign in” y seleccionamos iniciar con GitHub (u otros servicios).

Añadiendo AppVeyor a nuestro repositorio

Login AppVeyor

Con nuestra cuenta creada, añadimos el proyecto con el botón “NEW PROJECT”

Señala el botón de crear proyecto en AppVeyor

Y después, seleccionamos el proyecto que queremos, y pulsamos sobre el botón “Add”

Con esto, nuestro proyecto se compilará automáticamente cada vez que hagamos un “push” al repositorio y ejecutará las pruebas unitarias, aunque obviamente fallará porque aún no hemos configurado que tiene que hacer.

Para configurarlo, vamos a la pestaña “settings”

En primer lugar, en el menú “General” vamos a tener que bajar hasta casi el final, y seleccionar “On” en la opción “.NET Core .csproj patching “, con esto, vamos a conseguir cambiar la versión del paquete a la que queramos. Recordemos, qué si intentamos resubir un paquete con la misma versión que uno que ya existe, fallará. Como lo que nos interesa es que la versión se actualice y no se repita, vamos a utilizar la variable de AppVeyor “version“, la cual depende de los campos “Next build number” y “Build version format“, siendo el primero el número de compilación (es autoincremental) y el segundo la versión “Major” que queremos que tenga nuestro paquete, una vez hecho, pulsamos sobre el botón “Save” para guardar los cambios.

La imagen muestra como activar el parcheo de versión del paquete Nuget en AppVeyor

Pasamos al menú “Environment”, en este solo vamos a necesitar seleccionar la imagen de Visual Studio 2017 y pulsar en el botón “Save”.

La imagen muestra como seleccionar Visual Studio 2017 en AppVeyor

Ahora vamos con el menú “Build”, aquí le vamos a indicar como tiene que hacer la compilación, además de ejecutar scripts para preparar los prerrequisitos que tengamos, por ejemplo, hacer un “nuget restore”. Esta es quizás la parte más compleja del trabajo.

Lo primero, seleccionamos la configuración “Release” escribiéndolo en el apartado “Configuraton” al inicio, y después hay que bajar casi hasta el final para seleccionar que queremos hacer un paquete (“Package NuGet projects”), que queremos incluir los símbolos para SourceLink (“Include NuGet symbol packages”), y por último y muy importante (si no, no compilará), añadir un comando previo a la compilación que ejecutará un “nuget restore”.

La imagen muestra la configuración del menú "Build" de AppVeyor

Con esto, tras pulsar en “Save”, si hacemos cambios sobre el repositorio, podemos ver que ejecuta toda la integración continua.

La imagen muestra la salida de la consola de AppVeyor

Configurando el despliegue en Nuget.org desde AppVeyor

Por último, vamos al menú “Deployment”, y añadimos un nuevo despliegue pulsando sobre “Add deployment” y seleccionando Nuget en la lista desplegable. Ahora, simplemente introducimos nuestra API Key, le decimos que no queremos publicar un paquete de símbolos, y por ultimo y MUY IMPORTANTE, como no queremos que se haga deploy de cada push, añadimos la condición de que para hacer un deploy, tiene que ser un push con un “tag”, esto lo conseguimos poniendo como condición que la variable de AppVeyor “APPVEYOR_REPO_TAG” sea true.

La imagen muestra la configuración de el despliegue en AppVeyor

Si con esto pulsamos sobre salvar, y mandamos un nuevo tag al repositorio, veremos cómo al igual que si lo enviábamos manualmente, aparece disponible en Nuget.org. Como siempre, dejo el código fuente en GitHub.

En próximas entradas, hablaremos sobre como utilizar Azure Pipelines como CD además de CI y las ventajas que tiene cerrar el ciclo CI/CD.

**La entrada Herramientas de desarrollo: AppVeyor se publicó primero en Fixed Buffer.**

Picando Código: Películas para ver en 2019

$
0
0

Ya estamos en Marzo y no había publicado nada en el blog en 2019. Una buena manera de empezar es la tradición de listar las películas que quiero ver este año, ¡aunque algunas ya se hayan estrenado! Más vale tarde que nunca… 😬

Al igual que años anteriores, 2019 promete ser un excelente año para películas de super héroes, ciencia ficción, animación y demás temas que tanto disfrutamos. En lo personal hay varias que vengo esperando con mucha anticipación desde hace mucho tiempo. Ordenadas más o menos por género, acá van las películas que quiero ver en 2019:

Shazam!

Shazam es el superhéroe antes conocido como Capitán Marvel (pueden leer más acá), y uno de mis personajes favoritos de los cómics. Primer tráiler de la lista porque junto con Captain Marvel, tengo muchísimas expectativas y estoy muy contento de poder verlos en el cine. El tono del tráiler parece coincidir con lo que quiero ver en una película de Shazam, así que espero no decepcione. En mi lista creo que ya está en el primer puesto de películas del universo DC y espero una de las mejores películas de super héroes. Pero midamos las exceptativas…

Estreno: 5 de abril.

Captain Marvel

Otra entrega del Universo Cinematográfico de Marvel (UCM), con Carol Danvers como protagonista. Tiene la particularidad de contar los hechos ocurridos en los 90’s, pero que tendrán repercusión en el presente como vimos en Infinity Wars. Además de ser la primera película del UCM con una mujer como protagonista (se supone que también vendría una película de Black Widow), introduce a los Skrulls -una raza de extraterrestres capaces de transformarse en otros seres vivos- que según tenía entendido eran propiedad de Fox. Con ellos y los Kree, está el potencial de ver adaptaciones de historias de los cómics como la Guerra Kree/Skrull o Secret Invasion, de la cual parecen haber sacado alguna idea por lo que muestran los tráilers. ¡Se estrena esta semana!

Estreno: 8 de marzo

Avengers: End Game

El UCM me ha dado mucho entretenimiento y alegría en sus más de 10 años, y los Avengers han sido una parte importante de eso. Esta película promete ser el cierre de este primer ciclo, y ni necesito ver más tráilers para saber qué pasa. Cada película fue más grande que la anterior e Infinity Wars fue gigante. Así que las expectativas están muy altas.

Estreno: 26 de abril

Spider-Man: Far From Home

Otro de mis superhéroes favoritos y cuya representación en el cine fue de horrible en las películas de Tobey Maguire, a bien en las películas con Andrew Garfield y excelentes y reivindicadas con Tom Holland. La alianza Sony/MCU logró el mejor Spider-Man cinematográfico live-action hasta ahora.

Estreno: 5 de julio

Glass

La última parte de la trilogía “Unbreakable” de M. Night Shyamalan. un thriller superheróico. Se estrenó en enero y aparentemente no tuvo muy buenas críticas. De todas formas tendría que mirar Unbreakable de nuevo y Split por primera vez antes de mirarla.

Ya estrenada

Brightburn

Una película de super héroes pero con toques de terror producida por James Gunn. Algo así como una versión alternativa de Superman, donde el personaje con super poderes es malo. No puedo evitar creer que está aunque sea un poco inspirado en Irredeemable, un excelente cómic por Mark Waid con la misma premisa.

Estreno: 24 de mayo

Dark Phoenix

Por alguna razón no logro conectar con los X-Men. Si bien he leído cómics que me han gustado, ninguna de las películas me han atrapado hasta ahora. Creo que voy a pasar de ver ésta en el cine, pero de todas formas merece estar en la lista.

Estrena: 7 de junio

New Mutants

Lo mismo que la anterior, más películas sobre los mutantes. Aunque ésta tiene un toque más de terror, lo que por lo menos asegura una fórmula distinta. Potencialmente puede ser muy buena. Al igual que Dark Phoenix, se iba a estrenar el año pasado pero se atrasó.

Estreno: 2 de Agosto

Hellboy

¿Necesitaba un reboot ya? No sé, nunca leí los cómics de Mignola. Sólo miré las dos películas anteriores, si recuerdo bien la segunda me gustó bastante. Por el tráiler parece prometedora, sin vergüenza de ser una película de acción y fantasía.

Estreno: 12 de abril

Star Wars Episode IX

The Force Awakens y The Last Jedi me encantaron, no puedo esperar a ver Episodio 9. La trilogía de trilogías que prometió George Lucas hace tantos años… Se cierra la historia Skywalker, además de ser la última película en la que compondrá John Williams. Vuelven Rey, Finn, Poe, BB-8, C-3PO y R2-D2. Seguro tengamos también a Luke en su forma “fantasma de la Fuerza” y la despedida de la Princesa Leia con las últimas escenas grabadas por Carrie Fisher 😢

Star Wars: Episode IX

Estreno: 20 de diciembre

Men In Black: International

Me gustó mucho la primera película de MiB. Tenía el VHS original y la debo haber mirado cientos de veces. No puedo decir lo mismo de la segunda, y si bien miré la tercera, no recuerdo mucho. Voy a intentar ver ésta en el cine, el concepto de comedia ciencia ficción puede ser muy efectivo para mí, y la tecnología en efectos especiales ha avanzado mucho desde la primera entrega. MiB 1 salió hace más de 20 años 👴

Estreno: 14 de junio

Iron Sky: The coming race

La secuela de Iron Sky, que cuenta con la participación de una de mis personas preferidas y con quien tuve el gusto de tomarme una cerveza una vez: Tom Green. En la primera película descubrimos que tras su derrota en 1945, los Nazis se estaban escondiendo en la Luna. Ahí construyeron una base y una flota espacial para volver a atacar la Tierra. Ahora, una colonia de humanos vive en la base en la Luna, con un gobierno fascista y religiones incluyendo una de las tantas que afectan nuestra actualidad: los “Jobistas”, un culto a Steve Jobs. Al volver a la Tierra se encuentran con dinosaurios y reptilianos liderados por Hitler. Todo dicho…

Estreno: Se estrenó en Finlandia en enero y se estrena en otros países en Marzo. Pueden ayudar a su distribución demandando que se estrene en su país en el siguiente enlace.

Terminator 6

Terminator 6

Sexta película de la saga Terminator. Aparentemente sería una secuela directa de Terminator y Terminator 2: Judgement Day, ignorando el resto de las películas como líneas de tiempo alternativas. También vuelve Arnold Schwarzenegger, Linda Hamilton y el John Connor original, pero todos pasados por CGI para hacerlos parecer jóvenes. Hollywood explotando al máximo la nostalgia y el miedo al cambio del público…

Alita: Battle Angel

Estuvo originalmente en la lista de películas para ver en 2018, pero se estrenó finalmente este año. Es una adaptación de un manga cyberpunk y se ve muy interesante. Las críticas han sido mezcladas, voy a tener que ir al cine a verla antes que salga de cartelera para formar mi propia opinión…

Estreno: Ya estrenada

Godzilla: King of the Monsters

Me gustó la primera película del nuevo “MonsterVerse” de Legendary. Aunque no tenía tanta acción o Godzilla como esperaba, siempre estoy a favor de películas con monstruos gigantes en la pantalla. Otra muy buena que recomiendo es Shin Godzilla, que me gustó más. En esta segunda entrega veremos muchos más monstruos, y con suerte sea todavía más entretenida que la primera. Y el año que viene cierra la trilogía con el encuentro de Godzilla Vs. Kong.

Estreno: 31 de mayo.

How to Train your Dragon: The Hidden World

Siguiendo con la temática monstruos y dragones, se estrenó en febrero la tercera entrega de “How to Train your Dragon”. Me encantan las primeras dos películas de esta saga. La animación es excelente, la historia y música son muy buenas y los dragones súper simpáticos. Todavía la están dando en el cine por acá, así que en una de esas esta semana me pego una vuelta.

Estreno: Ya estrenada

POKÉMON: Detective Pikachu

La premisa es tan ridícula que no sabía qué esperar de Detective Pikachu: Ryan Reynolds es la voz de Pikachu en una película live action con Pokemones realistas. Sus apariencias generaron reacciones encontradas entre el público, pero después de ver los trailers que han salido hasta ahora, compro. Se ve muy divertida y seguramente esté llena de guiños a los pokemaníacos.

Estreno: 10 de mayo

Mewtwo Strikes Back Evolution

Una remake CGi de la primera película de Pokémon. La animación se ve muy bien, tanto los Pokémon como los entrenadores. Lo hace a uno querer un juego de Pokémon así para Switch… Se estrena en Japón en julio, con suerte se estrene en más países.

Estreno: 12 de julio en Japón

Toy Story 4

Película de Pixar, tiene que estar en la lista. Y se trata de nada más y nada menos que la saga que empezó todo: Toy Story. La tercera parte me pareció un cierre correcto a la historia de los personajes, aunque debe ser la película que más me ha hecho llorar en un cine hasta ahora. De todas formas no tengo problema en volver a ver a Woody, Buzz, Jessie, Rex y los demás nombres clave de Debian en el cine. También me da una excusa para volver a ver las tres primeras 🤔

Estreno: 21 de junio

Frozen 2

La secuela de la excelente película animada de Disney que además de tremenda canción (Let it go! ¿No les queda la canción sonando en la cabeza?), dejó el mensaje que no todas las películas de princesas de Disney tienen que ser iguales. Elsa, Anna, Kristoff, Olaf y los renos viajan por ahí en una secuela que parece tener un toque más de aventura que la anterior. Ya me enteraré en el cine…

Estreno: 22 de noviembre

Lego Movie 2

Secuela de Lego Movie donde aparentemente “Everything is not awesome”. La original me entretuvo mucho así que la voy a mirar. Por cierto, si les gusta el humor en Lego Movie, les recomiendo la película de Ninjago, me resultó muy divertida también.

Estreno: Ya estrenada

Playmobil: The Movie

En mi infancia los Playmobil eran los juguetes “que no estaban tan buenos como los Lego”. Pero ahora que soy adulto, no mantengo esos conceptos infantiles. Excepto cuando peleo a un amigo fanático de Playmobil intentando hacerle entender lo superiores que son los Lego, algo que todos sabemos. Al igual que Lego, que no es competencia porque Lego es un juguete de armar cosas, que fomenta la creatividad y el desarrollo intelectual y Playmobil no, saltan a la pantalla grande con su propia película:

Estreno: 16 de agosto

Otras

Hay varias películas más que potencialmente podrían estar interesantes pero todavía falta ver más. La mascota de Sega, Sonic, tendrá su película pero todavía no está muy claro de qué va la cosa. En principio se publicó una imagen con la silueta de Sonic que no voy a compartir por acá para evitarle las pesadillas a quienes no la hayan visto. Y estos días se vió un supuesto “leak” de más imágenes. Me imagino que fue aprobada por un ejecutivo de Hollywood bajo los efectos de drogas fuertas. Es el tipo de película que -por ahora-, sólo me hace preguntarme “¿por qué?”.

He-Man volvería a tener una película de la mano de Sony. Pero entre que Mattel quiere empezar a hacer películas, licencias, y que hay poco y nada de información al respecto, no sé si veremos algo este año.

El reboot de Jumanji tendría una secuela, todavía no vi la primera, así que ni sé si merece estar en esta lista.

Los Locos Adams volverían en película animada, a estrenarse el 11 de octubre. Actualizaré este post ni bien aparezca algún trailer.

El villano más quemado del universo DC, el Joker (o Guasón), contará con su propia película este año protagonizada por Joaquin Phoenix, que me cae bien porque es vegano y hace campaña en defensa de los animales. Otra que ni bien haya tráiler la agrego a la lista, se estrena el 4 de octubre.

Picando Código: Basingstoke: Juego gratis de Puppy Games para Linux

$
0
0

Basingstoke

El estudio independiente de videojuegos Puppy Games es responsable de excelentes títulos como Droid Assault, Ultratron, Titan Attacks! y Revenge of the Titans. Su título más reciente es Basingstoke:

Basingstoke ha sido destruida y las ruinas se encuentran llenas de muertos reanimados y feroces monstruos extraterrestres. ¿Eres el único superviviente? ¡Explora la ciudad para descubrirlo! Escabúllete por las humeantes calles y edificios de Basingstoke, rebúscate sobre la marcha, y crea tu propio equipamiento para ayudarte en tu misión… Basingstoke es el único juego donde kebabs pueden ser usados como armas, y puedes saquear rollos de salchica de policías muertos. El juego es una mezcla entre sigilio furtivo y acción arcade, con un estilo distintivo que mezcla tiernos gráficos 3D con tensión espantosa.

Los desarrolladores han decidido publicar Basingstoke GRATIS en Linux:

Hemos decidido hacer GRATIS a Basingstoke para Linux, y en los próximos meses cuando tenga un poco de tiempo, voy a subir todos nuestros otros juegos a itch.io también, y van a ser GRATIS para usuarios de Linux también. Todas las donaciones se aceptan con agradecimiento por supuesto.

Y no se olviden de darle una mirada a nuestro Patreon. ¡Los juegos no se escriben solos! Estamos pasando la gorra, esperando juntar suficiente dinero para hacer Battledroid.

Pueden descargar Basingstoke en este enlace, eligiendo el precio que quieren pagar por él (incluyendo 0).

Bitácora de Javier Gutiérrez Chamorro (Guti): Cosas interesantes con Take Command

Picando Código: 6ta edición de Rails Girls en Argentina – 22 y 23 de marzo en Buenos Aires

$
0
0

El 22 y 23 de Marzo se realiza una nueva edición de Rails Girls Argentina en el coworking AreaTres en Buenos Aires. El evento consta de un taller gratuito de fin de semana donde aprenderás sobre aplicaciones Web y programación con Ruby on Rails. ¡No es necesario tener conocimientos previos en programación!

Rails Girls Argentina 2019

Más sobre Rails Girls:

Rails Girls propone herramientas para que chicas y mujeres construyan sus sueños e ideas con código.

Aprenderás sobre diseño, prototipado y programación con la ayuda de nuestros coaches.

Podés aplicar para participar en este formulario.

También te podés sumar como Rails Coach:

Como Rails Coach, acompañarás a un equipo de 4/5 principiantes en aprender cómo se construye una aplicación Web, harás mentoring, compartirás tu experiencia como Web developer y nos ayudarás a transmitir la pasión por programar! Las participantes son principalmente mujeres, porque queremos sumar más programadoras al mundo tecnológico! No importa si sos mujer u hombre para ser coach, ni tener conocimientos muy avanzados de Ruby on Rails, ya que el taller es de introducción.

Nos juntaremos una tarde (o mediante Hangouts) antes del evento para terminar de organizar la jornada.

Anotate acá.

Más información en el sitio de Rails Girls Argentina, también pueden seguir su cuenta de Twitter y ver cómo se pasó en eventos anteriores para motivarte a participar!

Picando Código: Se viene Rust Latam Montevideo 2019 – Conferencia latinoamericana de Rust

$
0
0

Los días 29 y 30 de marzo de 2019 en Montevideo, Uruguay, se realiza la primera conferencia latinoamericana del lenguaje de programación Rust: Rust Latam.

¿Qué es Rust?

Si tenés curiosidad por aprender sobre Rust, ¡éste es el lugar correcto!

Rust es un lenguaje de programación de sistemas que corre increíblemente rápido, previene segfaults, y garantiza seguridad en programación multihilos. La promesa es permitir construir software confiable y eficiente aprovechando potentes chequeos del compilador y un set de herramientas maduro que ayudará y asistirá durante todo el proceso.

Sobre la conferencia:

Rust Latam Montevideo

La Conferencia Rust Latam es el evento líder en América Latina por y para el movimiento Rust, y una de las oportunidades anuales más grandes de networking en la comunidad local de Rust. Esta conferencia de un fin de semana con sesiones interactivas, actividades prácticas, y charlas junta a más de 200 defensores, desarrolladores y entusiastas del lenguaje de programación Rust de todo el mundo. En marzo, la gente e ideas de la comunidad latinoamericana de Rust saltará de la pantalla para aprender, discutir, debatir y enfrentar Rust en persona. Nuestra primera conferencia Rust Latam anual empieza en Montevideo.

En marzo, tendremos ese mismo espíritu vehemente de las reuniones locales. También tendremos a la gente y recursos para hacer un gran impacto. Una conferncia de dos días – series de talleres y oradores – con decenas de expertos y principiantes significa que podemos avanzar el pensamiento en cómo tú y tu equipo pueden usar características de Rust para crear una amplia gama de nuevas aplicaicones de software, como motores de juegos, sistemas operativos, sistemas de archivos, componentes de navegadores web y motores de simulación para realidad virtual. Podemos forjar nuevas sociedades, podemos entrenar a los programadores del mañana y podemos alimentar a la construcción comunitaria a través de los países de América Latina.

Oradores

Docenas de expertos y principantes, lo que significa que podemos progresar mucho pensando en cómo tú y tu equipo pueden usar Rust.

Comunidad

Una meta compartida es conectar a la gente haciendo de Rust el mejor lenguaje de programación y la mejor comunidad.

Compromiso

Rust Latam Conf es sólo el comienzo. Para este primer año, esperamos dejar a Montevideo sintiéndose inspirado y comprometido.

Estimulando

Nos movemos hacia una comunidad más abierta e inclusiva para alimentar nuestra misión, el mejor Lenguaje de Programación Rust para todos.

La conferencia cuenta con un Código de Conducta, buscando ser un evento inclusivo, acogedor para todos y en contra de cualquier tipo de acoso u hostigamiento.

Charlas y Talleres

Va a haber dos keynotes, y charlas sobre Rust, Python, WebAssembly, Serverless, Macros y más. También un día entero de talleres incluyendo uno de Introducción a Rust:

El workshop introductorio está orientado a personas que desean conocer Rust y que tienen experiencia en otro lenguaje de programación. Este servirá de introducción a los conceptos fundamentales que hacen a Rust un lenguaje de progrmación diferente como; pertenencia, tiempos de vida y el sistema de tipos.

Al mismo tiempo los asistentes se podrán familiarizar con la sintaxis del lenguaje.

El workshop será una mezcla de conceptos teoricos y ejercicios cortos que apliquen a dichos conceptos.

Entradas y ubicación

La conferencia se realizará en el clásico Auditorio Torre de las Telecomunicaciones ANTEL, Calle Guatemala, 1075, Montevideo, Uruguay.

Hay dos tipos de entrada a la venta: Supporter por USD 100 (entrada con acceso total + aportar para que se haga la conferencia) y Regular USD 50 (entrada con acceso total a la conferencia). Las entradas se pueden comprar en este enlace.

La organización también está ofreciendo entradas gratis mediante un programa especial de becas. La idea es atraer nuevos entusiastas de Rust y darles la posibilidad que puedan descubrir más sobre este maravilloso lenguaje de programación:

Si eres un estudiante o profesor en latinoamérica, en áreas relacionadas con la ciencia y la ingeniería y te gustaría participar activamente en comunidades Open-Source y/o estás interesado en aprender sobre Rust, esta es una gran oportunidad para descubrir más acerca de este seguro, eficiente y rápido lenguaje de programación. Para ser seleccionado como beneficiario de este programa, hay que llenar este cuestionario antes del viernes 20 de marzo. El programa cubre el ingreso de manera gratuita al evento completo. Esto incluye workshops (29 de marzo) y la conferencia (30 de marzo, incluye almuerzo).

Más información

¡No se la pierdan! Ojalá pudiera ir…


Blog Bitix: Componentes en el cliente con Web Components usando JavaScript, HTML y CSS

$
0
0
JavaScript
HTML

En la rapidez con la que evolucionan las tecnologías una tendencia es el usar componentes en el lado del cliente y en los navegadores de una aplicación o página web. Los componentes son muy útiles ya que siguen los principios de encapsulación deseables una la programación que hace que un componente oculte los detalles del funcionamiento interno. Esta encapsulación hace que su funcionamiento interno sea más fácilmente entendible, por otro lado son reutilizables conociendo únicamente la interfaz que exponen y componer otros más complejos con otros más simples.

Han surgido varias librerías en JavaScript para desarrollar componentes en el lado del cliente, una de las primeras es Angular, otra React y otra es Vue pero el organismo W3C ha definido un estándar para desarrollar componentes, que los navegadores han de implementar. El estándar se llama Web Components está formado por varias especificaciones.

  • Custom Elements: permite definir nuevas etiquetas que el navegador es capaz de interpretar, hace el etiquetado de una página más sencillo.
  • Shadow DOM: el contenido HTML oculto de las etiquetas personalizadas.
  • HTML Templates: etiquetado HTML no visualizado por el navegador, utilizables para definir la estructura de los elementos sin tener que crearlo con código JavaScript.

Los Custom Elements se definen mediante código JavaScript con la función CustomElementRegistry.define() que recibe como parámetros el nombre de la etiqueta, la clase que la implementa y opcionalmente el elemento del que hereda. Hay dos tipos de Web Components los autónomos que heredan de HTMLElement y los personalizados que heredan de un elemento más concreto como un párrafo o botón, en cada caso de declaran de forma diferente en la función define y la etiqueta que la representa en el HTML en el ejemplo usando la etiqueta <hello-world> o <p is=“hello-world-customized”>.

Usando una definición de clase para el Custom Element se añade su funcionalidad, entre ella su etiquetado y estilos propios del componente, los elementos se añaden al Shadow DOM con la función appendChild() del objeto shadow obtenido con attachShadow(). El Custom Element puede tener atributos para recibir datos que se recuperan con la función getAttribute() y hasAttribute().

Con las funciones connectedCallback(), disconnectedCallback(), adoptedCallback(), attributeChangedCallback() y observedAttributes() del ciclo de vida un Web Component será notificado cuando se añada a una página, cuando se quite, cuando un atributo cambie su valor.

El Shadow DOM compone el etiquetado oculto del Web Compnent, las etiquetas HTML y los estilos CSS. El Shadow DOM es exclusivo del Web Component y está aislado del resto de modo que las clases CSS de estilos no entrarán en conflicto con las de otros Web Components aunque tengan los mismos nombres, esto hace menos necesarias las nomenclaturas que se utilizan precisamente para evitar los conflictos.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<!DOCTYPE html><html><head><scripttype="text/javascript">classHelloWorldextendsHTMLElement{staticgetobservedAttributes(){return["observed"];}constructor(){super();letstyle=document.createElement("style");style.textContent=".paragraph { font-size: 2em; font-weight: bold; }";letparagraph=document.createElement("p");paragraph.setAttribute("class","paragraph");paragraph.textContent="Hello World!";letshadow=this.attachShadow({mode:"open"});shadow.appendChild(style);shadow.appendChild(paragraph);}connectedCallback(){console.log("HelloWorld element added to page.");}attributeChangedCallback(name,oldValue,newValue){console.log("HelloWorld element attributes changed.");console.log({name:name,oldValue:oldValue,newValue:newValue});}}// ...
customElements.define("hello-world",HelloWorld);// ...
</script></head><body>
...
<hello-worldobserved="value"></hello-world>
...
</body></html>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!DOCTYPE html><html><head><scripttype="text/javascript">classHelloWorldCustomizedextendsHTMLParagraphElement{// ...
constructor(){super();letstyle=document.createElement("style");style.textContent=".paragraph { font-size: 2em; font-weight: bold; }";letspan=document.createElement("span");span.setAttribute("class","paragraph");span.textContent="Hello World! (Customized)";letshadow=this.attachShadow({mode:"open"});shadow.appendChild(style);shadow.appendChild(span);}// ...
}// ...
customElements.define("hello-world-customized",HelloWorldCustomized,{extends:"p"});// ...
</script></head><body>
...
<pis="hello-world-customized"></p>
...
</body></html>

Para hacer más sencilla la creación del etiquetado de los Web Components en vez de usando código JavaScript con las funciones createElement() y appendChild() está la especificación de HTML Templates. Plantillas en las que además se puede incluir los estilos CSS.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<!DOCTYPE html><html><head><scripttype="text/javascript">classHelloWorldTemplateextendsHTMLElement{// ...
constructor(){super();lettemplate=document.getElementById('hello-world-template');letshadow=this.attachShadow({mode:'open'})shadow.appendChild(template.content.cloneNode(true));}// ...
}// ...
customElements.define("hello-world-template",HelloWorldTemplate);// ...
</script></head><body>
...
<templateid="hello-world-template"><style>.paragraph{font-size:2em;font-weight:bold;}</style><pclass="paragraph">Hello World! (Template)</p></template>
...
<hello-world-template></hello-world-template>
...
</body></html>

Además con los slots se le puede proporcionar al Web Component un fragmento de HTML.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<!DOCTYPE html><html><head><scripttype="text/javascript">classHelloWorldSlotextendsHTMLElement{// ...
constructor(){super();lettemplate=document.getElementById('hello-world-slot');letshadow=this.attachShadow({mode:'open'})shadow.appendChild(template.content.cloneNode(true));}// ...
}// ...
customElements.define("hello-world-slot",HelloWorldSlot);// ...
</script></head><body>
...
<templateid="hello-world-slot"><style>.paragraph{font-size:2em;font-weight:bold;}</style><pclass="paragraph"><slotname="text">Hello World! (Slot)</slot></p></template>
...
<hello-world-slot></hello-world-slot><hello-world-slot><spanslot="text">Hello World! (Slot Custom)</span></hello-world-slot>
...
</body></html>
Etiquetado y eventos de varios Web Components

En la página de documentación los Web Components en MDN esta muy bien detallados. Los componentes de lado del cliente permiten desarrollar elementos funcionales reutilizables y compuestos entre ellos. Combinado con una interfaz REST o GraphQL en el lado del servidor es una forma de construir una aplicación o página web. JSF, Wicket, Apache Tapestry son frameworks web Java que proporciona componentes con ciertas similitudes pero en el lado del servidor.

La compatibilidad de los navegadores de los Web Components es amplia, no necesita de librerías JavaScript adicionales ya que el soporte está incluido en el navegador pero React y Vue están disponibles con anterioridad y proyectos como Redux y Vuex proporcionan el manejo del estado de los componentes.

El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub.

Variable not found: Enlaces interesantes 353

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

Por si te lo perdiste...

.NET / .NET Core

ASP.NET / ASP.NET Core

Azure / Cloud

Conceptos / Patrones / Buenas prácticas

Data

Machine learning / IA / Bots

Web / HTML / CSS / Javascript

Visual Studio / Complementos / Herramientas

Xamarin

Otros

Publicado en: www.variablenotfound.com.

Variable not found: Shadow properties en Entity Framework Core

$
0
0
Entity Framework CoreSeguimos hablando de características interesantes de Entity Framework Core, y en esta ocasión nos detendremos en las shadow properties, o propiedades ocultas.
A grandes rasgos, se trata de la capacidad de este framework para gestionar propiedades de una entidad que existen en el almacén datos pero no en la clase .NET que la representa en el mundo de los objetos.

De forma intuitiva podemos saber que esto ya existía en las versiones clásicas de Entity Framework. Por ejemplo, cuando introducíamos una propiedad de navegación entre dos entidades sin usar una clave foránea de forma explícita, el propio marco de trabajo creaba, por convención, una columna en la base de datos para almacenar dicha referencia, como en el siguiente escenario:
public class Friend
{
public int Id { get; set; }
public string Name { get; set; }
// Se crea una columna CountryId en la base de datos,
public Country Country { get; set; } // pero no existe en la entidad.

}
El valor de dicha columna CountryId no podía ser manipulada de forma directa porque se trataba de información usada internamente para gestionar las relaciones y su valor era obtenido y actualizado de forma transparente para nosotros.

Pues bien, Entity Framework Core aporta la capacidad para gestionar este tipo de campos "ocultos" para servir a nuestros propios intereses. De esta forma, podríamos añadir a una entidad propiedades que no tienen por qué estar visibles en la clase .NET en forma de propiedades; un ejemplo podría ser el clásico "IsDeleted" cuando implementamos borrado lógico, o información de auditoría como los tradicionales "UpdatedAt" o "UpdatedBy".

Definición de propiedades ocultas

La definición de shadow properties sólo puede realizarse utilizando el API fluido de configuración disponible a través del objeto ModelBuilder suministrado al método OnModelCreating() del contexto de datos.

Por ejemplo, el siguiente bloque de código añade a la entidad Friend las propiedades ocultas UpdatedAt y UpdatedBy, que podrían sernos de utilidad para almacenar información interna de auditoría:
// Entidad:
public class Friend
{
public int Id { get; set; }
public string Name { get; set; }
}

// Contexto de datos:
public class FriendsContext : DbContext
{
public DbSet<Friend> Friend { get; set; }

protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Friend>()
.Property<DateTime>("UpdatedAt");
builder.Entity<Friend>()
.Property<string>("UpdatedBy").HasMaxLength(80);
}
}
Y esto es todo, así de sencilla es la creación de shadow properties :)

Consultar o establecer el valor de una propiedad oculta de una entidad

Dado que estas propiedades no aparecen en las clases .NET que representan a las entidades de datos, no podemos acceder a sus valores utilizando expresiones como objeto.Propiedad desde nuestro código. Sus valores están gestionados directamente por el change tracker de Entity Framework, por lo que debemos recurrir a él para hacerlo.

Por ejemplo, el siguiente código muestra cómo acceder a las propiedades ocultas de una entidad obtenida previamente:
var friend = ctx.Friends.FirstOrDefault();
if(friend != null)
{
var name = friend.Name;
var updatedBy = ctx.Entry(friend).Property<string>("UpdatedBy").CurrentValue;
var updatedAt = ctx.Entry(friend).Property<DateTime>("UpdatedAt").CurrentValue;
Console.WriteLine($"{name} was updated by {updatedBy} at {updatedAt}");
}
De la misma forma, para actualizar el valor de las shadow properties, tendremos que esta la misma shadow property podríamos hacerlo como sigue:
var friend = ctx.Friends.FirstOrDefault();
if(friend != null)
{
ctx.Entry(friend).Property<string>("UpdatedBy").CurrentValue = "John Smith";
ctx.Entry(friend).Property<DateTime>("UpdatedAt").CurrentValue = DateTime.Now;
ctx.SaveChanges();
}

Incluir shadow properties en expresiones de consulta

Obviamente, el hecho de que no tengamos propiedades en la entidad para acceder a estos valores condiciona también la forma en que debemos utilizarlos desde LINQ en los predicados o criterios de consultas.

Pero de nuevo, tenemos una fórmula bastante sencilla para conseguirlo obteniendo una referencia válida para el árbol de expresión a través del método EF.Property(). En el siguiente ejemplo vemos cómo filtrar las entidades para obtener sólo aquellas actualizadas durante el último minuto:
var since = DateTime.Now.AddMinutes(-1);
var friendsRecentlyUpdated = ctx.Friends
.Where(b => EF.Property<DateTime>(b, "UpdatedAt") > since);
Publicado en Variable not found.

Picando Código: Humble Book Bundle: Libros de Linux por Wiley

$
0
0

Humble Bundle tiene un nuevo paquete de e-books sobre Linux, programación y varias certificaciones. Los ebooks están disponibles en PDF, ePUB y MOBI, por lo que pueden ser leídos en casi cualquier dispositivo. Como se acostumbra en los paquetes Humble Bundle, además de elegir el precio, podemos elegir dónde destinamos el dinero que pagamos, incluyendo una organización de beneficencia.

Humble Book Bundle: Linux by Wiley

Pagando USD 1 o más, el paquete incluye:
Linux Essentials, Ubuntu Linux Toolbox: 1000+ Commands for Power Users, Linux All-In-One For Dummies, Beginning Linux Programming.

Pagando USD 8, todos los anteriores más:
Linux Bible, Shell Scripting: Expert Recipes for Linux, Bash, and more, Linux Server Security: Hack and Defend,
CompTIA Linux+ and LPIC Practice Tests: Exams LX0-103/LPIC-1 101-400, LX0-104/LPIC-1 102-400, LPIC-2 201, and LPIC-2 202, Professional Linux Kernel Architecture

Finalmente, pagando USD 15 obtenemos el paquete completo con todos los anteriores y:
Linux Command Line and Shell Scripting Bible, CompTIA Linux+ Powered by Linux Professional Institute Study Guide: Exams LX0-103 and LX0-104, LPIC-1: Linux Professional Institute Certification Study Guide: Exams 101 and 102, LPIC-2: Linux Professional Institute Certification Study Guide: Exams 201 and 202, Red Hat Enterprise Linux 6 Administration: Real World Skills for Red Hat Administrators, Assembly Language Step-by-Step: Programming with Linux

Al momento de pagar, elegimos cómo repartir el dinero, con la opción de donar a la charidad “Freedom to Read”:
La Fundación Freedom to Read (FTRF) es una organización legal y educativa sin fines de lucro afiliada a la Asociación de Bibliotecas Americana. FTRF protege y defiende la Primera Enmienda de la Constitución y apoya el derecho de las bibliotecas de recolectara – y el acceso individual a – información.

La promoción termina el 25 de marzo, visita el Humble Book Bundle: Linux by Wiley

Picando Código: Awesome Rubies – Una colección de Rubies increíbles

$
0
0

Ruby

Awesome Rubies es una lista de “Rubys” (¿”Rubíes”?), o distintas implementaciones del lenguaje e información al respecto. La más conocida es MRI (Matz’s Ruby Interpreter), la implementación “de referencia” y probablemente la más usada. Actualmente se llama CRuby porque es un esfuerzo colaborativo y no “de Matz”, y existen además otras implementaciones como Rubinius, JRuby: Implementación de Ruby en la JVM y unas cuantas más.

Si has estado siguiendo Ruby, o has ido a conferencias recientemente, probablemente ya sepas de Ruby 3×3. Mi primer encuentro con el concepto “Ruby 3×3” fue en Euruko 2017. donde Matz abrió la conferencia con un Keynote sobre el futuro de Ruby. La idea es que la versión 3 de Ruby (esperada para el año que viene) va a ser 3 veces más rápida que la versión 2.0. Y con el trabajo que se viene haciendo para lograrlo, se vienen varias cosas interesantes en el lenguaje.

Siguiendo con Awesome Rubies, en la lista podemos ver las versiones principales (CRuby, JRuby, TruffleRuby), así como menores o próximas a salir (Topaz – Ruby en Python, GoRuby – Ruby en Go 🤦, etc) y versiones discontinuadas como IronRuby (.NET), MacRuby (Objective-C), y más. Desde ahí podemos acceder a más información sobre el recurso en particular. También encontraremos enlaces a investigaciones, papers, libros, benchmarks y otros recursos.

Algo que me resultó particularmente interesante fue ver en la lista dos lenguajes de programación que vengo siguiendo con interés desde hace un tiempo: Elixir y Crystal. No son exactamente versiones de Ruby, pero le veo sentido que estén listados como parte de la familia. Crystal tiene una sintaxis como Ruby, pero es estáticamente tipado y compila a código máquina (tengo un post sobre Crystal en borradores…). Elixir es un lenguaje de programación funcional que corre sobre la máquina virtual de Erlang, y su sintaxis está inspirada en la de Ruby.

También interesante ver en la lista Mirah, un lenguaje de programación que Charles Nutter presentó en Ruby Conf Uruguay 2010. Creo que la idea es algo así como una reimplementación de Java pero con la sintaxis de Ruby. Debería leer más…

Volviendo a Crystal y Elixir, obviamente no es coincidencia que venga estudiándolos y estén en la lista. Elixir es el más distinto de los dos, porque cambia el paradigma de programación mucho más radicalmente. Pero surgió de un miembro importante de la comunidad Ruby: José Valim. José parece seguir la filosofía de Ruby “Matz is nice and so we are nice”. Si bien Elixir todavía no ha agarrado mucha tracción como otros lenguajes o tecnologías que deben su éxito mayormente al apoyo de grandes corporaciones, es una buen lenguaje para aprender programación funcional. Y aunque sea lentamente, sigue creciendo, y Erlang no se va a ir a ningún lado por unos cuantos años. Por eso tiene sentido que varios rubistas “se hayan mudado” a Elixir o complementen su trabajo en Ruby con él.

Crystal es todavía bastante joven, pero también promete y mucho. Más adelante comentaré más al respecto.

Habiendo usado otros lenguajes, me sigue pareciendo importante la parte de la comunidad, abierta e inclusiva, además de “amable” como Matz. También que los lenguajes más allá de sus ventajas y decisiones técnicas, parecen seguir el paradigma -como Ruby- de ser diseñados para el programador y no para la computadora. O por lo menos así lo siento con Ruby, Elixir y eventualmente supongo que Crystal. Son lenguajes con ese “no sé qué” que por lo menos a mí me motiva aprender y disfruto usándolos. Así que no me parece una mala decisión de carrera especializarme en “Rubies”, e incluir Elixir y Crystal ahí.

Visiten Awesome Rubies para adentrarse más en este mundillo de rubíes.

Viewing all 2715 articles
Browse latest View live